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 }); }
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() }); }