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);
        }
Example #3
0
        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);
        }
Example #5
0
 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));
        }
Example #14
0
 public static List <Vector3[]> BuildOutlines(WallGrid grid)
 {
     return(OutlineGenerator.Generate(grid));
 }
Example #15
0
        public static MeshData BuildWalls(WallGrid grid, IHeightMap floorHeightMap, IHeightMap ceilingHeightMap)
        {
            var outlines = OutlineGenerator.Generate(grid);

            return(WallBuilder.Build(outlines, floorHeightMap, ceilingHeightMap));
        }