public List <Vector3[]> Generate(WallGrid grid) { byte[,] configurations = MarchingSquares.ComputeConfigurations(grid); length = configurations.GetLength(0); width = configurations.GetLength(1); TwoWayLookup outlineLookup = CreateLookupTable(configurations, outlineTable); var outlines = cachedOutlines; outlines.Clear(); var visited = cachedVisited; visited.Clear(); foreach (var pair in outlineLookup) { if (!visited.Contains(pair.Key)) { LocalPosition start = pair.Key; LocalPosition next = pair.Value; var outline = new List <LocalPosition>(); AddToOutline(outline, start, visited); AddToOutline(outline, next, visited); // first do a backward pass until looping or running out of connected outline edges while (start != next && outlineLookup.TryGetBackwardValue(next, out next)) { AddToOutline(outline, next, visited); } outline.Reverse(); // if no loop, then do a forward pass from the starting point if (start != next) { next = start; while (outlineLookup.TryGetForwardValue(next, out next)) { AddToOutline(outline, next, visited); } } Vector3[] completeOutline = outline.Select(p => p.ToGlobalPosition(grid.Scale, grid.Position)).ToArray(); outlines.Add(completeOutline); } } return(outlines); }
public static List <Vector3[]> Generate(WallGrid grid) { byte[][] outlineTable = BuildOutlineTable(); byte[,] configurations = MarchingSquares.ComputeConfigurations(grid); int numOutlineEdges = CountOutlineEdges(configurations, outlineTable); TwoWayLookup outlineLookup = CreateLookupTable(configurations, outlineTable, numOutlineEdges); var outlines = new List <Vector3[]>(); var visited = new HashSet <LocalPosition>(); foreach (var pair in outlineLookup) { if (!visited.Contains(pair.Key)) { LocalPosition start = pair.Key; LocalPosition next = pair.Value; var outline = new List <LocalPosition>(); AddToOutline(outline, start, visited); AddToOutline(outline, next, visited); // first do a backward pass until looping or running out of connected outline edges while (start != next && outlineLookup.TryGetBackwardValue(next, out next)) { AddToOutline(outline, next, visited); } outline.Reverse(); // if no loop, then do a forward pass from the starting point if (start != next) { next = start; while (outlineLookup.TryGetForwardValue(next, out next)) { AddToOutline(outline, next, visited); } } outlines.Add(ToGlobalPositions(outline, grid.Scale, grid.Position)); } } return(outlines); }
static TwoWayLookup CreateLookupTable(byte[,] configurations, byte[][] outlineTable, int capacity) { var lookupTable = new TwoWayLookup(capacity); int length = configurations.GetLength(0); int width = configurations.GetLength(1); for (int y = 0; y < width; y++) { for (int x = 0; x < length; x++) { byte[] outlineData = outlineTable[configurations[x, y]]; for (int i = 0; i < outlineData.Length; i += 2) { var a = new LocalPosition(x, y, outlineData[i]); var b = new LocalPosition(x, y, outlineData[i + 1]); lookupTable.AddPair(a, b); } } } return(lookupTable); }
TwoWayLookup CreateLookupTable(byte[,] configurations, byte[,] outlineTable) { cachedLookup.Clear(); var lookupTable = cachedLookup; for (int y = 0; y < width; y++) { for (int x = 0; x < length; x++) { int configuration = configurations[x, y]; int rowLength = outlineTable[configuration, 0]; for (int i = 1; i < rowLength; i += 2) { var a = new LocalPosition(x, y, outlineTable[configuration, i]); var b = new LocalPosition(x, y, outlineTable[configuration, i + 1]); lookupTable.AddPair(a, b); } } } return(lookupTable); }
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); }
public bool TryGetBackwardValue(LocalPosition key, out LocalPosition value) { return(backwardLookup.TryGetValue(key, out value)); }
public void AddPair(LocalPosition start, LocalPosition end) { forwardLookup[start] = end; backwardLookup[end] = start; }
static void AddToOutline(List <LocalPosition> outline, LocalPosition item, HashSet <LocalPosition> visited) { visited.Add(item); outline.Add(item); }