Exemplo n.º 1
0
        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;
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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;
            }
        }