public override void GetVertexData(List <VertexPositionNormalTexture> vertices, List <ushort> indices) { Vector3 normal; int numColumns = DisplayedObject.Heights.GetLength(0); int numRows = DisplayedObject.Heights.GetLength(1); for (int i = 0; i < numColumns; i++) { for (int j = 0; j < numRows; j++) { normal = DisplayedObject.GetNormal(i, j); vertices.Add(new VertexPositionNormalTexture( new Vector3(i * DisplayedObject.GetSpacingX(), DisplayedObject.Heights[i, j], j * DisplayedObject.GetSpacingZ()), normal, new Vector2(i, j))); } } for (int i = 0; i < numColumns - 1; i++) { for (int j = 0; j < numRows - 1; j++) { for (int k = DisplayedObject.QuadTriangles.Length - 1; k >= 0; k--) { switch (DisplayedObject.QuadTriangles[k]) { case 0: indices.Add((ushort)(numRows * j + i)); break; case 1: indices.Add((ushort)(numRows * j + i + 1)); break; case 2: indices.Add((ushort)(numRows * (j + 1) + i)); break; case 3: indices.Add((ushort)(numRows * (j + 1) + i + 1)); break; } } } } }
public override void GetMeshData(List <VertexPositionNormalTexture> vertices, List <ushort> indices) { int numColumns = DisplayedObject.Shape.Heights.GetLength(0); int numRows = DisplayedObject.Shape.Heights.GetLength(1); TerrainShape shape = DisplayedObject.Shape; //The terrain can be transformed arbitrarily. However, the collision against the triangles is always oriented such that the transformed local //up vector points in the same direction as the collidable surfaces. //To make sure the graphics match the terrain collision, see if a triangle normal faces in the same direction as the local up vector. //If not, construct the graphics with reversed winding. Vector3 a, b, c; DisplayedObject.GetPosition(0, 0, out a); DisplayedObject.GetPosition(1, 0, out b); DisplayedObject.GetPosition(0, 1, out c); Vector3 normal = Vector3.Cross(c - a, b - a); Vector3 terrainUp = new Vector3(DisplayedObject.WorldTransform.LinearTransform.M21, DisplayedObject.WorldTransform.LinearTransform.M22, DisplayedObject.WorldTransform.LinearTransform.M23); float dot; Vector3.Dot(ref normal, ref terrainUp, out dot); bool reverseWinding = dot < 0; for (int j = 0; j < numRows; j++) { for (int i = 0; i < numColumns; i++) { VertexPositionNormalTexture v; DisplayedObject.GetPosition(i, j, out v.Position); DisplayedObject.GetNormal(i, j, out v.Normal); if (reverseWinding) { Vector3.Negate(ref v.Normal, out v.Normal); } v.TextureCoordinate = new Vector2(i, j); vertices.Add(v); if (i < numColumns - 1 && j < numRows - 1) { if (shape.QuadTriangleOrganization == QuadTriangleOrganization.BottomLeftUpperRight) { //v3 v4 //v1 v2 //v1 v2 v3 indices.Add((ushort)(numColumns * j + i)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i)); indices.Add((ushort)(numColumns * j + i + 1)); } else { indices.Add((ushort)(numColumns * j + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i)); } //v2 v4 v3 indices.Add((ushort)(numColumns * j + i + 1)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i)); indices.Add((ushort)(numColumns * (j + 1) + i + 1)); } else { indices.Add((ushort)(numColumns * (j + 1) + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i)); } } else if (shape.QuadTriangleOrganization == QuadTriangleOrganization.BottomRightUpperLeft) { //v1 v2 v4 indices.Add((ushort)(numColumns * j + i)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i + 1)); indices.Add((ushort)(numColumns * j + i + 1)); } else { indices.Add((ushort)(numColumns * j + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i + 1)); } //v1 v4 v3 indices.Add((ushort)(numColumns * j + i)); if (reverseWinding) { indices.Add((ushort)(numColumns * (j + 1) + i)); indices.Add((ushort)(numColumns * (j + 1) + i + 1)); } else { indices.Add((ushort)(numColumns * (j + 1) + i + 1)); indices.Add((ushort)(numColumns * (j + 1) + i)); } } } } } }