コード例 #1
0
        /// <summary>
        /// The matricies can only be calculated if the mesh has all positions, indices and uv coordinates initialized.
        /// Thus call this after initializing the mesh.
        /// </summary>
        private void CalcTangentsAndBitangents()
        {
            float maxId = IDs.Max();

            if (maxId > TexCoord.Count)
            {
                throw new ArgumentException("Not all TexCoords are set, tangents and bitangents can not be calculated.");
            }

            //Calculate TBN for every triangle in the mesh
            List <Vector3> tangentPerTriangle   = new List <Vector3>();
            List <Vector3> bitangentPerTriangle = new List <Vector3>();

            for (int i = 0; i < IDs.Count; i += 3)
            {
                int id0 = (int)IDs[i + 0];
                int id1 = (int)IDs[i + 1];
                int id2 = (int)IDs[i + 2];

                Vector3 p0 = Position[id0];
                Vector3 p1 = Position[id1];
                Vector3 p2 = Position[id2];

                Vector3 q1 = p1 - p0;
                Vector3 q2 = p2 - p0;

                float u0 = TexCoord[id0].X;
                float u1 = TexCoord[id1].X;
                float u2 = TexCoord[id2].X;

                float v0 = TexCoord[id0].Y;
                float v1 = TexCoord[id1].Y;
                float v2 = TexCoord[id2].Y;

                Vector2 s = new Vector2(u1 - u0, u2 - u0);
                Vector2 t = new Vector2(v1 - v0, v2 - v0);

                var leftSide  = Mat2x2(t.Y, -t.X, -s.Y, s.X);
                var rightSide = VecToMat(q1, q2);
                var det       = (1.0f / (s.X * t.Y - s.Y * t.X));

                Matrix4x4 tb = Matrix4x4.Multiply(Matrix4x4.Multiply(leftSide, det), rightSide);

                Vector3 tan   = new Vector3(tb.M11, tb.M12, tb.M13);
                Vector3 bitan = new Vector3(tb.M21, tb.M22, tb.M23);

                tangentPerTriangle.Add(Vector3.Normalize(tan));
                bitangentPerTriangle.Add(Vector3.Normalize(bitan));
            }

            //Average TBN on every vertex
            for (int i = 0; i < Position.Count; i++)
            {
                int     countOfPointMatches = 0;
                Vector3 resultingTangent    = Vector3.Zero;
                Vector3 resultingBitangent  = Vector3.Zero;

                for (int k = 0; k < IDs.Count; k += 3)
                {
                    int id0 = (int)IDs[k + 0];
                    int id1 = (int)IDs[k + 1];
                    int id2 = (int)IDs[k + 2];

                    if (id0 == i || id1 == i || id2 == i)
                    {
                        countOfPointMatches++;
                        resultingTangent   += tangentPerTriangle[(k - k % 3) / 3];
                        resultingBitangent += bitangentPerTriangle[(k - k % 3) / 3];
                    }
                }

                if (countOfPointMatches != 0)
                {
                    resultingTangent   = resultingTangent / countOfPointMatches;
                    resultingBitangent = resultingBitangent / countOfPointMatches;
                }

                Tangent.Add(resultingTangent);
                Bitangent.Add(resultingBitangent);
            }
        }