private (Vector3[], Vector3[]) smoothTerrainVerticesAndNormals(MeshGenerator.Data data, Vector3 axisA, Vector3 axisB)
        {
            Vector3[] vertices = new Vector3[(MeshGenerator.CHUNK_SIZE + 1) * (MeshGenerator.CHUNK_SIZE + 1)];
            Vector3[] normals  = new Vector3[(MeshGenerator.CHUNK_SIZE + 1) * (MeshGenerator.CHUNK_SIZE + 1)];

            float stepSize     = (data.chunkLength + data.chunkLength) / MeshGenerator.CHUNK_SIZE;
            var   axisAOffset  = (axisA * data.chunkLength);
            var   axisBOffset  = (axisB * data.chunkLength);
            var   planetRadius = (float)(Math.Pow(2, Planet.PLANET_SIZE) * Planet.SCALE);

            for (int y = 0; y < MeshGenerator.CHUNK_SIZE + 1; y++)
            {
                for (int x = 0; x < MeshGenerator.CHUNK_SIZE + 1; x++)
                {
                    var pointOnCube           = computePointOnCube(x, y);
                    var pointOnUnitSphere     = Vector3.Normalize(pointOnCube);
                    var pointOnSphere         = pointOnUnitSphere * planetRadius;
                    var elevatedPointOnSphere = pointOnSphere * (1.0f + noiseFilter.Evaluate(pointOnSphere) * Planet.SCALE);
                    vertices[y * (MeshGenerator.CHUNK_SIZE + 1) + x] = elevatedPointOnSphere;

                    Vector3 leftNeighbor;
                    Vector3 topNeighbor;
                    if (x > 0 && y > 0)
                    {
                        leftNeighbor = vertices[y * (MeshGenerator.CHUNK_SIZE + 1) + (x - 1)];
                        topNeighbor  = vertices[(y - 1) * (MeshGenerator.CHUNK_SIZE + 1) + x];
                    }
                    else
                    {
                        var leftNeighborOnSphere = Vector3.Normalize(computePointOnCube(x - 1, y)) * planetRadius;
                        leftNeighbor = leftNeighborOnSphere * (1.0f + noiseFilter.Evaluate(leftNeighborOnSphere) * Planet.SCALE);

                        var topNeighborOnSphere = Vector3.Normalize(computePointOnCube(x, y - 1)) * planetRadius;
                        topNeighbor = topNeighborOnSphere * (1.0f + noiseFilter.Evaluate(topNeighborOnSphere) * Planet.SCALE);
                    }
                    normals[y * (MeshGenerator.CHUNK_SIZE + 1) + x] += Vector3.Cross(topNeighbor - elevatedPointOnSphere, leftNeighbor - elevatedPointOnSphere);

                    var rightNeighborOnSphere = Vector3.Normalize(computePointOnCube(x + 1, y)) * planetRadius;
                    var rightNeighbor         = rightNeighborOnSphere * (1.0f + noiseFilter.Evaluate(rightNeighborOnSphere) * Planet.SCALE);

                    var bottomNeighborOnSphere = Vector3.Normalize(computePointOnCube(x, y + 1)) * planetRadius;
                    var bottomNeighbor         = bottomNeighborOnSphere * (1.0f + noiseFilter.Evaluate(bottomNeighborOnSphere) * Planet.SCALE);
                    normals[y * (MeshGenerator.CHUNK_SIZE + 1) + x] += Vector3.Cross(bottomNeighbor - elevatedPointOnSphere, rightNeighbor - elevatedPointOnSphere);
                }
            }

            Vector3 computePointOnCube(int x, int y)
            {
                return(axisA * (y * stepSize) + axisB * (x * stepSize) + data.center - axisAOffset - axisBOffset);
            }

            for (int i = 0; i < normals.Length; i++)
            {
                normals[i] = Vector3.Normalize(normals[i]);
            }

            return(vertices, normals);
        }
 private Mesh smoothTerrainMesh(MeshGenerator.Data data, Vector3 axisA, Vector3 axisB)
 {
     var(vertices, normals) = smoothTerrainVerticesAndNormals(data, axisA, axisB);
     return(new Mesh()
     {
         vertices = vertices,
         indices = IndicesLookup.Indices,
         normals = normals
     });
 }
예제 #3
0
        private Mesh blockTerrainMesh(MeshGenerator.Data data, Vector3 axisA, Vector3 axisB)
        {
            List <Vector3> vertices = new List <Vector3>();
            List <int>     indices  = new List <int>();

            var axisAOffset = (axisA * data.chunkLength);
            var axisBOffset = (axisB * data.chunkLength);

            float[] lastRowElevations   = new float[MeshGenerator.CHUNK_SIZE];
            float   lastColumnElevation = 0.0f;

            for (int y = 0; y < MeshGenerator.CHUNK_SIZE; y++)
            {
                for (int x = 0; x < MeshGenerator.CHUNK_SIZE; x++)
                {
                    var middlePointOnCube = axisA * ((y + 0.5f) * BLOCK_HEIGHT) + axisB * ((x + 0.5f) * BLOCK_HEIGHT) + data.center - axisAOffset - axisBOffset;

                    var topLeftPointOnCube     = middlePointOnCube + axisA * (BLOCK_HEIGHT * 0.5f) - axisB * (BLOCK_HEIGHT * 0.5f);
                    var topRightPointOnCube    = middlePointOnCube + axisA * (BLOCK_HEIGHT * 0.5f) + axisB * (BLOCK_HEIGHT * 0.5f);
                    var bottomLeftPointOnCube  = middlePointOnCube - axisA * (BLOCK_HEIGHT * 0.5f) - axisB * (BLOCK_HEIGHT * 0.5f);
                    var bottomRightPointOnCube = middlePointOnCube - axisA * (BLOCK_HEIGHT * 0.5f) + axisB * (BLOCK_HEIGHT * 0.5f);

                    // TODO: reuse points in next iteration
                    var topLeftPointOnSphere     = Vector3.Normalize(topLeftPointOnCube);
                    var topRightPointOnSphere    = Vector3.Normalize(topRightPointOnCube);
                    var bottomLeftPointOnSphere  = Vector3.Normalize(bottomLeftPointOnCube);
                    var bottomRightPointOnSphere = Vector3.Normalize(bottomRightPointOnCube);

                    var scaledTopLeftPointOnSphere     = topLeftPointOnSphere * PLANET_RADIUS;
                    var scaledTopRightPointOnSphere    = topRightPointOnSphere * PLANET_RADIUS;
                    var scaledBottomLeftPointOnSphere  = bottomLeftPointOnSphere * PLANET_RADIUS;
                    var scaledBottomRightPointOnSphere = bottomRightPointOnSphere * PLANET_RADIUS;

                    var elevation           = 1.0f + this.elevation(x, y, axisA, axisB, axisAOffset, axisBOffset, data.center) * Planet.SCALE;
                    var elevatedTopLeft     = scaledTopLeftPointOnSphere * elevation;
                    var elevatedTopRight    = scaledTopRightPointOnSphere * elevation;
                    var elevatedBottomLeft  = scaledBottomLeftPointOnSphere * elevation;
                    var elevatedBottomRight = scaledBottomRightPointOnSphere * elevation;

                    vertices.Add(elevatedTopLeft);
                    vertices.Add(elevatedTopRight);
                    vertices.Add(elevatedBottomLeft);
                    vertices.Add(elevatedBottomRight);

                    int vertexBlockStart = vertices.Count - 4;

                    indices.Add(vertexBlockStart + 0);
                    indices.Add(vertexBlockStart + 1);
                    indices.Add(vertexBlockStart + 2);

                    indices.Add(vertexBlockStart + 1);
                    indices.Add(vertexBlockStart + 3);
                    indices.Add(vertexBlockStart + 2);

                    if (y > 0)
                    {
                        var topElevation = lastRowElevations[x];
                        computeVerticalCubeFaces(
                            vertexBlockStart,
                            computeVertexBlockStart(x, y - 1),
                            elevation,
                            topElevation,
                            2,
                            3,
                            0,
                            1,
                            bottomLeftPointOnSphere,
                            bottomRightPointOnSphere,
                            vertices,
                            indices);
                    }

                    if (x > 0)
                    {
                        var leftElevation = lastColumnElevation;
                        computeVerticalCubeFaces(
                            vertexBlockStart,
                            vertices.Count - 8,
                            elevation,
                            leftElevation,
                            0,
                            2,
                            1,
                            3,
                            topLeftPointOnSphere,
                            bottomLeftPointOnSphere,
                            vertices,
                            indices);
                    }

                    lastColumnElevation  = elevation;
                    lastRowElevations[x] = elevation;
                }
            }

            int computeVertexBlockStart(int x, int y)
            {
                return((x + MeshGenerator.CHUNK_SIZE * y) * 4);
            }

            return(new Mesh()
            {
                vertices = vertices.ToArray(),
                indices = indices.ToArray()
            });
        }