- Home /
Question by
theswedishswede · Sep 26, 2018 at 08:10 PM ·
meshverticesgenerationtriangles
Connecting flatshaded vertices
Using Sebastian Lague's tutorial on procedural landmass generation I've been able to create a working mesh. However i would like to add faces between the overlapping vertices to connect them.
(The green rectangles is where i want the faces).
How can this be done?
using System.Collections;
using UnityEngine;
public class MeshGenerator : MonoBehaviour {
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.Finalize();
return meshData;
}
}
public class MeshData
{
Vector3[] vertices;
int[] triangles;
Vector2[] uvs;
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;
}
}
public void Finalize()
{
if (useFlatShading)
{
FlatShading();
}
else
{
}
}
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;
}
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 Mesh CreateMesh()
{
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.normals = CalculateNormals();
if(useFlatShading)
{
mesh.RecalculateNormals();
}
else
{
}
return mesh;
}
}
mesh.png
(27.6 kB)
Comment
Your answer
Follow this Question
Related Questions
Voxel mesh generation not working. 1 Answer
Setting triangles failing 0 Answers
Problem drawing a mesh with Graphics.DrawMeshNow 1 Answer
contains two different ids for the same vertex 0 Answers
Highmap on a cube. 0 Answers