/// <summary> /// <para>Compute the normals for each vertex of the mesh, checking the edges cells of other chunks.</para> /// <para>This process is needed to avoid illumination differences between contiguous cells of different chunks (seams).</para> /// </summary> /// <param name="chunk"></param> protected virtual void ComputeNormals(Chunk chunk) { chunk.Normals = new Vector3[(ChunkSize + 1) * (ChunkSize + 1)]; int i, triangleIdx, x, z; Vector2Int vertexTerrainPos; Vector3 a, b, c, normal; // Normal for each vertex for (i = 0; i < chunk.Vertices.Count; i++) { LC_Math.IndexToCoords(i, ChunkSize + 1, out x, out z); // If isn't edge if (x < ChunkSize && z < ChunkSize) { triangleIdx = LC_Math.CoordsToIndex(x, z, ChunkSize) * 6; CalculateTrianglesNormals(triangleIdx, chunk); CalculateTrianglesNormals(triangleIdx + 3, chunk); } // If is edge if (x == 0 || z == 0 || x >= ChunkSize || z >= ChunkSize) { vertexTerrainPos = chunk.ChunkPosToTerrain(new Vector2Int(x, z)); a = chunk.Vertices[i]; if (x == 0 || z == 0) { b = TerrainPosToReal(vertexTerrainPos.x - 1, chunk.HeightsMap[x, z + 1], vertexTerrainPos.y); // x - 1, z c = TerrainPosToReal(vertexTerrainPos.x - 1, chunk.HeightsMap[x, z], vertexTerrainPos.y - 1); // x - 1, z - 1 normal = -Vector3.Cross(b - a, c - a); chunk.Normals[i] += normal; if (x != 0) { chunk.Normals[i - (ChunkSize + 1)] += normal; } b = c; // x - 1, z - 1 c = TerrainPosToReal(vertexTerrainPos.x, chunk.HeightsMap[x + 1, z], vertexTerrainPos.y - 1); // x, z - 1 normal = -Vector3.Cross(b - a, c - a); chunk.Normals[i] += normal; if (z != 0) { chunk.Normals[i - 1] += normal; } } if (x == ChunkSize || z == ChunkSize) { b = TerrainPosToReal(vertexTerrainPos.x + 1, chunk.HeightsMap[x + 2, z + 1], vertexTerrainPos.y); // x + 1, z c = TerrainPosToReal(vertexTerrainPos.x + 1, chunk.HeightsMap[x + 2, z + 2], vertexTerrainPos.y + 1); // x + 1, z + 1 normal = -Vector3.Cross(b - a, c - a); chunk.Normals[i] += normal; if (x < ChunkSize) { chunk.Normals[i + (ChunkSize + 1)] += normal; } b = c; // x + 1, z + 1 c = TerrainPosToReal(vertexTerrainPos.x, chunk.HeightsMap[x + 1, z + 2], vertexTerrainPos.y + 1); // x, z + 1 normal = -Vector3.Cross(b - a, c - a); chunk.Normals[i] += normal; if (z < ChunkSize) { chunk.Normals[i + 1] += normal; } } } } for (i = 0; i < chunk.Normals.Length; i++) { chunk.Normals[i].Normalize(); } }