public void AddPoint(Vector3Df point) { points.Add(point); // add front line Vertex3D v1front = new Vertex3D(point, new Vector3Df(0), new Color(0)); Vertex3D v2front = new Vertex3D((point - Center).Normalize() * height, new Vector3Df(0), FrontColor); vertFront.Add(v1front); vertFront.Add(v2front); // add back line Vertex3D v1back = v1front; Vertex3D v2back = new Vertex3D(v2front); v2back.Color = BackColor; vertBack.Add(v1back); vertBack.Add(v2back); // add connection line if possible (front and back) if (vertFront.Count >= 4) { vertFront.Add(vertFront.Get(vertFront.Count - 3)); vertFront.Add(v2front); vertBack.Add(vertBack.Get(vertBack.Count - 3)); vertBack.Add(v2back); } // update indices "used" count indBoth.SetCount(vertFront.Count); }
public PrimitiveMesh(Device device, Mesh baseMesh) { BaseMesh = baseMesh; var vert3d = new Vertex3D[baseMesh.Vertices.Length]; for (var i = 0; i < vert3d.Length; ++i) vert3d[i] = new Vertex3D(baseMesh.Vertices[i]); IndexBuffer = Buffer.Create<ushort>(device, BindFlags.IndexBuffer, baseMesh.Indices); VertexBuffer = Buffer.Create<Vertex3D>(device, BindFlags.VertexBuffer, vert3d); VertexBufferBinding = new VertexBufferBinding(VertexBuffer, VertexBuffer.Description.SizeInBytes / baseMesh.Vertices.Length, 0); }
// Runs once before first turn internal static void ReadStatic() { // Read the list of vertex locations. int n = int.Parse(IO.ReadLine()); // List of points in the map. vertexList = new Vertex3D[n]; // vertexColors = new int[n]; for (int i = 0; i < n; i++) { string[] tokens = IO.ReadLine().Split(); vertexList[i] = new Vertex3D(i,int.Parse(tokens[0]), int.Parse(tokens[1]), int.Parse(tokens[2])); // vertexList[i].adjacentColorMap = 0; } //Console.Error.Write("VertexColors: "); //foreach (int x in vertexColors) Console.Error.Write(" " + x.ToString()); //Console.Error.WriteLine(); // Read the list of region outlines. n = int.Parse(IO.ReadLine()); // List of regions in the map regionList = new Region[n]; for (int regionNumber = 0; regionNumber < n; regionNumber++) { string[] tokens = IO.ReadLine().Split(); int vertexCount = int.Parse(tokens[0]); regionList[regionNumber] = new Region(regionNumber); regionList[regionNumber].vertexList = new int[vertexCount]; for (int rVertextNumber = 0; rVertextNumber < vertexCount; rVertextNumber++) { int vertexNumber = int.Parse(tokens[rVertextNumber + 1]); regionList[regionNumber].vertexList[rVertextNumber] = vertexNumber; vertexList[vertexNumber].adjacentRegions.Add(regionNumber); } } // List of current region colors, pusher and marker locations. // These are updated on every turn snapshot from the game. //regionColors = new int[regionList.Length]; pList = new Pusher[2 * PCOUNT]; for (int i = 0; i < pList.Length; i++) pList[i] = new Pusher(i); mList = new Marker[MCOUNT]; for (int i = 0; i < mList.Length; i++) mList[i] = new Marker(i); }
public LensflareSceneNode(SceneNode parent, SceneManager mgr, int id) : base(parent, mgr, id) { draw_flare = true; ign_geom = false; smgr = mgr; indices = new ushort[6]; indices[0] = 0; indices[1] = 2; indices[2] = 1; indices[3] = 0; indices[4] = 3; indices[5] = 2; vertices = new Vertex3D[4]; for (int i = 0; i < 4; i++) { vertices[i] = new Vertex3D(); } vertices[0].TCoords = Vector2D.From(0.0f, 1.0f); vertices[0].Color = Color.White; vertices[1].TCoords = Vector2D.From(0.0f, 0.0f); vertices[1].Color = Color.White; vertices[2].TCoords = Vector2D.From(1.0f, 0.0f); vertices[2].Color = Color.White; vertices[3].TCoords = Vector2D.From(1.0f, 1.0f); vertices[3].Color = Color.White; material = new Material(); material.Lighting = false; material.MaterialType = MaterialType.TransparentAddColor; material.ZBuffer = 0; material.ZWriteEnable = false; bbox = new Box3D(); bbox.MinEdge = Vector3D.From(-2, -2, -2); bbox.MaxEdge = Vector3D.From(2, 2, 2); }
public MoveMarkerToVertexGoal(Pusher inMe, int turn) : base(inMe,turn) { me = inMe; //IO.ErrorWrite("MoveMarkerToVertexGoal P#" + me.num.ToString()); // Find a marker to move myMarker = Map.mList[GoalUtility.FindNearest(me.pos, Map.RED)]; myMarker.beingUsedBy = this; //IO.ErrorWrite(myMarker.Short()); // Find a place to push it. targetVertextSeq = GoalUtility.PickAVertex(myMarker.pos); targetVertex = Map.vertexList[targetVertextSeq]; //IO.ErrorWrite(targetVertex.Short2D()); targetVertex.target = true; // we should fix this make me the user. dest = new Vector2D(targetVertex.x, targetVertex.y); //IO.ErrorWriteLine(""); }
public CSampleSceneNode(SceneNode parent, SceneManager smgr, int id) : base(parent, smgr, id) { this.OnRegisterSceneNode += new RegisterSceneNodeEventHandler(CSampleSceneNode_OnRegisterSceneNode); this.OnRender += new RenderEventHandler(CSampleSceneNode_OnRender); this.OnGetBoundingBox += new GetBoundingBoxEventHandler(CSampleSceneNode_OnGetBoundingBox); this.OnGetMaterialCount += new GetMaterialCountEventHandler(CSampleSceneNode_OnGetMaterialCount); this.OnGetMaterial += new GetMaterialEventHandler(CSampleSceneNode_OnGetMaterial); material.Wireframe = false; material.Lighting = false; vertices = new Vertex3D[4]; vertices[0] = new Vertex3D(0, 0, 10, 1, 1, 0, new Color(0, 255, 255), 0, 1); vertices[1] = new Vertex3D(10, 0, -10, 1, 0, 0, new Color(255, 0, 255), 1, 1); vertices[2] = new Vertex3D(0, 20, 0, 0, 1, 1, new Color(255, 255, 0), 1, 0); vertices[3] = new Vertex3D(-10, 0, -10, 0, 0, 1, new Color(0, 255, 0), 0, 0); bbox.Set(vertices[0].Position); for (int i = 1; i < vertices.Length; i++) bbox.AddInternalPoint(vertices[i].Position); }
public HitPoint(Vertex3D p, ItemType itemType) : base(itemType) { P = p; }
private void Run() { // Read the static parts of the map. // Read the list of vertex locations. int n = int.Parse( Console.ReadLine() ); // List of points in the map. Vertex3D[] vertexList = new Vertex3D [ n ]; for ( int i = 0; i < n; i++ ) { string[] tokens = Console.ReadLine().Split(); vertexList[ i ] = new Vertex3D( int.Parse( tokens[ 0 ] ), int.Parse( tokens[ 1 ] ), int.Parse( tokens[ 2 ] ) ); } // Read the list of region outlines. n = int.Parse( Console.ReadLine() ); // List of regions in the map int[][] regionList = new int [ n ] []; for ( int i = 0; i < n; i++ ) { string[] tokens = Console.ReadLine().Split(); int m = int.Parse( tokens[ 0 ] ); regionList[ i ] = new int [ m ]; for ( int j = 0; j < m; j++ ) regionList[ i ][ j ] = int.Parse( tokens[ j + 1 ] ); } // List of current region colors, pusher and marker locations. // These are updated on every turn snapshot from the game. int[] regionColors = new int [ regionList.Length ]; Pusher[] pList = new Pusher [ 2 * PCOUNT ]; for ( int i = 0; i < pList.Length; i++ ) pList[ i ] = new Pusher(); Marker[] mList = new Marker [ MCOUNT ]; for ( int i = 0; i < mList.Length; i++ ) mList[ i ] = new Marker(); int turnNum = int.Parse( Console.ReadLine() ); while ( turnNum >= 0 ) { string[] tokens = Console.ReadLine().Split(); score[ RED ] = int.Parse( tokens[ 0 ] ); score[ BLUE ] = int.Parse( tokens[ 1 ] ); // Read all the region colors. tokens = Console.ReadLine().Split(); n = int.Parse( tokens[ 0 ] ); for ( int i = 0; i < regionList.Length; i++ ) regionColors[ i ] = int.Parse( tokens[ i + 1 ] ); // Read all the pusher locations. n = int.Parse( Console.ReadLine() ); for ( int i = 0; i < pList.Length; i++ ) { tokens = Console.ReadLine().Split(); pList[ i ].pos.x = double.Parse( tokens[ 0 ] ); pList[ i ].pos.y = double.Parse( tokens[ 1 ] ); pList[ i ].vel.x = double.Parse( tokens[ 2 ] ); pList[ i ].vel.y = double.Parse( tokens[ 3 ] ); } // Read all the marker locations. n = int.Parse( Console.ReadLine() ); for ( int i = 0; i < n; i++ ) { tokens = Console.ReadLine().Split(); mList[ i ].pos.x = double.Parse( tokens[ 0 ] ); mList[ i ].pos.y = double.Parse( tokens[ 1 ] ); mList[ i ].vel.x = double.Parse( tokens[ 2 ] ); mList[ i ].vel.y = double.Parse( tokens[ 3 ] ); mList[ i ].color = int.Parse( tokens[ 4 ] ); } // Compute a bit vector for the region colors incident on each // vertex. int[] vertexColors = new int [ vertexList.Length ]; for ( int i = 0; i < regionList.Length; i++ ) for ( int j = 0; j < regionList[ i ].Length; j++ ) vertexColors[ regionList[ i ][ j ] ] |= ( 1 << regionColors[ i ] ); // Candidate vertices for putting a marker on, vertices that have // some red but are not all red. List< int > candidates = new List< int >(); for ( int i = 0; i < vertexList.Length; i++ ) if ( ( vertexColors[ i ] & 0x1 ) == 1 && vertexColors[ i ] != 1 ) candidates.Add( i ); // Choose a next action for each pusher, each pusher is responsible // for the marker with the same index. for ( int pdex = 0; pdex < PCOUNT; pdex++ ) { Pusher p = pList[ pdex ]; // See how long this pusher has been doing its job. if ( p.busy ) { // Go to idle if we work to long on the same job. p.jobTime++; if ( p.jobTime >= 60 ) p.busy = false; } // If we lose our marker, then just sit idle. if ( mList[ pdex ].color != RED ) { p.busy = false; } // Otherwise, try to find a new place to push our marker. if ( mList[ pdex ].color == RED && !p.busy ) { if ( candidates.Count > 0 ) { int choice = rnd.Next( candidates.Count ); p.targetVertex = candidates[ choice ]; candidates.RemoveAt( choice ); p.busy = true; } } // Choose a move direction in support of our current goal. if ( p.busy ) { // Get behind our marker and push it toward its destination. Vertex3D v = vertexList[ p.targetVertex ]; Vector2D dest = new Vector2D( v.x, v.y ); if ( MoveAround( p, mList[ pdex ], dest ) ) { Vector2D mToD = ( dest - mList[ pdex ].pos ).Norm(); MoveTo( p, mList[ pdex ].pos - mToD ); } } else Console.Write( "0.0 0.0" ); // Print a space or a newline depending on whether we're at // the last pusher. if ( pdex + 1 < PCOUNT ) Console.Write( " " ); else Console.WriteLine(); } turnNum = int.Parse( Console.ReadLine() ); } }
private void meshGeneratorThread_generateMesh(int layerIndex) { GridLayer l = layers[layerIndex]; if (l.Mesh != null) l.Mesh.Drop(); l.Mesh = Mesh.Create(); if (gridCubeCount > 0) { Vertex3D[] cubeVerts = null; ushort[] cubeInds = null; int cubeIndex = maxCubesPerBuffer; // this way we force buffers to be recreated at next new cube int totalCubesAdded = 0; float baseX = -(CubeSize * GridDim) / 2; float baseZ = -(CubeSize * GridDim) / 2; for (int i = 0; i < GridDim; i++) { for (int j = 0; j < GridDim; j++) { if (grid[i, j] == 0) continue; // check if current buffer is out of room, if so make a mesh buffer and attach it to the gridMesh and init next cubeVerts&Inds if (cubeIndex == maxCubesPerBuffer) { if (cubeVerts != null && cubeInds != null) { MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); b.Append(cubeVerts, cubeInds); l.Mesh.AddMeshBuffer(b); b.Drop(); totalCubesAdded += cubeIndex; } int cubeCount = gridCubeCount - totalCubesAdded; if (cubeCount > maxCubesPerBuffer) cubeCount = maxCubesPerBuffer; cubeIndex = 0; cubeVerts = new Vertex3D[cubeCount * 8]; // 8 verts per cube cubeInds = new ushort[cubeCount * 3 * 2 * 6]; // 3 indices per triangle; 2 triangles per face; 6 faces per cube } // build the cube and add it // note: we build 8 vertices cube because we don't need to texture it; if you want to change that (to use texture instead of vertex colors) - you need to build 12 vertices cube and initialize UV coords float x = baseX + i * CubeSize; float y = 0; float z = baseZ + j * CubeSize; int iv = cubeIndex * 8; cubeVerts[iv + 0] = new Vertex3D(x, y, z); cubeVerts[iv + 1] = new Vertex3D(x + CubeSize, y, z); cubeVerts[iv + 2] = new Vertex3D(x + CubeSize, y + CubeSize, z); cubeVerts[iv + 3] = new Vertex3D(x, y + CubeSize, z); cubeVerts[iv + 4] = new Vertex3D(x, y, z + CubeSize); cubeVerts[iv + 5] = new Vertex3D(x + CubeSize, y, z + CubeSize); cubeVerts[iv + 6] = new Vertex3D(x + CubeSize, y + CubeSize, z + CubeSize); cubeVerts[iv + 7] = new Vertex3D(x, y + CubeSize, z + CubeSize); int ii = cubeIndex * 3 * 2 * 6; // top cubeInds[ii + 0] = (ushort)(iv + 3); cubeInds[ii + 1] = (ushort)(iv + 7); cubeInds[ii + 2] = (ushort)(iv + 6); cubeInds[ii + 3] = (ushort)(iv + 3); cubeInds[ii + 4] = (ushort)(iv + 6); cubeInds[ii + 5] = (ushort)(iv + 2); // front cubeInds[ii + 6] = (ushort)(iv + 0); cubeInds[ii + 7] = (ushort)(iv + 3); cubeInds[ii + 8] = (ushort)(iv + 2); cubeInds[ii + 9] = (ushort)(iv + 0); cubeInds[ii + 10] = (ushort)(iv + 2); cubeInds[ii + 11] = (ushort)(iv + 1); // right cubeInds[ii + 12] = (ushort)(iv + 1); cubeInds[ii + 13] = (ushort)(iv + 2); cubeInds[ii + 14] = (ushort)(iv + 6); cubeInds[ii + 15] = (ushort)(iv + 1); cubeInds[ii + 16] = (ushort)(iv + 6); cubeInds[ii + 17] = (ushort)(iv + 5); // left cubeInds[ii + 18] = (ushort)(iv + 0); cubeInds[ii + 19] = (ushort)(iv + 4); cubeInds[ii + 20] = (ushort)(iv + 7); cubeInds[ii + 21] = (ushort)(iv + 0); cubeInds[ii + 22] = (ushort)(iv + 7); cubeInds[ii + 23] = (ushort)(iv + 3); // back cubeInds[ii + 24] = (ushort)(iv + 4); cubeInds[ii + 25] = (ushort)(iv + 5); cubeInds[ii + 26] = (ushort)(iv + 6); cubeInds[ii + 27] = (ushort)(iv + 4); cubeInds[ii + 28] = (ushort)(iv + 6); cubeInds[ii + 29] = (ushort)(iv + 7); // bottom cubeInds[ii + 30] = (ushort)(iv + 0); cubeInds[ii + 31] = (ushort)(iv + 1); cubeInds[ii + 32] = (ushort)(iv + 5); cubeInds[ii + 33] = (ushort)(iv + 0); cubeInds[ii + 34] = (ushort)(iv + 5); cubeInds[ii + 35] = (ushort)(iv + 4); cubeIndex++; } } if (cubeIndex > 0) { MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); b.Append(cubeVerts, cubeInds); l.Mesh.AddMeshBuffer(b); b.Drop(); } device.SceneManager.MeshManipulator.SetVertexColors(l.Mesh, cubeColor); } l.Transform.Rotation = new Vector3Df(gridGeneration * 0.93f, gridGeneration * 0.81f, gridGeneration * 0.69f); l.Generation = gridGeneration; l.CubeCount = gridCubeCount; l.MeshIsReady = true; }
private void RenderTriangles() { for (int iTriangle = 0; iTriangle < triangleIndicesList.Count; iTriangle++) { TriangleIndices triangleIndices = triangleIndicesList[iTriangle]; Vertex3D vertex1 = vertexList[triangleIndices.Index1]; Vertex3D vertex2 = vertexList[triangleIndices.Index2]; Vertex3D vertex3 = vertexList[triangleIndices.Index3]; Vector3D normal1 = vertex1.NormalVector; Vector3D normal2 = vertex2.NormalVector; Vector3D normal3 = vertex3.NormalVector; Vector3D triangeNormal = triangleNormalVectorList[iTriangle]; GL.Begin(PrimitiveType.Triangles); if (textureID > 0) { GL.BindTexture(TextureTarget.Texture2D, textureID); } if (shadingModel == ShadingModel.Flat) { GL.Normal3(triangeNormal.X, triangeNormal.Z, -triangeNormal.Y); } if (shadingModel == ShadingModel.Smooth) { GL.Normal3(normal1.X, normal1.Z, -normal1.Y); } if (!useLight) { GL.Color4(vertex1.Color.R, vertex1.Color.G, vertex1.Color.B, vertex1.Color.A); } if (textureID > 0) { GL.TexCoord2(vertex1.TextureCoordinates.X, vertex1.TextureCoordinates.Y); } GL.Vertex3(vertex1.Position.X, vertex1.Position.Z, -vertex1.Position.Y); if (shadingModel == ShadingModel.Smooth) { GL.Normal3(normal2.X, normal2.Z, -normal2.Y); } if (!useLight) { GL.Color4(vertex2.Color.R, vertex2.Color.G, vertex2.Color.B, vertex2.Color.A); } if (textureID > 0) { if (vertex2.TextureCoordinates.X < vertex1.TextureCoordinates.X) { GL.TexCoord2(vertex2.TextureCoordinates.X + 1, vertex2.TextureCoordinates.Y); } else { GL.TexCoord2(vertex2.TextureCoordinates.X, vertex2.TextureCoordinates.Y); } } GL.Vertex3(vertex2.Position.X, vertex2.Position.Z, -vertex2.Position.Y); if (shadingModel == ShadingModel.Smooth) { GL.Normal3(normal3.X, normal3.Z, -normal3.Y); } if (!useLight) { GL.Color4(vertex3.Color.R, vertex3.Color.G, vertex3.Color.B, vertex3.Color.A); } if (textureID > 0) { if (vertex3.TextureCoordinates.X < vertex1.TextureCoordinates.X) { GL.TexCoord2(vertex3.TextureCoordinates.X + 1, vertex3.TextureCoordinates.Y); } else { GL.TexCoord2(vertex3.TextureCoordinates.X, vertex3.TextureCoordinates.Y); } } GL.Vertex3(vertex3.Position.X, vertex3.Position.Z, -vertex3.Position.Y); GL.End(); } }
private HitObject[] GenerateHitTargetHits(Table.Table table, IItem item) { var addedEdges = new EdgeSet(); var hitMesh = _meshGenerator.GetRenderObjects(table, Origin.Original, false).RenderObjects[0].Mesh; var hitObjects = GenerateCollidables(hitMesh, addedEdges, _data.IsLegacy, table, item).ToList(); var tempMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(_data.RotZ)); var fullMatrix = new Matrix3D().Multiply(tempMatrix); if (!_data.IsLegacy) { var rgv3D = new Vertex3D[DropTargetHitPlaneVertices.Length]; var hitShapeOffset = 0.18f; if (_data.TargetType == TargetType.DropTargetBeveled) { hitShapeOffset = 0.25f; } if (_data.TargetType == TargetType.DropTargetFlatSimple) { hitShapeOffset = 0.13f; } // now create a special hit shape with hit event enabled to prevent a hit event when hit from behind for (var i = 0; i < DropTargetHitPlaneVertices.Length; i++) { var dropTargetHitPlaneVertex = DropTargetHitPlaneVertices[i]; var vert = new Vertex3D( dropTargetHitPlaneVertex.X, dropTargetHitPlaneVertex.Y + hitShapeOffset, dropTargetHitPlaneVertex.Z ); vert.X *= _data.Size.X; vert.Y *= _data.Size.Y; vert.Z *= _data.Size.Z; vert.MultiplyMatrix(fullMatrix); rgv3D[i] = new Vertex3D( vert.X + _data.Position.X, vert.Y + _data.Position.Y, vert.Z * table.GetScaleZ() + _data.Position.Z + table.TableHeight ); } for (var i = 0; i < DropTargetHitPlaneIndices.Length; i += 3) { var i0 = DropTargetHitPlaneIndices[i]; var i1 = DropTargetHitPlaneIndices[i + 1]; var i2 = DropTargetHitPlaneIndices[i + 2]; // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order var rgv3D2 = new[] { rgv3D[i0], rgv3D[i2], rgv3D[i1] }; hitObjects.Add(SetupHitObject(new HitTriangle(rgv3D2, ItemType.HitTarget, item), true, table)); hitObjects.AddRange(addedEdges.AddHitEdge(i0, i1, rgv3D2[0], rgv3D2[2], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table))); hitObjects.AddRange(addedEdges.AddHitEdge(i1, i2, rgv3D2[2], rgv3D2[1], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table))); hitObjects.AddRange(addedEdges.AddHitEdge(i2, i0, rgv3D2[1], rgv3D2[0], ItemType.HitTarget, item).Select(obj => SetupHitObject(obj, true, table))); } // add collision vertices for (var i = 0; i < DropTargetHitPlaneVertices.Length; ++i) { hitObjects.Add(SetupHitObject(new HitPoint(rgv3D[i], ItemType.HitTarget, item), true, table)); } } return(hitObjects.ToArray()); }
public static float EuclidianDistance(Vertex3D v1, Vertex3D v2) { return((float)Math.Sqrt(Math.Pow(v1.x - v2.x, 2.0) + Math.Pow(v1.y - v2.y, 2.0) + Math.Pow(v1.z - v2.z, 2.0))); }
/*private void DoParticleSystem(uint time) { }*/ private void ReallocateBuffers() { if (Particles.Length * 4 > Vertices.Length || Particles.Length * 6 > Indices.Length) { int oldSize = Vertices.Length; ArrayList newvert = new ArrayList(); int i; newvert.AddRange(Vertices); for (i = oldSize; i < (Particles.Length * 4); i++) { Vertex3D temp = new Vertex3D(); temp.Normal = new Vector3D(0, 1, 0); newvert.Add(temp); } Vertices = (Vertex3D[])newvert.ToArray(typeof(Vertex3D)); newvert.Clear(); int oldIdxSize = Indices.Length; int oldvertices = oldSize; newvert.AddRange(Indices); for (i = oldIdxSize; i < (Particles.Length * 12); i += 12) { newvert.Add((ushort)(0 + oldvertices)); newvert.Add((ushort)(2 + oldvertices)); newvert.Add((ushort)(1 + oldvertices)); newvert.Add((ushort)(0 + oldvertices)); newvert.Add((ushort)(3 + oldvertices)); newvert.Add((ushort)(2 + oldvertices)); newvert.Add((ushort)(1 + oldvertices)); newvert.Add((ushort)(2 + oldvertices)); newvert.Add((ushort)(0 + oldvertices)); newvert.Add((ushort)(2 + oldvertices)); newvert.Add((ushort)(3 + oldvertices)); newvert.Add((ushort)(0 + oldvertices)); oldvertices += 4; } Indices = (ushort[])newvert.ToArray(typeof(ushort)); newvert.Clear(); } }
private Vertex3D[] GenerateSphere(Vector3 position, float width, float height, float depth, float radians, uint numHorizontalDivisions, uint numVerticalDivisions) { /* * Coordinate System Here is RHS, Y Vertical. * V = Vertical Angle [inclination] .. (around horizontal X axis, 0 is pointing straight up) * H = Horizontal Angle [azimuth] .. (around vertical Y axis, positive is clockwise from positive x direction towards positive z) * * z = R.Sin(V).Sin(H) * x = R.Sin(V).Cos(H) * y = R.Cos(V) */ var verts = new Vertex3D[numHorizontalDivisions * numVerticalDivisions]; var divFracH = 1.0f / (1.0f * (numHorizontalDivisions - 1)); var divFracV = 1.0f / (1.0f * (numVerticalDivisions - 1)); var hw = 0.5f * width; var hh = 0.5f * height; var hd = 0.5f * depth; float fracX, fracY; for (var ny = 0; ny < numVerticalDivisions; ny++) { fracY = ny * divFracV; for (var nx = 0; nx < numHorizontalDivisions; nx++) { fracX = nx * divFracH; var horizontalAngle = (-0.5f + (-fracX * 2.0f)) * (float)Math.PI; //Rotate 90 degress CCW (negative direction) to pointing along negative z. then wrap around in CCW direction from there var verticalAngle = fracY * (float)Math.PI; var H = horizontalAngle; var V = verticalAngle; var sinH = (float)Math.Sin(H); var cosH = (float)Math.Cos(H); var sinV = (float)Math.Sin(V); var cosV = (float)Math.Cos(V); var x = sinV * cosH; var y = cosV; var z = sinV * sinH; var index = (numHorizontalDivisions * ny) + nx; var positionScaled = new Vector3(x * hw, y * hh, z * hd); var positionRotated = Vector3.Transform(positionScaled, Matrix4x4.CreateRotationY(-radians)); verts[index] = new Vertex3D { Position = positionRotated + position, TexCoord = new Vector2(fracX, fracY), }; } } /*Calculate Normals * * Given the user has the option to distort the sphere by arbitary width, height and depth * The per vertex normals are not guaranteed to be just normalised vectors of it's position * (as is the case for a uniform sphere of constant radius around the origin) * We therefore need to employ the standard vertex normal calculation technique: * * Sum all Face Normals of the faces surrounding each vertex and normalise * * Note: although in this mesh each face will be the same size, this technique does * account for the different weighting that differently sized faces should have on a vertex * normal. This is because a face normal is calculated using the cross product of two sides * of a triangle. The length of the resulting vector is proportional the area of the face * and it's direction is naturally in the direction of the face normal * * Finally, care must be taken to ensure the face-out normals are calculated rather than face-in. * * There are a select number of normals we already know. namely that those in the top and bottom * Vertical row are +/- UnitY */ for (var ny = 0; ny < numVerticalDivisions; ny++) { for (var nx = 0; nx < numHorizontalDivisions; nx++) { var index = (numHorizontalDivisions * ny) + nx; if (ny == 0) { //Top row points straight up verts[index].Normal = Vector3.UnitY; continue; } if (ny == numVerticalDivisions - 1) { //Bottom row points straight down verts[index].Normal = -Vector3.UnitY; continue; } //Vector3.Cross -> Positive Unit X crossed with Positive Unit Y == Unit Positive Z //To get an outward facing normal, I will use those vectors along azimuth/inclination //directions (psuedo vertical and horizontal lines in the reference frame of the vertex) //and i will each one with the next in the counter clockwise direction if facing straight on /* * x and Letter = Vertex * * x x /C\ x x * / | \ * x D---A---B x \ | / \ x x \E/ x x \ \ \ Vertex Normal of A == Normalise(ABxAC + ACxAD + ADxAE + AExAB) */ var indexMinusOne = index - 1; if (nx == 0) { indexMinusOne = (numHorizontalDivisions * (ny + 1)) - 2; //-2 not -1 NOTE } var indexPlusOne = index + 1; if (nx == numHorizontalDivisions - 1) { indexPlusOne -= numHorizontalDivisions; indexPlusOne++; //Adding an extra 1 NOTE } //Why NOTE.. because the edge azimuth / horizontal points actually overlap at 0 and max azimuth. wrap points are not shared //There is a seem at the back with overlapping points var A = verts[index].Position; var B = verts[indexPlusOne].Position; var C = verts[index - numHorizontalDivisions].Position; var D = verts[indexMinusOne].Position; var E = verts[index + numHorizontalDivisions].Position; var sum = Vector3.Cross(B - A, C - A) + Vector3.Cross(C - A, D - A) + Vector3.Cross(D - A, E - A) + Vector3.Cross(E - A, B - A); verts[index].Normal = Vector3.Normalize(sum); } } return(_vertexGridToTriangleListTool.Convert(numHorizontalDivisions, numVerticalDivisions, verts)); }
private void GetRelativeVelocity(Vertex3D normal, Ball.Ball ball, Vertex3D vRel, Vertex3D rB, Vertex3D rF) { rB.Set(normal.Clone().MultiplyScalar(-ball.Data.Radius)); var hitPos = ball.State.Pos.Clone().Add(rB); var cF = new Vertex3D( _mover.HitCircleBase.Center.X, _mover.HitCircleBase.Center.Y, ball.State.Pos.Z // make sure collision happens in same z plane where ball is ); rF.Set(hitPos.Clone().Sub(cF)); // displacement relative to flipper center var vB = ball.Hit.SurfaceVelocity(rB); var vF = _mover.SurfaceVelocity(rF); vRel.Set(vB.Clone().Sub(vF)); }
public Ball(BallData data, Vertex3D initialVelocity, Table.Table table) { Data = data; }
public override void Collide(CollisionEvent coll, PlayerPhysics physics) { var ball = coll.Ball; var normal = coll.HitNormal; var vRel = new Vertex3D(); var rB = new Vertex3D(); var rF = new Vertex3D(); GetRelativeVelocity(normal, ball, vRel, rB, rF); var bnv = normal.Dot(vRel); // relative normal velocity if (bnv >= -PhysicsConstants.LowNormVel) { // nearly receding ... make sure of conditions if (bnv > PhysicsConstants.LowNormVel) { // otherwise if clearly approaching .. process the collision // is this velocity clearly receding (i.E must > a minimum) return; } //#ifdef PhysicsConstants.EMBEDDED if (coll.HitDistance < -PhysicsConstants.Embedded) { bnv = -PhysicsConstants.EmbedShot; // has ball become embedded???, give it a kick } else { return; } //#endif } //#ifdef PhysicsConstants.DISP_GAIN // correct displacements, mostly from low velocity blindness, an alternative to true acceleration processing var hitDist = -PhysicsConstants.DispGain * coll.HitDistance; // distance found in hit detection if (hitDist > 1.0e-4) { if (hitDist > PhysicsConstants.DispLimit) { hitDist = PhysicsConstants.DispLimit; // crossing ramps, delta noise } // push along norm, back to free area; use the norm, but is not correct ball.State.Pos.Add(coll.HitNormal.Clone().MultiplyScalar(hitDist)); } //#endif // angular response to impulse in normal direction var angResp = Vertex3D.CrossProduct(rF, normal); /* * Check if flipper is in contact with its stopper and the collision impulse * would push it beyond the stopper. In that case, don"t allow any transfer * of kinetic energy from ball to flipper. This avoids overly dead bounces * in that case. */ var angImp = -angResp.Z; // minus because impulse will apply in -normal direction var flipperResponseScaling = 1.0f; if (_mover.IsInContact && _mover.ContactTorque * angImp >= 0f) { // if impulse pushes against stopper, allow no loss of kinetic energy to flipper // (still allow flipper recoil, but a diminished amount) angResp.SetZero(); flipperResponseScaling = 0.5f; } /* * Rubber has a coefficient of restitution which decreases with the impact velocity. * We use a heuristic model which decreases the COR according to a falloff parameter: * 0 = no falloff, 1 = half the COR at 1 m/s (18.53 speed units) */ var epsilon = Functions.ElasticityWithFalloff(Elasticity, ElasticityFalloff, bnv); var pv1 = angResp.Clone().DivideScalar(_mover.Inertia); var impulse = -(1.0f + epsilon) * bnv / (ball.Hit.InvMass + normal.Dot(Vertex3D.CrossProduct(pv1, rF))); var flipperImp = normal.Clone().MultiplyScalar(-(impulse * flipperResponseScaling)); var rotI = Vertex3D.CrossProduct(rF, flipperImp); if (_mover.IsInContact) { if (rotI.Z * _mover.ContactTorque < 0) { // pushing against the solenoid? // Get a bound on the time the flipper needs to return to static conditions. // If it"s too short, we treat the flipper as static during the whole collision. var recoilTime = -rotI.Z / _mover.ContactTorque; // time flipper needs to eliminate this impulse, in 10ms // Check ball normal velocity after collision. If the ball rebounded // off the flipper, we need to make sure it does so with full // reflection, i.E., treat the flipper as static, otherwise // we get overly dead bounces. var bnvAfter = bnv + impulse * ball.Hit.InvMass; if (recoilTime <= 0.5 || bnvAfter > 0) { // treat flipper as static for this impact impulse = -(1.0f + epsilon) * bnv * ball.Data.Mass; flipperImp.SetZero(); rotI.SetZero(); } } } ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(impulse * ball.Hit.InvMass)); // new velocity for ball after impact _mover.ApplyImpulse(rotI); // apply friction var tangent = vRel.Clone().Sub(normal.Clone().MultiplyScalar(vRel.Dot(normal))); // calc the tangential velocity var tangentSpSq = tangent.LengthSq(); if (tangentSpSq > 1e-6) { tangent.DivideScalar(MathF.Sqrt(tangentSpSq)); // normalize to get tangent direction var vt = vRel.Dot(tangent); // get speed in tangential direction // compute friction impulse var crossB = Vertex3D.CrossProduct(rB, tangent); var pv12 = crossB.Clone().DivideScalar(ball.Hit.Inertia); var kt = ball.Hit.InvMass + tangent.Dot(Vertex3D.CrossProduct(pv12, rB)); var crossF = Vertex3D.CrossProduct(rF, tangent); var pv13 = crossF.Clone().DivideScalar(_mover.Inertia); kt += tangent.Dot(Vertex3D.CrossProduct(pv13, rF)); // flipper only has angular response // friction impulse can't be greater than coefficient of friction times collision impulse (Coulomb friction cone) var maxFriction = Friction * impulse; var jt = Functions.Clamp(-vt / kt, -maxFriction, maxFriction); ball.Hit.ApplySurfaceImpulse( crossB.Clone().MultiplyScalar(jt), tangent.Clone().MultiplyScalar(jt) ); _mover.ApplyImpulse(crossF.Clone().MultiplyScalar(-jt)); } if (bnv < -0.25 && physics.TimeMsec - _lastHitTime > 250) { // limit rate to 250 milliseconds per event var flipperHit = coll.HitMomentBit ? -1.0 : -bnv; // move event processing to end of collision handler... if (flipperHit < 0) { _events.FireGroupEvent(EventId.HitEventsHit); // simple hit event } else { // collision velocity (normal to face) _events.FireVoidEventParam(EventId.FlipperEventsCollide, flipperHit); } } _lastHitTime = physics.TimeMsec; // keep resetting until idle for 250 milliseconds }
public override void Contact(CollisionEvent coll, float dTime, PlayerPhysics physics) { var ball = coll.Ball; var normal = coll.HitNormal; //#ifdef PhysicsConstants.EMBEDDED if (coll.HitDistance < -PhysicsConstants.Embedded) { // magic to avoid balls being pushed by each other through resting flippers! ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(0.1f)); } //#endif var vRel = new Vertex3D(); var rB = new Vertex3D(); var rF = new Vertex3D(); GetRelativeVelocity(normal, ball, vRel, rB, rF); // this should be zero, but only up to +/- C_CONTACTVEL var normVel = vRel.Dot(normal); // If some collision has changed the ball's velocity, we may not have to do anything. if (normVel <= PhysicsConstants.ContactVel) { // compute accelerations of point on ball and flipper var aB = ball.Hit.SurfaceAcceleration(rB, physics); var aF = _mover.SurfaceAcceleration(rF); var aRel = aB.Clone().Sub(aF); // time derivative of the normal vector var normalDeriv = Vertex3D.CrossZ(_mover.AngleSpeed, normal); // relative acceleration in the normal direction var normAcc = aRel.Dot(normal) + 2.0f * normalDeriv.Dot(vRel); if (normAcc >= 0) { return; // objects accelerating away from each other, nothing to do } // hypothetical accelerations arising from a unit contact force in normal direction var aBc = normal.Clone().MultiplyScalar(ball.Hit.InvMass); var pv2 = normal.Clone().MultiplyScalar(-1); var cross = Vertex3D.CrossProduct(rF, pv2); var pv1 = cross.Clone().DivideScalar(_mover.Inertia); var aFc = Vertex3D.CrossProduct(pv1, rF); var contactForceAcc = normal.Dot(aBc.Clone().Sub(aFc)); // find j >= 0 such that normAcc + j * contactForceAcc >= 0 (bodies should not accelerate towards each other) var j = -normAcc / contactForceAcc; // kill any existing normal velocity ball.Hit.Vel.Add(normal.Clone().MultiplyScalar(j * dTime * ball.Hit.InvMass - coll.HitOrgNormalVelocity)); _mover.ApplyImpulse(cross.Clone().MultiplyScalar(j * dTime)); // apply friction // first check for slippage var slip = vRel.Clone().Sub(normal.Clone().MultiplyScalar(normVel)); // calc the tangential slip velocity var maxFriction = j * Friction; var slipSpeed = slip.Length(); Vertex3D slipDir; Vertex3D crossF; float numer; float denomF; Vertex3D pv13; if (slipSpeed < PhysicsConstants.Precision) { // slip speed zero - static friction case var slipAcc = aRel.Clone().Sub(normal.Clone().MultiplyScalar(aRel.Dot(normal))); // calc the tangential slip acceleration // neither slip velocity nor slip acceleration? nothing to do here if (slipAcc.LengthSq() < 1e-6) { return; } slipDir = slipAcc.Normalize(); numer = -slipDir.Dot(aRel); crossF = Vertex3D.CrossProduct(rF, slipDir); pv13 = crossF.Clone().DivideScalar(-_mover.Inertia); denomF = slipDir.Dot(Vertex3D.CrossProduct(pv13, rF)); } else { // nonzero slip speed - dynamic friction case slipDir = slip.Clone().DivideScalar(slipSpeed); numer = -slipDir.Dot(vRel); crossF = Vertex3D.CrossProduct(rF, slipDir); pv13 = crossF.Clone().DivideScalar(_mover.Inertia); denomF = slipDir.Dot(Vertex3D.CrossProduct(pv13, rF)); } var crossB = Vertex3D.CrossProduct(rB, slipDir); var pv12 = crossB.Clone().DivideScalar(ball.Hit.Inertia); var denomB = ball.Hit.InvMass + slipDir.Dot(Vertex3D.CrossProduct(pv12, rB)); var friction = Functions.Clamp(numer / (denomB + denomF), -maxFriction, maxFriction); ball.Hit.ApplySurfaceImpulse( crossB.Clone().MultiplyScalar(dTime * friction), slipDir.Clone().MultiplyScalar(dTime * friction) ); _mover.ApplyImpulse(crossF.Clone().MultiplyScalar(-dTime * friction)); } }
public void Draw(uint time) { removeDead(time); Material mat = new Material(); mat.Type = MaterialType.TransparentVertexAlpha; mat.Lighting = false; sceneManager.VideoDriver.SetMaterial(mat); sceneManager.VideoDriver.SetTransform(TransformationState.World, Matrix.Identity); Random random = new Random(); Color[] colors = new Color[11]; // 11 colors (line count + 1, since each line has 2 points) for (int i = 0; i < colors.Length; i++) { colors[i] = new Color(255, 255, 255, 255 - (10 - i) * 25); } vertexBuffer.SetCount(0); foreach (var shot in shots) { Vector3Df pos = shot.node.Position; AABBox box = new AABBox(pos - new Vector3Df(shotRadius), pos + new Vector3Df(shotRadius)); List <Triangle3Df> tris = worldTriangles.GetTriangles(box, 1000); if (tris.Count == 0) { continue; } Dictionary <float, Vector3Df> uniquePoints = new Dictionary <float, Vector3Df>(); foreach (var t in tris) { Vector3Df p = t.GetClosestPointOnTriangle(pos); float k = p.X + p.Y * 1000 + p.Z * 1000000; uniquePoints[k] = p; } foreach (var point in uniquePoints.Values) { BillboardSceneNode n = sceneManager.AddBillboardSceneNode(null, new Dimension2Df(7.5f)); n.SetMaterialFlag(MaterialFlag.Lighting, false); n.SetMaterialType(MaterialType.TransparentAddColor); n.SetMaterialTexture(0, sceneManager.VideoDriver.GetTexture("../../media/particlewhite.bmp")); n.Position = point; var animator = sceneManager.CreateDeleteAnimator(0.1f); n.AddAnimator(animator); animator.Drop(); Vertex3D v1 = new Vertex3D(point); Vertex3D v2 = new Vertex3D(); for (int i = 0; i < 10; i++) { v1.Color = colors[i]; v2.Color = colors[i + 1]; v2.Position = pos.GetInterpolated(point, i * 0.111); if (i != 0 && i != 9) // do not displace first and last points { v2.Position += new Vector3Df((random.Next() % 10) - 5, (random.Next() % 10) - 5, (random.Next() % 10) - 5); } vertexBuffer.Add(v1); vertexBuffer.Add(v2); v1.Position = v2.Position; } } } indexBuffer.SetCount(vertexBuffer.Count); sceneManager.VideoDriver.DrawVertexPrimitiveList(vertexBuffer, indexBuffer, PrimitiveType.Lines); }
public P3DSimplexNoiseTerrain(SceneNode parent, SceneManager mgr, int id, int vertsPerRow, int vertsPerCol, int cellSpacing, float heightScale) : base(parent, mgr, id) { _mgr = mgr; _driver = _mgr.VideoDriver; Material = new Material(); Material.Lighting = false; _numVertsPerRow = vertsPerRow; _numVertsPerCol = vertsPerCol; _cellSpacing = cellSpacing; _heightScale = heightScale; _numCellsPerRow = _numVertsPerRow - 1; _numCellsPerCol = _numVertsPerCol - 1; _width = _numCellsPerRow * _cellSpacing; _depth = _numCellsPerCol * _cellSpacing; NumVertices = _numVertsPerRow * _numVertsPerCol; _numIndices = (_numCellsPerRow * _numCellsPerCol) * 6; _numTriangles = (_numCellsPerRow * _numCellsPerCol) * 2; _indices = new ushort[_numIndices]; int startX = -_width / 2; int startZ = _depth / 2; int endX = _width / 2; int endZ = -_depth / 2; Box3D = new Box3D(new Vector3D(startX, -_heightScale, startZ), new Vector3D(endX, _heightScale, endZ)); const float uCoordIncrementSize = 1.0f; const float vCoordIncrementSize = 1.0f; _heights = new float[NumVertices]; int i = 0; for (int z = startZ; z >= endZ; z -= _cellSpacing) { int j = 0; for (int x = startX; x <= endX; x += _cellSpacing) { int index = i * _numVertsPerRow + j; // large noise. float height = PerlinSimplexNoise.noise(x * 0.0001f, z * 0.0001f) * _heightScale; // detail noise. height += PerlinSimplexNoise.noise(x * 0.001f, z * 0.001f) * _heightScale / 10; Vertex3D v = new Vertex3D( new Vector3D(x, height, z), new Vector3D(0, 1, 0), Color.Black, new Vector2D(j * uCoordIncrementSize, i * vCoordIncrementSize) ); _buffer.SetVertex((uint)index, v); j++; } i++; } uint baseIndex = 0; for (uint k = 0; k < _numCellsPerRow; k++) { for (uint j = 0; j < _numCellsPerCol; j++) { _buffer.SetIndex(baseIndex + 0, (ushort)(k * _numVertsPerRow + j)); _buffer.SetIndex(baseIndex + 1, (ushort)(k * _numVertsPerRow + j + 1)); _buffer.SetIndex(baseIndex + 2, (ushort)((k + 1) * _numVertsPerRow + j)); _buffer.SetIndex(baseIndex + 3, (ushort)((k + 1) * _numVertsPerRow + j)); _buffer.SetIndex(baseIndex + 4, (ushort)(k * _numVertsPerRow + j + 1)); _buffer.SetIndex(baseIndex + 5, (ushort)((k + 1) * _numVertsPerRow + j + 1)); baseIndex += 6; } } }
public HitPoint(Vertex3D p, ItemType itemType, IItem item) : base(itemType, item) { P = p; }
public void Draw(uint time) { removeDead(time); Material mat = new Material(); mat.Type = MaterialType.TransparentVertexAlpha; mat.Lighting = false; sceneManager.VideoDriver.SetMaterial(mat); sceneManager.VideoDriver.SetTransform(TransformationState.World, Matrix.Identity); Random random = new Random(); Color[] colors = new Color[11]; // 11 colors (line count + 1, since each line has 2 points) for (int i = 0; i < colors.Length; i++) colors[i] = new Color(255, 255, 255, 255 - (10 - i) * 25); vertexBuffer.SetCount(0); foreach (var shot in shots) { Vector3Df pos = shot.node.Position; AABBox box = new AABBox(pos - new Vector3Df(shotRadius), pos + new Vector3Df(shotRadius)); List<Triangle3Df> tris = worldTriangles.GetTriangles(box, 1000); if (tris.Count == 0) continue; Dictionary<float, Vector3Df> uniquePoints = new Dictionary<float, Vector3Df>(); foreach (var t in tris) { Vector3Df p = t.GetClosestPointOnTriangle(pos); float k = p.X + p.Y * 1000 + p.Z * 1000000; uniquePoints[k] = p; } foreach (var point in uniquePoints.Values) { BillboardSceneNode n = sceneManager.AddBillboardSceneNode(null, new Dimension2Df(7.5f)); n.SetMaterialFlag(MaterialFlag.Lighting, false); n.SetMaterialType(MaterialType.TransparentAddColor); n.SetMaterialTexture(0, sceneManager.VideoDriver.GetTexture("../../media/particlewhite.bmp")); n.Position = point; n.AddAnimator(sceneManager.CreateDeleteAnimator(0.1f)); n.AnimatorList[0].Drop(); Vertex3D v1 = new Vertex3D(point); Vertex3D v2 = new Vertex3D(); for (int i = 0; i < 10; i++) { v1.Color = colors[i]; v2.Color = colors[i + 1]; v2.Position = pos.GetInterpolated(point, i * 0.111); if (i != 0 && i != 9) // do not displace first and last points v2.Position += new Vector3Df((random.Next() % 10) - 5, (random.Next() % 10) - 5, (random.Next() % 10) - 5); vertexBuffer.Add(v1); vertexBuffer.Add(v2); v1.Position = v2.Position; } } } indexBuffer.SetCount(vertexBuffer.Count); sceneManager.VideoDriver.DrawVertexPrimitiveList(vertexBuffer, indexBuffer, PrimitiveType.Lines); }
internal void GenerateColliders(float playfieldHeight, ICollection <ICollider> colliders) { var localToPlayfield = MeshGenerator.GetTransformationMatrix(); // QUICK FIX and TODO for Cupiii /* hitmesh should not be generated by the Mesh generator. Drop Targets need special Hitshapes, that shoujld be very simple and cannot be activated from behind. * var hitMesh = MeshGenerator.GetMesh(); * for (var i = 0; i < hitMesh.Vertices.Length; i++) { * hitMesh.Vertices[i].MultiplyMatrix(localToPlayfield); * } * * var addedEdges = EdgeSet.Get(); * * GenerateCollidables(hitMesh, addedEdges, Data.IsLegacy, colliders); */ var addedEdges = EdgeSet.Get(); var tempMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(Data.RotZ)); var fullMatrix = new Matrix3D().Multiply(tempMatrix); //if (!Data.IsLegacy) // Always generate special hitshapes (QUICKFIX) { var rgv3D = new Vertex3D[DropTargetHitPlaneVertices.Length]; var hitShapeOffset = 0.18f; if (Data.TargetType == TargetType.DropTargetBeveled) { hitShapeOffset = 0.25f; } if (Data.TargetType == TargetType.DropTargetFlatSimple) { hitShapeOffset = 0.13f; } // now create a special hit shape with hit event enabled to prevent a hit event when hit from behind for (var i = 0; i < DropTargetHitPlaneVertices.Length; i++) { var dropTargetHitPlaneVertex = DropTargetHitPlaneVertices[i]; var vert = new Vertex3D( dropTargetHitPlaneVertex.x, dropTargetHitPlaneVertex.y + hitShapeOffset, dropTargetHitPlaneVertex.z ); vert.X *= Data.ScaleX; vert.Y *= Data.ScaleY; vert.Z *= Data.ScaleZ; vert = vert.MultiplyMatrix(fullMatrix); rgv3D[i] = new Vertex3D( vert.X + Data.PositionX, vert.Y + Data.PositionY, vert.Z + Data.PositionZ + playfieldHeight ); } for (var i = 0; i < DropTargetHitPlaneIndices.Length; i += 3) { var i0 = DropTargetHitPlaneIndices[i]; var i1 = DropTargetHitPlaneIndices[i + 1]; var i2 = DropTargetHitPlaneIndices[i + 2]; // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order var rgv0 = rgv3D[i0].ToUnityFloat3(); var rgv1 = rgv3D[i1].ToUnityFloat3(); var rgv2 = rgv3D[i2].ToUnityFloat3(); colliders.Add(new TriangleCollider(rgv0, rgv2, rgv1, GetColliderInfo(true))); if (addedEdges.ShouldAddHitEdge(i0, i1)) { colliders.Add(new Line3DCollider(rgv0, rgv2, GetColliderInfo(true))); } if (addedEdges.ShouldAddHitEdge(i1, i2)) { colliders.Add(new Line3DCollider(rgv2, rgv1, GetColliderInfo(true))); } if (addedEdges.ShouldAddHitEdge(i2, i0)) { colliders.Add(new Line3DCollider(rgv1, rgv0, GetColliderInfo(true))); } } // add collision vertices for (var i = 0; i < DropTargetHitPlaneVertices.Length; ++i) { colliders.Add(new PointCollider(rgv3D[i].ToUnityFloat3(), GetColliderInfo(true))); } } }
protected float HitTestBasicRadius(Ball ball, float dTime, CollisionEvent coll, bool direction, bool lateral, bool rigid) { if (!IsEnabled || ball.State.IsFrozen) { return(-1.0f); } var c = new Vertex3D(Center.X, Center.Y, 0.0f); var dist = ball.State.Pos.Clone().Sub(c); // relative ball position var dv = ball.Hit.Vel.Clone(); var capsule3D = !lateral && ball.State.Pos.Z > HitBBox.ZHigh; var isKicker = ObjType == ItemType.Kicker; var isKickerOrTrigger = ObjType == ItemType.Trigger || ObjType == ItemType.Kicker; float targetRadius; if (capsule3D) { targetRadius = Radius * (float)(13.0 / 5.0); c.Z = HitBBox.ZHigh - Radius * (float)(12.0 / 5.0); dist.Z = ball.State.Pos.Z - c.Z; // ball rolling point - capsule center height } else { targetRadius = Radius; if (lateral) { targetRadius += ball.Data.Radius; } dist.Z = 0.0f; dv.Z = 0.0f; } var bcddsq = dist.LengthSq(); // ball center to circle center distance ... squared var bcdd = MathF.Sqrt(bcddsq); // distance center to center if (bcdd <= 1.0e-6) { // no hit on exact center return(-1.0f); } var b = dist.Dot(dv); var bnv = b / bcdd; // ball normal velocity if (direction && bnv > PhysicsConstants.LowNormVel) { // clearly receding from radius return(-1.0f); } var bnd = bcdd - targetRadius; // ball normal distance to var a = dv.LengthSq(); var hitTime = 0f; var isUnhit = false; var isContact = false; // Kicker is special.. handle ball stalled on kicker, commonly hit while receding, knocking back into kicker pocket if (isKicker && bnd <= 0 && bnd >= -Radius && a < PhysicsConstants.ContactVel * PhysicsConstants.ContactVel && ball.Hit.IsRealBall()) { if (ball.Hit.VpVolObjs.Contains(Obj)) { ball.Hit.VpVolObjs.Remove(Obj); // cause capture } } // contact positive possible in future ... objects Negative in contact now if (rigid && bnd < PhysicsConstants.PhysTouch) { if (bnd < -ball.Data.Radius) { return(-1.0f); } if (MathF.Abs(bnv) <= PhysicsConstants.ContactVel) { isContact = true; } else { // estimate based on distance and speed along distance // the ball can be that fast that in the next hit cycle the ball will be inside the hit shape of a bumper or other element. // if that happens bnd is negative and greater than the negative bnv value that results in a negative hittime // below the "if (infNan(hittime) || hittime <0.F...)" will then be true and the hit function will return -1.0f = no hit hitTime = MathF.Max(0.0f, (float)(-bnd / bnv)); } } else if (isKickerOrTrigger && ball.Hit.IsRealBall() && bnd < 0 == ball.Hit.VpVolObjs.IndexOf(Obj) < 0) { // triggers & kickers // here if ... ball inside and no hit set .... or ... ball outside and hit set if (MathF.Abs(bnd - Radius) < 0.05) { // if ball appears in center of trigger, then assumed it was gen"ed there ball.Hit.VpVolObjs.Add(Obj); // special case for trigger overlaying a kicker } else { // this will add the ball to the trigger space without a Hit isUnhit = bnd > 0; // ball on outside is UnHit, otherwise it"s a Hit } } else { if (!rigid && bnd * bnv > 0 || a < 1.0e-8) { // (outside and receding) or (inside and approaching) // no hit ... ball not moving relative to object return(-1.0f); } var sol = Functions.SolveQuadraticEq(a, 2.0f * b, bcddsq - targetRadius * targetRadius); if (sol == null) { return(-1.0f); } var(time1, time2) = sol; isUnhit = time1 * time2 < 0; hitTime = isUnhit ? MathF.Max(time1, time2) : MathF.Min(time1, time2); // ball is inside the circle } if (float.IsNaN(hitTime) || float.IsInfinity(hitTime) || hitTime < 0 || hitTime > dTime) { // contact out of physics frame return(-1.0f); } var hitZ = ball.State.Pos.Z + ball.Hit.Vel.Z * hitTime; // rolling point if (hitZ + ball.Data.Radius * 0.5 < HitBBox.ZLow || !capsule3D && hitZ - ball.Data.Radius * 0.5 > HitBBox.ZHigh || capsule3D && hitZ < HitBBox.ZHigh) { return(-1.0f); } var hitX = ball.State.Pos.X + ball.Hit.Vel.X * hitTime; var hitY = ball.State.Pos.Y + ball.Hit.Vel.Y * hitTime; var sqrLen = (hitX - c.X) * (hitX - c.X) + (hitY - c.Y) * (hitY - c.Y); coll.HitNormal.SetZero(); // over center? if (sqrLen > 1.0e-8) { // no var invLen = 1.0f / MathF.Sqrt(sqrLen); coll.HitNormal.X = (hitX - c.X) * invLen; coll.HitNormal.Y = (hitY - c.Y) * invLen; } else { // yes, over center coll.HitNormal.X = 0.0f; // make up a value, any direction is ok coll.HitNormal.Y = 1.0f; coll.HitNormal.Z = 0.0f; } if (!rigid) { // non rigid body collision? return direction coll.HitFlag = isUnhit; // UnHit signal is receding from target } coll.IsContact = isContact; if (isContact) { coll.HitOrgNormalVelocity = bnv; } coll.HitDistance = bnd; // actual contact distance ... //coll.M_hitRigid = rigid; // collision type return(hitTime); }
public ATMOSkySceneNode(Texture tex, SceneNode parent, SceneManager mgr, int faces, int id) : base(parent, mgr, id) { smgr = mgr; AutomaticCulling = CullingType.Off; material = new Material(); material.Lighting = false; material.ZBuffer = 0; material.Texture1 = tex; face = faces; vertices = new Vertex3D[face + 1]; indices = new ushort[face * 3]; double angle = 0.0f; double angle2 = 360.0f / face; vert = 0; //vertice nr int nr = -3; //indices nr vertices[0] = new Vertex3D(Vector3D.From(0.0f, 100.0f, 0.0f), Vector3D.From(0.0568988f, 0.688538f, -0.722965f), Color.White, Vector2D.From(0.0f, 0.1f) ); for (ushort n = 1; n < face + 1; n++) { vert++; nr += 3; double x = Math.Cos(angle * 0.017453292519943295769236907684886f) * 100; double z = Math.Sin(angle * 0.017453292519943295769236907684886f) * 100; vertices[vert] = new Vertex3D(Vector3D.From((float)x, -5.0f, (float)z), Vector3D.From(0.0568988f, 0.688538f, -0.722965f), Color.White, Vector2D.From(0.0f, 0.9f) ); angle = angle + angle2; indices[nr] = 0; indices[nr + 1] = (ushort)vert; indices[nr + 2] = (ushort)(vert + 1); } indices[nr + 2] = 1; }
public HitObject[] GenerateHitObjects(Table.Table table, IItem item) { var hitObjects = new List <HitObject>(); var rv = _meshGenerator.GetRampVertex(table, PhysicsConstants.HitShapeDetailLevel, true); var rgvLocal = rv.RgvLocal; var rgHeight1 = rv.PointHeights; var vertexCount = rv.VertexCount; var(wallHeightRight, wallHeightLeft) = GetWallHeights(); Vertex2D pv1, pv2, pv3 = new Vertex2D(), pv4 = new Vertex2D(); // Add line segments for right ramp wall. if (wallHeightRight > 0.0f) { for (var i = 0; i < vertexCount - 1; i++) { pv2 = rgvLocal[i]; pv3 = rgvLocal[i + 1]; hitObjects.AddRange(GenerateWallLineSeg(pv2, pv3, i > 0, rgHeight1[i], rgHeight1[i + 1], wallHeightRight, item)); hitObjects.AddRange(GenerateWallLineSeg(pv3, pv2, i < vertexCount - 2, rgHeight1[i], rgHeight1[i + 1], wallHeightRight, item)); // add joints at start and end of right wall if (i == 0) { hitObjects.Add(GenerateJoint2D(pv2, rgHeight1[0], rgHeight1[0] + wallHeightRight, item)); } if (i == vertexCount - 2) { hitObjects.Add(GenerateJoint2D(pv3, rgHeight1[vertexCount - 1], rgHeight1[vertexCount - 1] + wallHeightRight, item)); } } } // Add line segments for left ramp wall. if (wallHeightLeft > 0.0f) { for (var i = 0; i < vertexCount - 1; i++) { pv2 = rgvLocal[vertexCount + i]; pv3 = rgvLocal[vertexCount + i + 1]; hitObjects.AddRange(GenerateWallLineSeg(pv2, pv3, i > 0, rgHeight1[vertexCount - i - 2], rgHeight1[vertexCount - i - 1], wallHeightLeft, item)); hitObjects.AddRange(GenerateWallLineSeg(pv3, pv2, i < vertexCount - 2, rgHeight1[vertexCount - i - 2], rgHeight1[vertexCount - i - 1], wallHeightLeft, item)); // add joints at start and end of left wall if (i == 0) { hitObjects.Add(GenerateJoint2D(pv2, rgHeight1[vertexCount - 1], rgHeight1[vertexCount - 1] + wallHeightLeft, item)); } if (i == vertexCount - 2) { hitObjects.Add(GenerateJoint2D(pv3, rgHeight1[0], rgHeight1[0] + wallHeightLeft, item)); } } } // Add hit triangles for the ramp floor. HitTriangle ph3dpoly, ph3dpolyOld = null; Vertex3D[] rgv3D; for (var i = 0; i < vertexCount - 1; i++) { /* * Layout of one ramp quad seen from above, ramp direction is bottom to top: * * 3 - - 4 * | \ | * | \ | * 2 - - 1 */ pv1 = rgvLocal[i]; // i-th right pv2 = rgvLocal[vertexCount * 2 - i - 1]; // i-th left pv3 = rgvLocal[vertexCount * 2 - i - 2]; // (i+1)-th left pv4 = rgvLocal[i + 1]; // (i+1)-th right // left ramp floor triangle, CCW order rgv3D = new [] { new Vertex3D(pv2.X, pv2.Y, rgHeight1[i]), new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]), new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1]) }; // add joint for starting edge of ramp if (i == 0) { hitObjects.Add(GenerateJoint(rgv3D[0], rgv3D[1], item)); } // add joint for left edge hitObjects.Add(GenerateJoint(rgv3D[0], rgv3D[2], item)); //!! this is not efficient at all, use native triangle-soup directly somehow ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item); if (!ph3dpoly.IsDegenerate) // degenerate triangles happen if width is 0 at some point { hitObjects.Add(ph3dpoly); hitObjects.AddRange(CheckJoint(ph3dpolyOld, ph3dpoly, item)); ph3dpolyOld = ph3dpoly; } // right ramp floor triangle, CCW order rgv3D = new [] { new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1]), new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]), new Vertex3D(pv4.X, pv4.Y, rgHeight1[i + 1]) }; // add joint for right edge hitObjects.Add(GenerateJoint(rgv3D[1], rgv3D[2], item)); ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item); if (!ph3dpoly.IsDegenerate) { hitObjects.Add(ph3dpoly); } hitObjects.AddRange(CheckJoint(ph3dpolyOld, ph3dpoly, item)); ph3dpolyOld = ph3dpoly; } if (vertexCount >= 2) { // add joint for final edge of ramp var v1 = new Vertex3D(pv4.X, pv4.Y, rgHeight1[vertexCount - 1]); var v2 = new Vertex3D(pv3.X, pv3.Y, rgHeight1[vertexCount - 1]); hitObjects.Add(GenerateJoint(v1, v2, item)); } // add outside bottom, // joints at the intersections are not needed since the inner surface has them // this surface is identical... except for the direction of the normal face. // hence the joints protect both surface edges from having a fall through for (var i = 0; i < vertexCount - 1; i++) { // see sketch above pv1 = rgvLocal[i]; pv2 = rgvLocal[vertexCount * 2 - i - 1]; pv3 = rgvLocal[vertexCount * 2 - i - 2]; pv4 = rgvLocal[i + 1]; // left ramp triangle, order CW rgv3D = new[] { new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]), new Vertex3D(pv2.X, pv2.Y, rgHeight1[i]), new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1]) }; ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item); if (!ph3dpoly.IsDegenerate) { hitObjects.Add(ph3dpoly); } // right ramp triangle, order CW rgv3D = new[] { new Vertex3D(pv3.X, pv3.Y, rgHeight1[i + 1]), new Vertex3D(pv4.X, pv4.Y, rgHeight1[i + 1]), new Vertex3D(pv1.X, pv1.Y, rgHeight1[i]) }; ph3dpoly = new HitTriangle(rgv3D, ItemType.Ramp, item); if (!ph3dpoly.IsDegenerate) { hitObjects.Add(ph3dpoly); } } return(hitObjects .Select(obj => SetupHitObject(obj, table)) .ToArray()); }
public new IRenderVertex Set(Vertex3D v) { base.Set(v); return(this); }
private void meshGeneratorThread_generateMesh(int layerIndex) { GridLayer l = layers[layerIndex]; if (l.Mesh != null) { l.Mesh.Drop(); } l.Mesh = Mesh.Create(); if (gridCubeCount > 0) { Vertex3D[] cubeVerts = null; ushort[] cubeInds = null; int cubeIndex = maxCubesPerBuffer; // this way we force buffers to be recreated at next new cube int totalCubesAdded = 0; float baseX = -(CubeSize * GridDim) / 2; float baseZ = -(CubeSize * GridDim) / 2; for (int i = 0; i < GridDim; i++) { for (int j = 0; j < GridDim; j++) { if (grid[i, j] == 0) { continue; } // check if current buffer is out of room, if so make a mesh buffer and attach it to the gridMesh and init next cubeVerts&Inds if (cubeIndex == maxCubesPerBuffer) { if (cubeVerts != null && cubeInds != null) { MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); b.Append(cubeVerts, cubeInds); l.Mesh.AddMeshBuffer(b); b.Drop(); totalCubesAdded += cubeIndex; } int cubeCount = gridCubeCount - totalCubesAdded; if (cubeCount > maxCubesPerBuffer) { cubeCount = maxCubesPerBuffer; } cubeIndex = 0; cubeVerts = new Vertex3D[cubeCount * 8]; // 8 verts per cube cubeInds = new ushort[cubeCount * 3 * 2 * 6]; // 3 indices per triangle; 2 triangles per face; 6 faces per cube } // build the cube and add it // note: we build 8 vertices cube because we don't need to texture it; if you want to change that (to use texture instead of vertex colors) - you need to build 12 vertices cube and initialize UV coords float x = baseX + i * CubeSize; float y = 0; float z = baseZ + j * CubeSize; int iv = cubeIndex * 8; cubeVerts[iv + 0] = new Vertex3D(x, y, z); cubeVerts[iv + 1] = new Vertex3D(x + CubeSize, y, z); cubeVerts[iv + 2] = new Vertex3D(x + CubeSize, y + CubeSize, z); cubeVerts[iv + 3] = new Vertex3D(x, y + CubeSize, z); cubeVerts[iv + 4] = new Vertex3D(x, y, z + CubeSize); cubeVerts[iv + 5] = new Vertex3D(x + CubeSize, y, z + CubeSize); cubeVerts[iv + 6] = new Vertex3D(x + CubeSize, y + CubeSize, z + CubeSize); cubeVerts[iv + 7] = new Vertex3D(x, y + CubeSize, z + CubeSize); int ii = cubeIndex * 3 * 2 * 6; // top cubeInds[ii + 0] = (ushort)(iv + 3); cubeInds[ii + 1] = (ushort)(iv + 7); cubeInds[ii + 2] = (ushort)(iv + 6); cubeInds[ii + 3] = (ushort)(iv + 3); cubeInds[ii + 4] = (ushort)(iv + 6); cubeInds[ii + 5] = (ushort)(iv + 2); // front cubeInds[ii + 6] = (ushort)(iv + 0); cubeInds[ii + 7] = (ushort)(iv + 3); cubeInds[ii + 8] = (ushort)(iv + 2); cubeInds[ii + 9] = (ushort)(iv + 0); cubeInds[ii + 10] = (ushort)(iv + 2); cubeInds[ii + 11] = (ushort)(iv + 1); // right cubeInds[ii + 12] = (ushort)(iv + 1); cubeInds[ii + 13] = (ushort)(iv + 2); cubeInds[ii + 14] = (ushort)(iv + 6); cubeInds[ii + 15] = (ushort)(iv + 1); cubeInds[ii + 16] = (ushort)(iv + 6); cubeInds[ii + 17] = (ushort)(iv + 5); // left cubeInds[ii + 18] = (ushort)(iv + 0); cubeInds[ii + 19] = (ushort)(iv + 4); cubeInds[ii + 20] = (ushort)(iv + 7); cubeInds[ii + 21] = (ushort)(iv + 0); cubeInds[ii + 22] = (ushort)(iv + 7); cubeInds[ii + 23] = (ushort)(iv + 3); // back cubeInds[ii + 24] = (ushort)(iv + 4); cubeInds[ii + 25] = (ushort)(iv + 5); cubeInds[ii + 26] = (ushort)(iv + 6); cubeInds[ii + 27] = (ushort)(iv + 4); cubeInds[ii + 28] = (ushort)(iv + 6); cubeInds[ii + 29] = (ushort)(iv + 7); // bottom cubeInds[ii + 30] = (ushort)(iv + 0); cubeInds[ii + 31] = (ushort)(iv + 1); cubeInds[ii + 32] = (ushort)(iv + 5); cubeInds[ii + 33] = (ushort)(iv + 0); cubeInds[ii + 34] = (ushort)(iv + 5); cubeInds[ii + 35] = (ushort)(iv + 4); cubeIndex++; } } if (cubeIndex > 0) { MeshBuffer b = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); b.Append(cubeVerts, cubeInds); l.Mesh.AddMeshBuffer(b); b.Drop(); } device.SceneManager.MeshManipulator.SetVertexColors(l.Mesh, cubeColor); } l.Transform.Rotation = new Vector3Df(gridGeneration * 0.93f, gridGeneration * 0.81f, gridGeneration * 0.69f); l.Generation = gridGeneration; l.CubeCount = gridCubeCount; l.MeshIsReady = true; }
private Vertex3DNoTex2[] CreateWire(int numRings, int numSegments, IReadOnlyList <Vertex2D> midPoints, IReadOnlyList <float> initialHeights) { var vertices = new Vertex3DNoTex2[numRings * numSegments]; var prev = new Vertex3D(); var index = 0; for (var i = 0; i < numRings; i++) { var i2 = i == numRings - 1 ? i : i + 1; var height = initialHeights[i]; var tangent = new Vertex3D( midPoints[i2].X - midPoints[i].X, midPoints[i2].Y - midPoints[i].Y, initialHeights[i2] - initialHeights[i] ); if (i == numRings - 1) { // for the last spline point use the previous tangent again, otherwise we won't see the complete wire (it stops one control point too early) tangent.X = midPoints[i].X - midPoints[i - 1].X; tangent.Y = midPoints[i].Y - midPoints[i - 1].Y; } Vertex3D biNormal; Vertex3D normal; if (i == 0) { var up = new Vertex3D( midPoints[i2].X + midPoints[i].X, midPoints[i2].Y + midPoints[i].Y, initialHeights[i2] - height ); normal = Vertex3D.CrossProduct(tangent, up); //normal biNormal = Vertex3D.CrossProduct(tangent, normal); } else { normal = Vertex3D.CrossProduct(prev, tangent); biNormal = Vertex3D.CrossProduct(tangent, normal); } biNormal.Normalize(); normal.Normalize(); prev = biNormal; var invNumRings = 1.0f / numRings; var invNumSegments = 1.0f / numSegments; var u = i * invNumRings; for (var j = 0; j < numSegments; j++, index++) { var v = (j + u) * invNumSegments; var tmp = Vertex3D.GetRotatedAxis(j * (360.0f * invNumSegments), tangent, normal) * (_data.WireDiameter * 0.5f); vertices[index] = new Vertex3DNoTex2 { X = midPoints[i].X + tmp.X, Y = midPoints[i].Y + tmp.Y, Z = height + tmp.Z, Tu = u, Tv = v }; // normals var n = new Vertex3D( vertices[index].X - midPoints[i].X, vertices[index].Y - midPoints[i].Y, vertices[index].Z - height ); var len = 1.0f / MathF.Sqrt(n.X * n.X + n.Y * n.Y + n.Z * n.Z); vertices[index].Nx = n.X * len; vertices[index].Ny = n.Y * len; vertices[index].Nz = n.Z * len; } } return(vertices); }
/* istanbul ignore never next executed below the "magic" check (https://www.vpforums.org/index.php?showtopic=42690) */ public void CreateNextLevel(int level, int levelEmpty) { var orgItems = Items & 0x3FFFFFFF; // !! magic if (orgItems <= 4 || level >= 128 / 2) { return; } var vDiag = new Vertex3D( RectBounds.Right - RectBounds.Left, RectBounds.Bottom - RectBounds.Top, RectBounds.ZHigh - RectBounds.ZLow ); int axis; if (vDiag.X > vDiag.Y && vDiag.X > vDiag.Z) { if (vDiag.X < 0.0001) { return; } axis = 0; } else if (vDiag.Y > vDiag.Z) { if (vDiag.Y < 0.0001) { return; } axis = 1; } else { if (vDiag.Z < 0.0001) { return; } axis = 2; } //!! weight this with ratio of elements going to middle vs left&right! (avoids volume split that goes directly through object) // create children, calc bboxes _children = _hitOct.AllocTwoNodes(); if (_children.Length == 0) { // ran out of nodes - abort return; } _children[0].RectBounds = RectBounds; _children[1].RectBounds = RectBounds; var vCenter = new Vertex3D( (RectBounds.Left + RectBounds.Right) * 0.5f, (RectBounds.Top + RectBounds.Bottom) * 0.5f, (RectBounds.ZLow + RectBounds.ZHigh) * 0.5f ); if (axis == 0) { _children[0].RectBounds.Right = vCenter.X; _children[1].RectBounds.Left = vCenter.X; } else if (axis == 1) { _children[0].RectBounds.Bottom = vCenter.Y; _children[1].RectBounds.Top = vCenter.Y; } else { _children[0].RectBounds.ZHigh = vCenter.Z; _children[1].RectBounds.ZLow = vCenter.Z; } _children[0]._hitOct = _hitOct; //!! meh _children[0].Items = 0; _children[0]._children = null; _children[1]._hitOct = _hitOct; //!! meh _children[1].Items = 0; _children[1]._children = null; // determine amount of items that cross splitplane, or are passed on to the children if (axis == 0) { for (var i = Start; i < Start + orgItems; ++i) { var pho = _hitOct.GetItemAt(i); if (pho.HitBBox.Right < vCenter.X) { _children[0].Items++; } else if (pho.HitBBox.Left > vCenter.X) { _children[1].Items++; } } } else if (axis == 1) { for (var i = Start; i < Start + orgItems; ++i) { var pho = _hitOct.GetItemAt(i); if (pho.HitBBox.Bottom < vCenter.Y) { _children[0].Items++; } else if (pho.HitBBox.Top > vCenter.Y) { _children[1].Items++; } } } else { // axis == 2 for (var i = Start; i < Start + orgItems; ++i) { var pho = _hitOct.GetItemAt(i); if (pho.HitBBox.ZHigh < vCenter.Z) { _children[0].Items++; } else if (pho.HitBBox.ZLow > vCenter.Z) { _children[1].Items++; } } } // check if at least two nodes feature objects, otherwise don"t bother subdividing further var countEmpty = 0; if (_children[0].Items == 0) { countEmpty = 1; } if (_children[1].Items == 0) { ++countEmpty; } if (orgItems - _children[0].Items - _children[1].Items == 0) { ++countEmpty; } if (countEmpty >= 2) { ++levelEmpty; } else { levelEmpty = 0; } if (levelEmpty > 8) { // If 8 levels were all just subdividing the same objects without luck, exit & Free the nodes again (but at least empty space was cut off) _hitOct.NumNodes -= 2; _children = null; return; } _children[0].Start = Start + orgItems - _children[0].Items - _children[1].Items; _children[1].Start = _children[0].Start + _children[0].Items; var items = 0; _children[0].Items = 0; _children[1].Items = 0; switch (axis) { // sort items that cross splitplane in-place, the others are sorted into a temporary case 0: { for (var i = Start; i < Start + orgItems; ++i) { var pho = _hitOct.GetItemAt(i); if (pho.HitBBox.Right < vCenter.X) { _hitOct.Indices[_children[0].Start + _children[0].Items++] = _hitOct.OrgIdx[i]; } else if (pho.HitBBox.Left > vCenter.X) { _hitOct.Indices[_children[1].Start + _children[1].Items++] = _hitOct.OrgIdx[i]; } else { _hitOct.OrgIdx[Start + items++] = _hitOct.OrgIdx[i]; } } break; } case 1: { for (var i = Start; i < Start + orgItems; ++i) { var pho = _hitOct.GetItemAt(i); if (pho.HitBBox.Bottom < vCenter.Y) { _hitOct.Indices[_children[0].Start + _children[0].Items++] = _hitOct.OrgIdx[i]; } else if (pho.HitBBox.Top > vCenter.Y) { _hitOct.Indices[_children[1].Start + _children[1].Items++] = _hitOct.OrgIdx[i]; } else { _hitOct.OrgIdx[Start + items++] = _hitOct.OrgIdx[i]; } } break; } default: { // axis == 2 for (var i = Start; i < Start + orgItems; ++i) { var pho = _hitOct.GetItemAt(i); if (pho.HitBBox.ZHigh < vCenter.Z) { _hitOct.Indices[_children[0].Start + _children[0].Items++] = _hitOct.OrgIdx[i]; } else if (pho.HitBBox.ZLow > vCenter.Z) { _hitOct.Indices[_children[1].Start + _children[1].Items++] = _hitOct.OrgIdx[i]; } else { _hitOct.OrgIdx[Start + items++] = _hitOct.OrgIdx[i]; } } break; } } // The following assertions hold after this step: //assert( this.Start + items == this.Children[0].This.Start ); //assert( this.Children[0].This.Start + this.Children[0].This.Items == this.Children[1].This.Start ); //assert( this.Children[1].This.Start + this.Children[1].This.Items == this.Start + org_items ); //assert( this.Start + org_items <= this.HitOct->tmp.Size() ); Items = items | (axis << 30); // copy temporary back //!! could omit this by doing everything inplace for (var i = 0; i < _children[0].Items; i++) { _hitOct.OrgIdx[_children[0].Start + i] = _hitOct.Indices[_children[0].Start + i]; } for (var i = 0; i < _children[1].Items; i++) { _hitOct.OrgIdx[_children[1].Start + i] = _hitOct.Indices[_children[1].Start + i]; } //memcpy(&this.HitOct->m_org_idx[this.Children[0].Start], &this.HitOct->tmp[this.Children[0].Start], this.Children[0].Items*sizeof(unsigned int)); //memcpy(&this.HitOct->m_org_idx[this.Children[1].Start], &this.HitOct->tmp[this.Children[1].Start], this.Children[1].This.Items*sizeof(unsigned int)); _children[0].CreateNextLevel(level + 1, levelEmpty); _children[1].CreateNextLevel(level + 1, levelEmpty); }
public HitTargetData(string name, float x, float y) : base(StoragePrefix.GameItem) { Name = name; Position = new Vertex3D(x, y, 0f); }
private Vertex3D[] GenerateMesh(ref Vector3 position, ref float width, ref float height, ref float depth, ref float cwRadsAroundY, ref RectangularCuboidMeshTexCoords tex) { var rotationMatrix = Matrix4x4.CreateRotationY(-cwRadsAroundY); var normals = new Vector3[] { new Vector3(0.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, -1.0f, 0.0f), }; for (var n = 0; n < 6; n++) { //Extra normalise not really needed, but might clean up some fp rounding errors normals[n] = Vector3.Normalize(Vector3.Transform(normals[n], rotationMatrix)); } /* * Coordinate System is RHS, with y upwards and z positive into camera * * The faces are set out on the cube such that * 1 to 4: side faces, with side one facing along z (into camera) for an unrotated cube mesh (up is positive y) * 1 = back face, normal along negative z * 2 = right face, normal along positive x * 3 = front face, normal along positive z * 4 = left face, normal along negative x * side 5 is top face. with the top of that 2d area being furthest along negative z in the above example * side 6 is bottom face. orientated so that upon rotating the above mentioned around the x axis the * top and bottom face would appear the same way up when facing the camera * i.e. when unrotated the top of the 2d area will be closest to camera upside down (highest z value). * a little tricky to describe - but should be roughly "as expected" */ var mesh = new Vertex3D[] { //Face 1 new Vertex3D { Position = new Vector3(1.0f, -1.0f, -1.0f), TexCoord = tex.One.BottomLeft, Normal = normals[0] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, -1.0f), TexCoord = tex.One.TopLeft, Normal = normals[0] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, -1.0f), TexCoord = tex.One.TopRight, Normal = normals[0] }, new Vertex3D { Position = new Vector3(1.0f, -1.0f, -1.0f), TexCoord = tex.One.BottomLeft, Normal = normals[0] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, -1.0f), TexCoord = tex.One.TopRight, Normal = normals[0] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, -1.0f), TexCoord = tex.One.BottomRight, Normal = normals[0] }, //Face 2 new Vertex3D { Position = new Vector3(1.0f, -1.0f, 1.0f), TexCoord = tex.Two.BottomLeft, Normal = normals[1] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, 1.0f), TexCoord = tex.Two.TopLeft, Normal = normals[1] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, -1.0f), TexCoord = tex.Two.TopRight, Normal = normals[1] }, new Vertex3D { Position = new Vector3(1.0f, -1.0f, 1.0f), TexCoord = tex.Two.BottomLeft, Normal = normals[1] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, -1.0f), TexCoord = tex.Two.TopRight, Normal = normals[1] }, new Vertex3D { Position = new Vector3(1.0f, -1.0f, -1.0f), TexCoord = tex.Two.BottomRight, Normal = normals[1] }, //Face 3 new Vertex3D { Position = new Vector3(-1.0f, -1.0f, 1.0f), TexCoord = tex.Three.BottomLeft, Normal = normals[2] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, 1.0f), TexCoord = tex.Three.TopLeft, Normal = normals[2] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, 1.0f), TexCoord = tex.Three.TopRight, Normal = normals[2] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, 1.0f), TexCoord = tex.Three.BottomLeft, Normal = normals[2] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, 1.0f), TexCoord = tex.Three.TopRight, Normal = normals[2] }, new Vertex3D { Position = new Vector3(1.0f, -1.0f, 1.0f), TexCoord = tex.Three.BottomRight, Normal = normals[2] }, //Face 4 new Vertex3D { Position = new Vector3(-1.0f, -1.0f, -1.0f), TexCoord = tex.Four.BottomLeft, Normal = normals[3] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, -1.0f), TexCoord = tex.Four.TopLeft, Normal = normals[3] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, 1.0f), TexCoord = tex.Four.TopRight, Normal = normals[3] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, -1.0f), TexCoord = tex.Four.BottomLeft, Normal = normals[3] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, 1.0f), TexCoord = tex.Four.TopRight, Normal = normals[3] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, 1.0f), TexCoord = tex.Four.BottomRight, Normal = normals[3] }, //Face 5 new Vertex3D { Position = new Vector3(-1.0f, 1.0f, 1.0f), TexCoord = tex.Five.BottomLeft, Normal = normals[4] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, -1.0f), TexCoord = tex.Five.TopLeft, Normal = normals[4] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, -1.0f), TexCoord = tex.Five.TopRight, Normal = normals[4] }, new Vertex3D { Position = new Vector3(-1.0f, 1.0f, 1.0f), TexCoord = tex.Five.BottomLeft, Normal = normals[4] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, -1.0f), TexCoord = tex.Five.TopRight, Normal = normals[4] }, new Vertex3D { Position = new Vector3(1.0f, 1.0f, 1.0f), TexCoord = tex.Five.BottomRight, Normal = normals[4] }, //Face 6 new Vertex3D { Position = new Vector3(1.0f, -1.0f, -1.0f), TexCoord = tex.Six.BottomLeft, Normal = normals[5] }, new Vertex3D { Position = new Vector3(1.0f, -1.0f, 1.0f), TexCoord = tex.Six.TopLeft, Normal = normals[5] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, 1.0f), TexCoord = tex.Six.TopRight, Normal = normals[5] }, new Vertex3D { Position = new Vector3(1.0f, -1.0f, -1.0f), TexCoord = tex.Six.BottomLeft, Normal = normals[5] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, 1.0f), TexCoord = tex.Six.TopRight, Normal = normals[5] }, new Vertex3D { Position = new Vector3(-1.0f, -1.0f, -1.0f), TexCoord = tex.Six.BottomRight, Normal = normals[5] }, }; var numVerts = mesh.Length; var hw = 0.5f * width; var hh = 0.5f * height; var hd = 0.5f * depth; for (var n = 0; n < numVerts; n++) { var pos = mesh[n].Position; mesh[n].Position = Vector3.Transform(new Vector3(hw * pos.X, hh * pos.Y, hd * pos.Z), rotationMatrix) + position; } return(mesh); }
public static Vector3 ToUnityVector3(this Vertex3D vertex) { return(new Vector3(vertex.X, vertex.Y, vertex.Z)); }
public void SetGrid(int xNo, int yNo, float xMin, float xMax, float yMin, float yMax) { SetDataNo(xNo * yNo); m_nGridXNo = xNo; m_nGridYNo = yNo; m_xMin = xMin; m_xMax = xMax; m_yMin = yMin; m_yMax = yMax; float dx = (m_xMax - m_xMin) / ((float)xNo - 1); float dy = (m_yMax - m_yMin) / ((float)yNo - 1); for (int i = 0; i < xNo; i++) { for (int j = 0; j < yNo; j++) { float xV = m_xMin + dx * ((float)(i)); float yV = m_yMin + dy * ((float)(j)); m_vertices[j * xNo + i] = new Vertex3D(); SetPoint(i, j, xV, yV, 0); } } }
/// <summary> /// Reads mesh buffer infos. /// </summary> void ReadMeshBufferInfos() { // IMPLEMENTED FROM jlouis' witcherconverter // http://jlouisb.users.sourceforge.net/ // https://bitbucket.org/jlouis/witcherconverter SBufferInfos bufferInfos = new SBufferInfos(); // *************** READ CHUNK INFOS *************** foreach (var chunk in _file.chunks) { if (chunk.Type == "CMesh") { List <SVertexBufferInfos> vertexBufferInfos = new List <SVertexBufferInfos>(); var cookedDatas = chunk.GetVariableByName("cookedData") as CVector; foreach (var cookedData in cookedDatas.variables) { switch (cookedData.Name) { case "renderChunks": { var bytes = ((CByteArray)cookedData).Bytes; var nbBuffers = bytes[0]; int curr = 1; for (uint i = 0; i < nbBuffers; i++) { SVertexBufferInfos buffInfo = new SVertexBufferInfos(); curr += 1; // Unknown buffInfo.verticesCoordsOffset = bytes.SubArray(ref curr, 4).GetUint(); buffInfo.uvOffset = bytes.SubArray(ref curr, 4).GetUint(); buffInfo.normalsOffset = bytes.SubArray(ref curr, 4).GetUint(); curr += 9; // Unknown buffInfo.indicesOffset = bytes.SubArray(ref curr, 4).GetUint(); curr += 1; // 0x1D buffInfo.nbVertices = bytes.SubArray(ref curr, 2).GetUshort(); buffInfo.nbIndices = bytes.SubArray(ref curr, 4).GetUint(); curr += 3; // Unknown buffInfo.lod = bytes.SubArray(ref curr, 1).GetByte(); // lod ? vertexBufferInfos.Add(buffInfo); } break; } case "indexBufferOffset": { bufferInfos.indexBufferOffset = uint.Parse(cookedData.ToString()); break; } case "indexBufferSize": { bufferInfos.indexBufferSize = uint.Parse(cookedData.ToString()); break; } case "vertexBufferOffset": { bufferInfos.vertexBufferOffset = uint.Parse(cookedData.ToString()); break; } case "vertexBufferSize": { bufferInfos.vertexBufferSize = uint.Parse(cookedData.ToString()); break; } case "quantizationOffset": { bufferInfos.quantizationOffset.X = float.Parse((cookedData as CVector).variables[0].ToString()); bufferInfos.quantizationOffset.Y = float.Parse((cookedData as CVector).variables[1].ToString()); bufferInfos.quantizationOffset.Z = float.Parse((cookedData as CVector).variables[2].ToString()); break; } case "quantizationScale": { bufferInfos.quantizationScale.X = float.Parse((cookedData as CVector).variables[0].ToString()); bufferInfos.quantizationScale.Y = float.Parse((cookedData as CVector).variables[1].ToString()); bufferInfos.quantizationScale.Z = float.Parse((cookedData as CVector).variables[2].ToString()); break; } case "bonePositions": { foreach (CVector item in cookedData as CArray) { if (item.variables.Count == 4) { Vector3Df pos = new Vector3Df(); pos.X = (item.variables[0] as CFloat).val; pos.Y = (item.variables[1] as CFloat).val; pos.Z = (item.variables[2] as CFloat).val; bonePositions.Add(pos); } } break; } } } bufferInfos.verticesBuffer = vertexBufferInfos; var meshChunks = chunk.GetVariableByName("chunks") as CArray; foreach (var meshChunk in meshChunks.array) { SMeshInfos meshInfo = new SMeshInfos(); foreach (var mesh in (meshChunk as CVector).variables) { switch (mesh.Name) { case "numVertices": { meshInfo.numVertices = uint.Parse(mesh.ToString()); break; } case "numIndices": { meshInfo.numIndices = uint.Parse(mesh.ToString()); break; } case "numBonesPerVertex": { meshInfo.numBonesPerVertex = uint.Parse(mesh.ToString()); break; } case "firstVertex": { meshInfo.firstVertex = uint.Parse(mesh.ToString()); break; } case "firstIndex": { meshInfo.firstIndex = uint.Parse(mesh.ToString()); break; } case "vertexType": { if ((mesh as CName).Value == "MVT_StaticMesh") { meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_STATIC; } else if ((mesh as CName).Value == "MVT_SkinnedMesh") { meshInfo.vertexType = SMeshInfos.EMeshVertexType.EMVT_SKINNED; } break; } case "materialID": { meshInfo.materialID = uint.Parse(mesh.ToString()); break; } } } meshInfos.Add(meshInfo); } } else if (chunk.Type == "CMaterialInstance") { materialInstances.Add(chunk.data as CMaterialInstance); } } // *************** READ MESH BUFFER INFOS *************** foreach (var meshInfo in meshInfos) { SVertexBufferInfos vBufferInf = new SVertexBufferInfos(); uint nbVertices = 0; uint firstVertexOffset = 0; uint nbIndices = 0; uint firstIndiceOffset = 0; for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++) { nbVertices += bufferInfos.verticesBuffer[i].nbVertices; if (nbVertices > meshInfo.firstVertex) { vBufferInf = bufferInfos.verticesBuffer[i]; // the index of the first vertex in the buffer firstVertexOffset = meshInfo.firstVertex - (nbVertices - vBufferInf.nbVertices); break; } } for (int i = 0; i < bufferInfos.verticesBuffer.Count; i++) { nbIndices += bufferInfos.verticesBuffer[i].nbIndices; if (nbIndices > meshInfo.firstIndex) { vBufferInf = bufferInfos.verticesBuffer[i]; firstIndiceOffset = meshInfo.firstIndex - (nbIndices - vBufferInf.nbIndices); break; } } using (StreamReader sr = new StreamReader(_file.FileName + ".1.buffer")) { uint vertexSize = 8; if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED) { vertexSize += meshInfo.numBonesPerVertex * 2; } sr.BaseStream.Seek(vBufferInf.verticesCoordsOffset + firstVertexOffset * vertexSize, SeekOrigin.Begin); List <Vertex3D> vertex3DCoords = new List <Vertex3D>(); Color defaultColor = new Color(255, 255, 255, 255); for (int i = 0; i < meshInfo.numVertices; i++) { ushort x, y, z, w; byte[] buff = new byte[2]; sr.BaseStream.Read(buff, 0, 2); x = buff.GetUshort(); sr.BaseStream.Read(buff, 0, 2); y = buff.GetUshort(); sr.BaseStream.Read(buff, 0, 2); z = buff.GetUshort(); sr.BaseStream.Read(buff, 0, 2); w = buff.GetUshort(); // skip skinning data if (meshInfo.vertexType == SMeshInfos.EMeshVertexType.EMVT_SKINNED) { sr.BaseStream.Seek(meshInfo.numBonesPerVertex * 2, SeekOrigin.Current); } Vertex3D vertex3DCoord = new Vertex3D(); vertex3DCoord.Position = new Vector3Df(x, y, z) / 65535f * bufferInfos.quantizationScale + bufferInfos.quantizationOffset; vertex3DCoord.Color = defaultColor; vertex3DCoords.Add(vertex3DCoord); } sr.BaseStream.Seek(vBufferInf.uvOffset + firstVertexOffset * 4, SeekOrigin.Begin); for (int i = 0; i < meshInfo.numVertices; i++) { ushort u, v; byte[] buff = new byte[2]; sr.BaseStream.Read(buff, 0, 2); u = buff.GetUshort(); sr.BaseStream.Read(buff, 0, 2); v = buff.GetUshort(); float uf = u.ToFloat(); float vf = v.ToFloat(); Vertex3D vertex3DCoord = vertex3DCoords[i]; vertex3DCoord.TCoords = new Vector2Df(uf, vf); vertex3DCoords[i] = vertex3DCoord; } // Indices ------------------------------------------------------------------- sr.BaseStream.Seek(bufferInfos.indexBufferOffset + vBufferInf.indicesOffset + firstIndiceOffset * 2, SeekOrigin.Begin); List <ushort> indices = new List <ushort>(); for (int i = 0; i < meshInfo.numIndices; i++) { indices.Add(0); } for (int i = 0; i < meshInfo.numIndices; i++) { ushort index; byte[] buff = new byte[2]; sr.BaseStream.Read(buff, 0, 2); index = buff.GetUshort(); // Indice need to be inversed for the normals if (i % 3 == 0) { indices[i] = index; } else if (i % 3 == 1) { indices[i + 1] = index; } else if (i % 3 == 2) { indices[i - 1] = index; } } MeshBuffer meshBuff = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); staticMesh.AddMeshBuffer(meshBuff); meshBuff.Append(vertex3DCoords, indices); meshBuff.RecalculateBoundingBox(); meshBuff.Drop(); } } // *************** READ RIG DATA *************** if (RigFile != null) { foreach (var chunk in RigFile.chunks) { if (chunk.Type == "CSkeleton") { var bones = chunk.GetVariableByName("bones") as CArray; meshSkeleton.nbBones = (uint)bones.array.Count; foreach (CVector bone in bones) { var boneName = bone.variables.GetVariableByName("nameAsCName") as CName; meshSkeleton.names.Add(boneName.Value); } var parentIndices = chunk.GetVariableByName("parentIndices") as CArray; foreach (CVariable parentIndex in parentIndices) { meshSkeleton.parentIdx.Add(short.Parse(parentIndex.ToString())); } var unknownBytes = chunk.unknownBytes.Bytes; int currPos = 0; for (uint i = 0; i < meshSkeleton.nbBones; i++) { Vector3Df position = new Vector3Df(); position.X = unknownBytes.SubArray(ref currPos, 4).GetFloat(); position.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat(); position.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat(); unknownBytes.SubArray(ref currPos, 4).GetFloat(); // the w component Quaternion orientation = new Quaternion(); orientation.X = unknownBytes.SubArray(ref currPos, 4).GetFloat(); orientation.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat(); orientation.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat(); orientation.W = unknownBytes.SubArray(ref currPos, 4).GetFloat(); Vector3Df scale; scale.X = unknownBytes.SubArray(ref currPos, 4).GetFloat(); scale.Y = unknownBytes.SubArray(ref currPos, 4).GetFloat(); scale.Z = unknownBytes.SubArray(ref currPos, 4).GetFloat(); unknownBytes.SubArray(ref currPos, 4).GetFloat(); // the w component Matrix posMat = new Matrix(); posMat.Translation = position; Matrix rotMat = new Matrix(); Vector3Df euler = orientation.ToEuler(); // chechNaNErrors(euler); rotMat.SetRotationRadians(euler); Matrix scaleMat = new Matrix(); scaleMat.Scale = scale; Matrix localTransform = posMat * rotMat * scaleMat; orientation = orientation.MakeInverse(); meshSkeleton.matrix.Add(localTransform); meshSkeleton.positions.Add(position); meshSkeleton.rotations.Add(orientation); meshSkeleton.scales.Add(scale); } } } } }
public IRenderVertex Set(Vertex3D v) { base.Set(v.X, v.Y); return(this); }
public void Set(Vertex3D v) { X = v.X; Y = v.Y; Z = v.Z; }
private Mesh GetMesh(Table.Table table, int acc = -1, bool createHitShape = false) { _data.StaticRendering = true; var mesh = new Mesh(_data.Name); int accuracy; if (table.GetDetailLevel() < 5) { accuracy = 6; } else if (table.GetDetailLevel() >= 5 && table.GetDetailLevel() < 8) { accuracy = 8; } else { accuracy = (int)(table.GetDetailLevel() * 1.3f); // see also below } // as solid rubbers are rendered into the static buffer, always use maximum precision if (_data.StaticRendering) { accuracy = (int)(10.0f * 1.2f); // see also above } if (acc != -1) { // hit shapes and UI display have the same, static, precision accuracy = acc; } var splineAccuracy = acc != -1 ? 4.0f * MathF.Pow(10.0f, (10.0f - PhysicsConstants.HitShapeDetailLevel) * (float)(1.0 / 1.5)) : -1.0f; var sv = new SplineVertex(_data.DragPoints, _data.Thickness, table.GetDetailLevel(), (int)splineAccuracy); var numRings = sv.VertexCount - 1; var numSegments = accuracy; var numVertices = numRings * numSegments; var numIndices = 6 * numVertices; //m_numVertices*2+2; var height = _data.HitHeight + table.TableHeight; mesh.Vertices = new Vertex3DNoTex2[numVertices]; mesh.Indices = new int[numIndices]; var prevB = new Vertex3D(); var invNr = 1.0f / numRings; var invNs = 1.0f / numSegments; var index = 0; for (var i = 0; i < numRings; i++) { var i2 = i == numRings - 1 ? 0 : i + 1; var tangent = new Vertex3D(sv.MiddlePoints[i2].X - sv.MiddlePoints[i].X, sv.MiddlePoints[i2].Y - sv.MiddlePoints[i].Y, 0.0f); Vertex3D biNormal; Vertex3D normal; if (i == 0) { var up = new Vertex3D(sv.MiddlePoints[i2].X + sv.MiddlePoints[i].X, sv.MiddlePoints[i2].Y + sv.MiddlePoints[i].Y, height * 2.0f); normal = new Vertex3D(tangent.Y * up.Z, -tangent.X * up.Z, tangent.X * up.Y - tangent.Y * up.X); // = CrossProduct(tangent, up) biNormal = new Vertex3D(tangent.Y * normal.Z, -tangent.X * normal.Z, tangent.X * normal.Y - tangent.Y * normal.X); // = CrossProduct(tangent, normal) } else { normal = prevB.Clone().Cross(tangent); biNormal = tangent.Clone().Cross(normal); } biNormal.Normalize(); normal.Normalize(); prevB = biNormal; var u = i * invNr; for (var j = 0; j < numSegments; j++) { var v = (j + u) * invNs; var tmp = Vertex3D.GetRotatedAxis(j * (360.0f * invNs), tangent, normal) .MultiplyScalar(_data.Thickness * 0.5f); mesh.Vertices[index] = new Vertex3DNoTex2 { X = sv.MiddlePoints[i].X + tmp.X, Y = sv.MiddlePoints[i].Y + tmp.Y }; if (createHitShape && (j == 0 || j == 3)) { //!! hack, adapt if changing detail level for hitshape // for a hit shape create a more rectangle mesh and not a smooth one tmp.Z *= 0.6f; } mesh.Vertices[index].Z = height + tmp.Z; //texel mesh.Vertices[index].Tu = u; mesh.Vertices[index].Tv = v; index++; } } // calculate faces for (var i = 0; i < numRings; i++) { for (var j = 0; j < numSegments; j++) { var quad = new int[4]; quad[0] = i * numSegments + j; if (j != numSegments - 1) { quad[1] = i * numSegments + j + 1; } else { quad[1] = i * numSegments; } if (i != numRings - 1) { quad[2] = (i + 1) * numSegments + j; if (j != numSegments - 1) { quad[3] = (i + 1) * numSegments + j + 1; } else { quad[3] = (i + 1) * numSegments; } } else { quad[2] = j; if (j != numSegments - 1) { quad[3] = j + 1; } else { quad[3] = 0; } } mesh.Indices[(i * numSegments + j) * 6] = quad[0]; mesh.Indices[(i * numSegments + j) * 6 + 1] = quad[1]; mesh.Indices[(i * numSegments + j) * 6 + 2] = quad[2]; mesh.Indices[(i * numSegments + j) * 6 + 3] = quad[3]; mesh.Indices[(i * numSegments + j) * 6 + 4] = quad[2]; mesh.Indices[(i * numSegments + j) * 6 + 5] = quad[1]; } } Mesh.ComputeNormals(mesh.Vertices, numVertices, mesh.Indices, numIndices); var maxX = Constants.FloatMin; var minX = Constants.FloatMax; var maxY = Constants.FloatMin; var minY = Constants.FloatMax; var maxZ = Constants.FloatMin; var minZ = Constants.FloatMax; for (var i = 0; i < numVertices; i++) { if (maxX < mesh.Vertices[i].X) { maxX = mesh.Vertices[i].X; } if (minX > mesh.Vertices[i].X) { minX = mesh.Vertices[i].X; } if (maxY < mesh.Vertices[i].Y) { maxY = mesh.Vertices[i].Y; } if (minY > mesh.Vertices[i].Y) { minY = mesh.Vertices[i].Y; } if (maxZ < mesh.Vertices[i].Z) { maxZ = mesh.Vertices[i].Z; } if (minZ > mesh.Vertices[i].Z) { minZ = mesh.Vertices[i].Z; } } MiddlePoint.X = (maxX + minX) * 0.5f; MiddlePoint.Y = (maxY + minY) * 0.5f; MiddlePoint.Z = (maxZ + minZ) * 0.5f; return(mesh); }
public void ShouldCorrectlyCrossVectors() { Vertex3D.CrossVectors(new Vertex3D(1.5f, 2.5f, 4f), new Vertex3D(3.5f, 100f, 95f)) .Should().BeEquivalentTo(new Vertex3D(-162.5f, -128.5f, 141.25f)); }
public TestBallCreator(float x, float y, float z, float vx, float vy, float vz) { _pos = new Vertex3D(x, y, z); _vel = new Vertex3D(vx, vy, vz); }
public void Set(Vertex3D v) { base.Set(v.X, v.Y); }
public static float3 ToUnityFloat3(this Vertex3D vertex) { return(new float3(vertex.X, vertex.Y, vertex.Z)); }
public new void Set(Vertex3D v) { base.Set(v); }
/// <param name="N">Number of cubes in single dimension (e.g. total cubes for 20 is 20^3=8000)</param> void generateVerticesAndIndices(int N, out Vertex3D[] vertices, out uint[] indices) { int cubeSide = 32; // ask Irrlicht to generate cube mesh for us (we use it like a template) Mesh cubeMesh = device.SceneManager.GeometryCreator.CreateCubeMesh(new Vector3Df(cubeSide)); ushort[] cubeIndices = cubeMesh.GetMeshBuffer(0).Indices as ushort[]; Vertex3D[] cubeVertices = cubeMesh.GetMeshBuffer(0).Vertices as Vertex3D[]; cubeMesh.Drop(); // generate cubes device.Logger.Log("Generating " + N * N * N + " cubes..."); vertices = new Vertex3D[N * N * N * cubeVertices.Length]; indices = new uint[N * N * N * cubeIndices.Length]; int verticesIndex = 0; int indicesIndex = 0; int colorBase = (255 - cubeVertices.Length) / N; float cubePosOffset = 2.0f * cubeSide; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { for (int k = 0; k < N; k++) { // add indices uint firstfreeIndex = (uint)verticesIndex; for (int l = 0; l < cubeIndices.Length; l++) indices[indicesIndex++] = firstfreeIndex + cubeIndices[l]; // add vertices for (int l = 0; l < cubeVertices.Length; l++) { Vertex3D v = new Vertex3D(cubeVertices[l]); v.Color = new Color(i * colorBase + l, j * colorBase + l, k * colorBase + l); v.Position += new Vector3Df(i, j, k) * cubePosOffset; vertices[verticesIndex++] = v; } } } device.Logger.Log( (((i + 1) * 100) / N) + "%: " + (i + 1) * N * N + " cubes has been generated. ~" + Program.MemUsageText); if ((i & 0xf) == 0xf) GC.Collect(); } }
/// <summary> /// Generates a MeshBuffer which represents all the vertices and indices for values of y /// between y0 and y1, and add it to the mesh. /// </summary> void addStrip(HeightMap map, ColorFunc cf, int y0, int y1) { Vertex3D[] vertices = new Vertex3D[(y1 - y0 + 1) * width]; ushort[] indices = new ushort[(y1 - y0) * (width - 1) * 6]; // "6" is a number of indices in 2 triangles (which forms a quad) // calculate vertices int i = 0; for (int y = y0; y <= y1; ++y) { for (int x = 0; x < width; ++x) { float z = map.GetHeight(x, y); float xf = (float)x / (float)width; float yf = (float)y / (float)height; vertices[i++] = new Vertex3D( new Vector3Df(x, scale * z, y), // position map.GetNormal(x, y, scale), // normal calculate(cf, xf, yf, z), // color new Vector2Df(xf, yf) // tcoords ); } } // calculate indices i = 0; for (int y = y0; y < y1; ++y) { for (int x = 0; x < width - 1; ++x) { int n = (y - y0) * width + x; indices[i++] = (ushort)n; indices[i++] = (ushort)(n + width); indices[i++] = (ushort)(n + width + 1); indices[i++] = (ushort)(n + width + 1); indices[i++] = (ushort)(n + 1); indices[i++] = (ushort)n; } } // append calculated verices and indices to mesh buffer MeshBuffer buf = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); // create new buffer Mesh.AddMeshBuffer(buf); buf.Append(vertices, indices); buf.RecalculateBoundingBox(); buf.Drop(); }