| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- using UnityEngine;
- using System.Collections;
- public static class MeshGenerator {
- public static MeshData GenerateTerrainMesh(float[,] heightMap, float heightMultiplier, AnimationCurve _heightCurve, int levelOfDetail, bool useFlatShading) {
- AnimationCurve heightCurve = new AnimationCurve (_heightCurve.keys);
- int meshSimplificationIncrement = (levelOfDetail == 0)?1:levelOfDetail * 2;
- int borderedSize = heightMap.GetLength (0);
- int meshSize = borderedSize - 2*meshSimplificationIncrement;
- int meshSizeUnsimplified = borderedSize - 2;
- float topLeftX = (meshSizeUnsimplified - 1) / -2f;
- float topLeftZ = (meshSizeUnsimplified - 1) / 2f;
- int verticesPerLine = (meshSize - 1) / meshSimplificationIncrement + 1;
- MeshData meshData = new MeshData (verticesPerLine,useFlatShading);
- int[,] vertexIndicesMap = new int[borderedSize,borderedSize];
- int meshVertexIndex = 0;
- int borderVertexIndex = -1;
- for (int y = 0; y < borderedSize; y += meshSimplificationIncrement) {
- for (int x = 0; x < borderedSize; x += meshSimplificationIncrement) {
- bool isBorderVertex = y == 0 || y == borderedSize - 1 || x == 0 || x == borderedSize - 1;
- if (isBorderVertex) {
- vertexIndicesMap [x, y] = borderVertexIndex;
- borderVertexIndex--;
- } else {
- vertexIndicesMap [x, y] = meshVertexIndex;
- meshVertexIndex++;
- }
- }
- }
- for (int y = 0; y < borderedSize; y += meshSimplificationIncrement) {
- for (int x = 0; x < borderedSize; x += meshSimplificationIncrement) {
- int vertexIndex = vertexIndicesMap [x, y];
- Vector2 percent = new Vector2 ((x-meshSimplificationIncrement) / (float)meshSize, (y-meshSimplificationIncrement) / (float)meshSize);
- float height = heightCurve.Evaluate (heightMap [x, y]) * heightMultiplier;
- Vector3 vertexPosition = new Vector3 (topLeftX + percent.x * meshSizeUnsimplified, height, topLeftZ - percent.y * meshSizeUnsimplified);
- meshData.AddVertex (vertexPosition, percent, vertexIndex);
- if (x < borderedSize - 1 && y < borderedSize - 1) {
- int a = vertexIndicesMap [x, y];
- int b = vertexIndicesMap [x + meshSimplificationIncrement, y];
- int c = vertexIndicesMap [x, y + meshSimplificationIncrement];
- int d = vertexIndicesMap [x + meshSimplificationIncrement, y + meshSimplificationIncrement];
- meshData.AddTriangle (a,d,c);
- meshData.AddTriangle (d,a,b);
- }
- vertexIndex++;
- }
- }
- meshData.ProcessMesh ();
- return meshData;
- }
- }
- public class MeshData {
- Vector3[] vertices;
- int[] triangles;
- Vector2[] uvs;
- Vector3[] bakedNormals;
- Vector3[] borderVertices;
- int[] borderTriangles;
- int triangleIndex;
- int borderTriangleIndex;
- bool useFlatShading;
- public MeshData(int verticesPerLine, bool useFlatShading) {
- this.useFlatShading = useFlatShading;
- vertices = new Vector3[verticesPerLine * verticesPerLine];
- uvs = new Vector2[verticesPerLine * verticesPerLine];
- triangles = new int[(verticesPerLine-1)*(verticesPerLine-1)*6];
- borderVertices = new Vector3[verticesPerLine * 4 + 4];
- borderTriangles = new int[24 * verticesPerLine];
- }
- public void AddVertex(Vector3 vertexPosition, Vector2 uv, int vertexIndex) {
- if (vertexIndex < 0) {
- borderVertices [-vertexIndex - 1] = vertexPosition;
- } else {
- vertices [vertexIndex] = vertexPosition;
- uvs [vertexIndex] = uv;
- }
- }
- public void AddTriangle(int a, int b, int c) {
- if (a < 0 || b < 0 || c < 0) {
- borderTriangles [borderTriangleIndex] = a;
- borderTriangles [borderTriangleIndex + 1] = b;
- borderTriangles [borderTriangleIndex + 2] = c;
- borderTriangleIndex += 3;
- } else {
- triangles [triangleIndex] = a;
- triangles [triangleIndex + 1] = b;
- triangles [triangleIndex + 2] = c;
- triangleIndex += 3;
- }
- }
- Vector3[] CalculateNormals() {
- Vector3[] vertexNormals = new Vector3[vertices.Length];
- int triangleCount = triangles.Length / 3;
- for (int i = 0; i < triangleCount; i++) {
- int normalTriangleIndex = i * 3;
- int vertexIndexA = triangles [normalTriangleIndex];
- int vertexIndexB = triangles [normalTriangleIndex + 1];
- int vertexIndexC = triangles [normalTriangleIndex + 2];
- Vector3 triangleNormal = SurfaceNormalFromIndices (vertexIndexA, vertexIndexB, vertexIndexC);
- vertexNormals [vertexIndexA] += triangleNormal;
- vertexNormals [vertexIndexB] += triangleNormal;
- vertexNormals [vertexIndexC] += triangleNormal;
- }
- int borderTriangleCount = borderTriangles.Length / 3;
- for (int i = 0; i < borderTriangleCount; i++) {
- int normalTriangleIndex = i * 3;
- int vertexIndexA = borderTriangles [normalTriangleIndex];
- int vertexIndexB = borderTriangles [normalTriangleIndex + 1];
- int vertexIndexC = borderTriangles [normalTriangleIndex + 2];
- Vector3 triangleNormal = SurfaceNormalFromIndices (vertexIndexA, vertexIndexB, vertexIndexC);
- if (vertexIndexA >= 0) {
- vertexNormals [vertexIndexA] += triangleNormal;
- }
- if (vertexIndexB >= 0) {
- vertexNormals [vertexIndexB] += triangleNormal;
- }
- if (vertexIndexC >= 0) {
- vertexNormals [vertexIndexC] += triangleNormal;
- }
- }
- for (int i = 0; i < vertexNormals.Length; i++) {
- vertexNormals [i].Normalize ();
- }
- return vertexNormals;
- }
- Vector3 SurfaceNormalFromIndices(int indexA, int indexB, int indexC) {
- Vector3 pointA = (indexA < 0)?borderVertices[-indexA-1] : vertices [indexA];
- Vector3 pointB = (indexB < 0)?borderVertices[-indexB-1] : vertices [indexB];
- Vector3 pointC = (indexC < 0)?borderVertices[-indexC-1] : vertices [indexC];
- Vector3 sideAB = pointB - pointA;
- Vector3 sideAC = pointC - pointA;
- return Vector3.Cross (sideAB, sideAC).normalized;
- }
- public void ProcessMesh() {
- if (useFlatShading) {
- FlatShading ();
- } else {
- BakeNormals ();
- }
- }
- void BakeNormals() {
- bakedNormals = CalculateNormals ();
- }
- void FlatShading() {
- Vector3[] flatShadedVertices = new Vector3[triangles.Length];
- Vector2[] flatShadedUvs = new Vector2[triangles.Length];
- for (int i = 0; i < triangles.Length; i++) {
- flatShadedVertices [i] = vertices [triangles [i]];
- flatShadedUvs [i] = uvs [triangles [i]];
- triangles [i] = i;
- }
- vertices = flatShadedVertices;
- uvs = flatShadedUvs;
- }
- public Mesh CreateMesh() {
- Mesh mesh = new Mesh ();
- mesh.vertices = vertices;
- mesh.triangles = triangles;
- mesh.uv = uvs;
- if (useFlatShading) {
- mesh.RecalculateNormals ();
- } else {
- mesh.normals = bakedNormals;
- }
- return mesh;
- }
- }
|