public MeshData Triangulate(WallGrid wallGrid) { byte[,] configurations = MarchingSquares.ComputeConfigurations(wallGrid); byte[][] configurationTable = MarchingSquares.BuildConfigurationTable(); var localVertices = new List <LocalPosition>(); var triangles = new List <int>(); // Stores vertex indices for a single square at a time. var vertexIndices = new ushort[MarchingSquares.MAX_VERTICES_IN_TRIANGULATION]; var currentRow = new ushort[PER_SQUARE_CACHE_SIZE, wallGrid.Length]; var previousRow = new ushort[PER_SQUARE_CACHE_SIZE, wallGrid.Length]; int width = configurations.GetLength(1); int length = configurations.GetLength(0); for (byte y = 0; y < width; y++) { for (byte x = 0; x < length; x++) { int config = configurations[x, y]; byte[] points = configurationTable[config]; for (int i = 0; i < points.Length; i++) { byte point = points[i]; ushort vertexIndex; if (isOnBottom[point] && y > 0) // is vertex cached below { vertexIndex = previousRow[bottomOffset[point], x]; } else if (isOnLeftSide[point] && x > 0) // is vertex cached to the left { vertexIndex = currentRow[leftOffset[point], x - 1]; } else // new vertex { vertexIndex = (ushort)localVertices.Count; localVertices.Add(new LocalPosition(x, y, point)); } if (point < PER_SQUARE_CACHE_SIZE) // cache vertex if top left, top, top right, right or bot right { currentRow[point, x] = vertexIndex; } vertexIndices[i] = vertexIndex; } int numTrianglesToBuild = points.Length - 2; for (int i = 0; i < numTrianglesToBuild; i++) { triangles.Add(vertexIndices[0]); triangles.Add(vertexIndices[i + 1]); triangles.Add(vertexIndices[i + 2]); } } SwapRows(ref currentRow, ref previousRow); } MeshData mesh = new MeshData(); mesh.vertices = localVertices.Select(v => v.ToGlobalPosition(wallGrid.Scale, wallGrid.Position)).ToArray(); mesh.triangles = triangles.ToArray(); return(mesh); }
public static MeshData Triangulate(WallGrid wallGrid) { Vector3 basePosition = wallGrid.Position; int scale = wallGrid.Scale; byte[,] configurations = MarchingSquares.ComputeConfigurations(wallGrid); byte[][] configurationTable = MarchingSquares.BuildConfigurationTable(); MeshSizes meshSizes = ComputeMeshSizes(configurations, configurationTable); // Note: meshSizes.NumVertices overcounts shared vertices. var localVertices = new LocalPosition[meshSizes.NumVertices]; var triangles = new int[meshSizes.NumTriangles]; ushort numVertices = 0; int numTriangles = 0; // Stores vertex indices for a single square at a time. var vertexIndices = new ushort[MarchingSquares.MAX_VERTICES_IN_TRIANGULATION]; var currentRow = new ushort[perSquareCacheSize, wallGrid.Length]; var previousRow = new ushort[perSquareCacheSize, wallGrid.Length]; var isOnLeftSide = new bool[] { true, false, false, false, false, false, true, true }; var isOnBottom = new bool[] { false, false, false, false, true, true, true, false }; var bottomOffset = new sbyte[] { -1, -1, -1, -1, 2, 1, 0, -1 }; var leftOffset = new sbyte[] { 2, -1, -1, -1, -1, -1, 4, 3 }; int width = configurations.GetLength(1); int length = configurations.GetLength(0); for (byte y = 0; y < width; y++) { for (byte x = 0; x < length; x++) { int config = configurations[x, y]; byte[] points = configurationTable[config]; for (int i = 0; i < points.Length; i++) { byte point = points[i]; ushort vertexIndex; if (isOnBottom[point] && y > 0) // is vertex cached below { vertexIndex = previousRow[bottomOffset[point], x]; } else if (isOnLeftSide[point] && x > 0) // is vertex cached to the left { vertexIndex = currentRow[leftOffset[point], x - 1]; } else // new vertex { vertexIndex = numVertices++; localVertices[vertexIndex] = new LocalPosition(x, y, point); } if (point < perSquareCacheSize) // cache vertex if top left, top, top right, right or bot right { currentRow[point, x] = vertexIndex; } vertexIndices[i] = vertexIndex; } int numTrianglesToBuild = points.Length - 2; for (int i = 0; i < numTrianglesToBuild; i++) { triangles[numTriangles++] = vertexIndices[0]; triangles[numTriangles++] = vertexIndices[i + 1]; triangles[numTriangles++] = vertexIndices[i + 2]; } } SwapRows(ref currentRow, ref previousRow); } MeshData mesh = new MeshData(); mesh.vertices = ToGlobalVertices(localVertices, numVertices, wallGrid.Scale, wallGrid.Position); mesh.triangles = triangles; return(mesh); }