// Given a root (aa) and two adjacent vertices (bb, cc), computer the normal for aa private static OMV.Vector3 MakeNormal(Vert aa, Vert bb, Vert cc) { OMV.Vector3 mm = aa.Position - bb.Position; OMV.Vector3 nn = aa.Position - cc.Position; OMV.Vector3 theNormal = OMV.Vector3.Cross(mm, nn); theNormal.Normalize(); return(theNormal); }
private void UpdateRegionTerrainMesh(RegionContextBase rcontext, RegionRenderInfo rri) { TerrainInfoBase ti = rcontext.TerrainInfo; rri.terrainVertices = new float[3 * ti.HeightMapLength * ti.HeightMapWidth]; rri.terrainTexCoord = new float[2 * ti.HeightMapLength * ti.HeightMapWidth]; rri.terrainNormal = new float[3 * ti.HeightMapLength * ti.HeightMapWidth]; int nextVert = 0; int nextTex = 0; int nextNorm = 0; for (int xx = 0; xx < ti.HeightMapLength; xx++) { for (int yy = 0; yy < ti.HeightMapWidth; yy++) { rri.terrainVertices[nextVert + 0] = (float)xx / ti.HeightMapLength * rcontext.Size.X; rri.terrainVertices[nextVert + 1] = (float)yy / ti.HeightMapWidth * rcontext.Size.Y; rri.terrainVertices[nextVert + 2] = ti.HeightMap[xx, yy]; nextVert += 3; rri.terrainTexCoord[nextTex + 0] = xx / ti.HeightMapLength; rri.terrainTexCoord[nextTex + 1] = yy / ti.HeightMapWidth; nextTex += 2; rri.terrainNormal[nextNorm + 0] = 0f; // simple normal pointing up rri.terrainNormal[nextNorm + 1] = 1f; rri.terrainNormal[nextNorm + 2] = 0f; nextNorm += 3; } } // Create the quads which make up the terrain rri.terrainIndices = new UInt16[4 * ti.HeightMapLength * ti.HeightMapWidth]; int nextInd = 0; for (int xx = 0; xx < ti.HeightMapLength - 1; xx++) { for (int yy = 0; yy < ti.HeightMapWidth - 1; yy++) { rri.terrainIndices[nextInd + 0] = (UInt16)((yy + 0) + (xx + 0) * ti.HeightMapLength); rri.terrainIndices[nextInd + 1] = (UInt16)((yy + 1) + (xx + 0) * ti.HeightMapLength); rri.terrainIndices[nextInd + 2] = (UInt16)((yy + 1) + (xx + 1) * ti.HeightMapLength); rri.terrainIndices[nextInd + 3] = (UInt16)((yy + 0) + (xx + 1) * ti.HeightMapLength); nextInd += 4; } } rri.terrainWidth = ti.HeightMapWidth; rri.terrainLength = ti.HeightMapLength; // Calculate normals // Take three corners of each quad and calculate the normal for the vector // a--b--e--... // | | | // d--c--h--... // The triangle a-b-d calculates the normal for a, etc int nextQuad = 0; int nextNrm = 0; for (int xx = 0; xx < ti.HeightMapLength - 1; xx++) { for (int yy = 0; yy < ti.HeightMapWidth - 1; yy++) { OMV.Vector3 aa, bb, cc; int offset = rri.terrainIndices[nextQuad + 0] * 3; aa.X = rri.terrainVertices[offset + 0]; aa.Y = rri.terrainVertices[offset + 1]; aa.Z = rri.terrainVertices[offset + 2]; offset = rri.terrainIndices[nextQuad + 1] * 3; bb.X = rri.terrainVertices[offset + 0]; bb.Y = rri.terrainVertices[offset + 1]; bb.Z = rri.terrainVertices[offset + 2]; offset = rri.terrainIndices[nextQuad + 3] * 3; cc.X = rri.terrainVertices[offset + 0]; cc.Y = rri.terrainVertices[offset + 1]; cc.Z = rri.terrainVertices[offset + 2]; OMV.Vector3 mm = aa - bb; OMV.Vector3 nn = aa - cc; OMV.Vector3 theNormal = -OMV.Vector3.Cross(mm, nn); theNormal.Normalize(); rri.terrainNormal[nextNrm + 0] = theNormal.X; // simple normal pointing up rri.terrainNormal[nextNrm + 1] = theNormal.Y; rri.terrainNormal[nextNrm + 2] = theNormal.Z; nextNrm += 3; nextQuad += 4; } rri.terrainNormal[nextNrm + 0] = 1.0f; rri.terrainNormal[nextNrm + 1] = 0.0f; rri.terrainNormal[nextNrm + 2] = 0.0f; nextNrm += 3; } }