private void CalculateTangentBinormal(DTempVertexType vertex1, DTempVertexType vertex2, DTempVertexType vertex3, out DVertexTempType tangent, out DVertexTempType binormal) { float[] vector1 = new float[3]; float[] vector2 = new float[3]; float[] tuVector = new float[2]; float[] tvVector = new float[2]; // Calculate the two vectors for this face. vector1[0] = vertex2.x - vertex1.x; vector1[1] = vertex2.y - vertex1.y; vector1[2] = vertex2.z - vertex1.z; vector2[0] = vertex3.x - vertex1.x; vector2[1] = vertex3.y - vertex1.y; vector2[2] = vertex3.z - vertex1.z; // Calculate the tu and tv texture space vectors. tuVector[0] = vertex2.tu - vertex1.tu; tvVector[0] = vertex2.tv - vertex1.tv; tuVector[1] = vertex3.tu - vertex1.tu; tvVector[1] = vertex3.tv - vertex1.tv; // Calculate the denominator of the tangent/binormal equation. float den = 1.0f / (tuVector[0] * tvVector[1] - tuVector[1] * tvVector[0]); // Calculate the cross products and multiply by the coefficient to get the tangent and binormal. tangent.x = (tvVector[1] * vector1[0] - tvVector[0] * vector2[0]) * den; tangent.y = (tvVector[1] * vector1[1] - tvVector[0] * vector2[1]) * den; tangent.z = (tvVector[1] * vector1[2] - tvVector[0] * vector2[2]) * den; binormal.x = (tuVector[0] * vector2[0] - tuVector[1] * vector1[0]) * den; binormal.y = (tuVector[0] * vector2[1] - tuVector[1] * vector1[1]) * den; binormal.z = (tuVector[0] * vector2[2] - tuVector[1] * vector1[2]) * den; // Calculate the length of this normal. float length = (float)Math.Sqrt((tangent.x * tangent.x) + (tangent.y * tangent.y) + (tangent.z * tangent.z)); // Normalize the normal and then store it binormal.x = binormal.x / length; binormal.y = binormal.y / length; binormal.z = binormal.z / length; }
private bool CalculateNormals() { // Create a temporary array to hold the un-normalized normal vectors. int index; float length; Vector3 vertex1, vertex2, vertex3, vector1, vector2, sum; DVertexTempType[] normals = new DVertexTempType[(m_TerrainHeight - 1) * (m_TerrainWidth - 1)]; // Go through all the faces in the mesh and calculate their normals. for (int j = 0; j < (m_TerrainHeight - 1); j++) { for (int i = 0; i < (m_TerrainWidth - 1); i++) { int index1 = (j * m_TerrainHeight) + i; int index2 = (j * m_TerrainHeight) + (i + 1); int index3 = ((j + 1) * m_TerrainHeight) + i; // Get three vertices from the face. vertex1.X = HeightMap[index1].x; vertex1.Y = HeightMap[index1].y; vertex1.Z = HeightMap[index1].z; vertex2.X = HeightMap[index2].x; vertex2.Y = HeightMap[index2].y; vertex2.Z = HeightMap[index2].z; vertex3.X = HeightMap[index3].x; vertex3.Y = HeightMap[index3].y; vertex3.Z = HeightMap[index3].z; // Calculate the two vectors for this face. vector1 = vertex1 - vertex3; vector2 = vertex3 - vertex2; index = (j * (m_TerrainHeight - 1)) + i; // Calculate the cross product of those two vectors to get the un-normalized value for this face normal. Vector3 vecTestCrossProduct = Vector3.Cross(vector1, vector2); normals[index].x = vecTestCrossProduct.X; normals[index].y = vecTestCrossProduct.Y; normals[index].z = vecTestCrossProduct.Z; } } // Now go through all the vertices and take an average of each face normal // that the vertex touches to get the averaged normal for that vertex. for (int j = 0; j < m_TerrainHeight; j++) { for (int i = 0; i < m_TerrainWidth; i++) { // Initialize the sum. sum = Vector3.Zero; // Initialize the count. int count = 9; // Bottom left face. if (((i - 1) >= 0) && ((j - 1) >= 0)) { index = ((j - 1) * (m_TerrainHeight - 1)) + (i - 1); sum[0] += normals[index].x; sum[1] += normals[index].y; sum[2] += normals[index].z; count++; } // Bottom right face. if ((i < (m_TerrainWidth - 1)) && ((j - 1) >= 0)) { index = ((j - 1) * (m_TerrainHeight - 1)) + i; sum[0] += normals[index].x; sum[1] += normals[index].y; sum[2] += normals[index].z; count++; } // Upper left face. if (((i - 1) >= 0) && (j < (m_TerrainHeight - 1))) { index = (j * (m_TerrainHeight - 1)) + (i - 1); sum[0] += normals[index].x; sum[1] += normals[index].y; sum[2] += normals[index].z; count++; } // Upper right face. if ((i < (m_TerrainWidth - 1)) && (j < (m_TerrainHeight - 1))) { index = (j * (m_TerrainHeight - 1)) + i; sum.X += normals[index].x; sum.Y += normals[index].y; sum.Z += normals[index].z; count++; } // Take the average of the faces touching this vertex. sum.X = (sum.X / (float)count); sum.Y = (sum.Y / (float)count); sum.Z = (sum.Z / (float)count); // Calculate the length of this normal. length = (float)Math.Sqrt((sum.X * sum.X) + (sum.Y * sum.Y) + (sum.Z * sum.Z)); // Get an index to the vertex location in the height map array. index = (j * m_TerrainHeight) + i; // Normalize the final shared normal for this vertex and store it in the height map array. DHeightMapType editHeightMap = HeightMap[index]; editHeightMap.nx = (sum.X / length); editHeightMap.ny = (sum.Y / length); editHeightMap.nz = (sum.Z / length); HeightMap[index] = editHeightMap; } } // Release the temporary normals. normals = null; return(true); }
private void CalculateTerrainVectors() { // Calculate the number of faces in the terrain model. int faceCount = VertexCount / 3; // Initialize the index to the model data. int index = 0; DTempVertexType vertex1, vertex2, vertex3; DVertexTempType tangent = new DVertexTempType(); DVertexTempType binormal = new DVertexTempType(); // Go through all the faces and calculate the the tangent, binormal, and normal vectors. for (int i = 0; i < faceCount; i++) { // Get the three vertices for this face from the terrain model. vertex1.x = TerrainModel[index].x; vertex1.y = TerrainModel[index].y; vertex1.z = TerrainModel[index].z; vertex1.tu = TerrainModel[index].tu; vertex1.tv = TerrainModel[index].tv; vertex1.nx = TerrainModel[index].nx; vertex1.ny = TerrainModel[index].ny; vertex1.nz = TerrainModel[index].nz; index++; vertex2.x = TerrainModel[index].x; vertex2.y = TerrainModel[index].y; vertex2.z = TerrainModel[index].z; vertex2.tu = TerrainModel[index].tu; vertex2.tv = TerrainModel[index].tv; vertex2.nx = TerrainModel[index].nx; vertex2.ny = TerrainModel[index].ny; vertex2.nz = TerrainModel[index].nz; index++; vertex3.x = TerrainModel[index].x; vertex3.y = TerrainModel[index].y; vertex3.z = TerrainModel[index].z; vertex3.tu = TerrainModel[index].tu; vertex3.tv = TerrainModel[index].tv; vertex3.nx = TerrainModel[index].nx; vertex3.ny = TerrainModel[index].ny; vertex3.nz = TerrainModel[index].nz; index++; /// MAKE SUEW that the tangent nad Binoemals calculated are being sent intot he model after the method below. // Calculate the tangent and binormal of that face. CalculateTangentBinormal(vertex1, vertex2, vertex3, out tangent, out binormal); // Store the tangent and binormal for this face back in the model structure. TerrainModel[index - 1].tx = tangent.x; TerrainModel[index - 1].ty = tangent.y; TerrainModel[index - 1].tz = tangent.z; TerrainModel[index - 1].bx = binormal.x; TerrainModel[index - 1].by = binormal.y; TerrainModel[index - 1].bz = binormal.z; TerrainModel[index - 2].tx = tangent.x; TerrainModel[index - 2].ty = tangent.y; TerrainModel[index - 2].tz = tangent.z; TerrainModel[index - 2].bx = binormal.x; TerrainModel[index - 2].by = binormal.y; TerrainModel[index - 2].bz = binormal.z; TerrainModel[index - 3].tx = tangent.x; TerrainModel[index - 3].ty = tangent.y; TerrainModel[index - 3].tz = tangent.z; TerrainModel[index - 3].bx = binormal.x; TerrainModel[index - 3].by = binormal.y; TerrainModel[index - 3].bz = binormal.z; } }