public MeshData BuildWalls(WallGrid grid, IHeightMap floorHeightMap, IHeightMap ceilingHeightMap, CaveWallModule caveWall) { var outlines = BuildOutlines(grid); var wallBuilder = new WallBuilder(outlines, floorHeightMap, ceilingHeightMap, caveWall); return(wallBuilder.Build()); }
public MeshData BuildEnclosure(WallGrid grid, IHeightMap heightMap) { WallGrid invertedGrid = grid.Invert(); MeshData mesh = BuildFlatMesh(invertedGrid, heightMap); FlipVisibility(mesh); return(mesh); }
static MeshData BuildFlatMesh(WallGrid grid, IHeightMap heightMap) { MeshData mesh = MapTriangulator.Triangulate(grid); mesh.uv = ComputeFlatUVArray(mesh.vertices); ApplyHeightMap(mesh.vertices, heightMap); return(mesh); }
internal FloorTester(WallGrid grid) { Assert.IsNotNull(grid); this.grid = grid; // WallGrids are immutable so we don't need to create a copy. scale = grid.Scale; scaleReciprocal = 1f / scale; xMax = (grid.Length - 1) * scale; zMax = (grid.Width - 1) * scale; wallCache = new WallCache(grid); }
public WallCache(WallGrid grid) { Assert.IsNotNull(grid); length = grid.Length; width = grid.Width; wallSums = new int[length, width]; for (int y = 0; y < width; y++) { for (int x = 0; x < length; x++) { wallSums[x, y] = grid[x, y] + GetWallSum(x - 1, y) + GetWallSum(x, y - 1) - GetWallSum(x - 1, y - 1); } } }
public static byte[,] ComputeConfigurations(WallGrid wallGrid) { int length = wallGrid.Length - 1; int width = wallGrid.Width - 1; byte[,] configurations = new byte[length, width]; byte[,] grid = wallGrid.ToByteArray(); for (int y = 0; y < width; y++) { for (int x = 0; x < length; x++) { configurations[x, y] = (byte)GetConfiguration(grid, x, y); } } return(configurations); }
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); }
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); }
public List <Vector3[]> BuildOutlines(WallGrid grid) { var generator = new OutlineGenerator(); return(generator.Generate(grid)); }
public MeshData BuildCeiling(WallGrid grid, IHeightMap heightMap) { return(BuildFlatMesh(grid, heightMap)); }
public MeshData BuildFloor(WallGrid grid, IHeightMap heightMap) { WallGrid invertedGrid = grid.Invert(); return(BuildFlatMesh(invertedGrid, heightMap)); }
public static List <Vector3[]> BuildOutlines(WallGrid grid) { return(OutlineGenerator.Generate(grid)); }
public static MeshData BuildWalls(WallGrid grid, IHeightMap floorHeightMap, IHeightMap ceilingHeightMap) { var outlines = OutlineGenerator.Generate(grid); return(WallBuilder.Build(outlines, floorHeightMap, ceilingHeightMap)); }