private void GenerateTangentsTriangle4f(IVertexArray positionArray, IVertexArray normalArray, IVertexArray texArray, IVertexArray tanArray, IVertexArray bitanArray)
            {
                uint count = (ElementCount != 0 ? ElementCount : _VertexArrayObject.ArrayLength) / 3;

                for (uint i = 0, v = ElementOffset; i < count; i++, v += 3)
                {
                    Vertex3f v0 = (Vertex3f)positionArray.GetElement <Vertex4f>(v);
                    Vertex3f v1 = (Vertex3f)positionArray.GetElement <Vertex4f>(v + 1);
                    Vertex3f v2 = (Vertex3f)positionArray.GetElement <Vertex4f>(v + 2);

                    Vertex2f t0 = texArray.GetElement <Vertex2f>(v);
                    Vertex2f t1 = texArray.GetElement <Vertex2f>(v + 1);
                    Vertex2f t2 = texArray.GetElement <Vertex2f>(v + 2);

                    Vertex3f dv1 = v1 - v0, dv2 = v2 - v0;
                    Vertex2f dt1 = t1 - t0, dt2 = t2 - t0;
                    float    w = 1.0f / (dt1.x * dt2.y - dt1.y * dt2.x);

                    Vertex3f tgVector, btVector;

                    if (Single.IsInfinity(w) == false)
                    {
                        tgVector = (dv1 * dt2.y - dv2 * dt1.y) * w;
                        tgVector.Normalize();

                        btVector = (dv2 * dt1.x - dv1 * dt2.x) * w;
                        btVector.Normalize();

                        Vertex3f n = normalArray.GetElement <Vertex3f>(v).Normalized;

                        n.Normalize();

                        if (((n ^ tgVector) * btVector) < 0.0f)
                        {
                            tgVector = tgVector * -1.0f;
                        }
                    }
                    else
                    {
                        // Degenerate triangles does not contribute
                        tgVector = btVector = Vertex3f.Zero;
                    }

                    tanArray.SetElement <Vertex3f>(tgVector, v);
                    tanArray.SetElement <Vertex3f>(tgVector, v + 1);
                    tanArray.SetElement <Vertex3f>(tgVector, v + 2);

                    bitanArray.SetElement <Vertex3f>(btVector, v);
                    bitanArray.SetElement <Vertex3f>(btVector, v + 1);
                    bitanArray.SetElement <Vertex3f>(btVector, v + 2);
                }
            }
            private void GenerateNormalsTriangle3f(IVertexArray positionArray, IVertexArray normalArray)
            {
                uint count = (ElementCount != 0 ? ElementCount : _VertexArrayObject.ArrayLength) / 3;

                for (uint i = 0, v = ElementOffset; i < count; i++)
                {
                    Vertex3f v0 = positionArray.GetElement <Vertex3f>(v++);
                    Vertex3f v1 = positionArray.GetElement <Vertex3f>(v++);
                    Vertex3f v2 = positionArray.GetElement <Vertex3f>(v++);

                    Vertex3f n = ((v2 - v0) ^ (v1 - v0)).Normalized;

                    normalArray.SetElement <Vertex3f>(n, v - 2);
                    normalArray.SetElement <Vertex3f>(n, v - 1);
                    normalArray.SetElement <Vertex3f>(n, v - 0);
                }
            }
            private void GenerateTexCoordsTriangle3f(IVertexArray positionArray, IVertexArray texArray, VertexArrayTexGenDelegate genTexCoordCallback)
            {
                for (uint i = 0, v = ElementOffset; i < ArrayIndices.ItemCount; i++, v++)
                {
                    uint vIndex = ArrayIndices.GetIndex(v);

                    Vertex3f v0 = positionArray.GetElement <Vertex3f>(vIndex);

                    texArray.SetElement <Vertex2f>(genTexCoordCallback(v0), vIndex);
                }
            }
            private void GenerateTangentsTriangleStrip3f(IVertexArray positionArray, IVertexArray normalArray, IVertexArray texArray, IVertexArray tanArray, IVertexArray bitanArray)
            {
                uint count = ElementCount != 0 ? ElementCount : ArrayIndices.ItemCount;

                uint     i0, i1, i2;
                Vertex3f v0, v1, v2;
                Vertex2f t0, t1, t2;

                i0 = ArrayIndices.GetIndex(ElementOffset);
                i1 = ArrayIndices.GetIndex(ElementOffset + 1);

                v0 = positionArray.GetElement <Vertex3f>(i0);
                v1 = positionArray.GetElement <Vertex3f>(i1);

                t0 = texArray.GetElement <Vertex2f>(i0);
                t1 = texArray.GetElement <Vertex2f>(i1);

                for (uint i = 0, v = ElementOffset + 2; i < count - 2; i++, v++)
                {
                    // Next triangle
                    i2 = ArrayIndices.GetIndex(v);
                    v2 = positionArray.GetElement <Vertex3f>(i2);
                    t2 = texArray.GetElement <Vertex2f>(i2);

                    // Compute tangent & bitangent
                    Vertex3f dv1 = v1 - v0, dv2 = v2 - v0;
                    Vertex2f dt1 = t1 - t0, dt2 = t2 - t0;

                    float w = 1.0f / (dt1.x * dt2.y - dt1.y * dt2.x);

                    Vertex3f tgVector, btVector;

                    if (Single.IsInfinity(w) == false)
                    {
                        tgVector = (dv1 * dt2.y - dv2 * dt1.y) * w;
                        tgVector.Normalize();

                        btVector = (dv2 * dt1.x - dv1 * dt2.x) * w;
                        btVector.Normalize();

                        //Vertex3f n = normalArray.GetElement<Vertex3f>(i2);

                        //n.Normalize();

                        //if (((n ^ tgVector) * btVector) < 0.0f)
                        //	tgVector = tgVector * -1.0f;
                    }
                    else
                    {
                        // Degenerate triangles does not contribute
                        tgVector = btVector = Vertex3f.Zero;
                    }

                    // Store (accumulate adjacent triangles)
                    Vertex3f tg0 = tanArray.GetElement <Vertex3f>(i0) + tgVector;
                    Vertex3f tg1 = tanArray.GetElement <Vertex3f>(i1) + tgVector;
                    Vertex3f tg2 = tanArray.GetElement <Vertex3f>(i2) + tgVector;

                    tanArray.SetElement <Vertex3f>(tg0, i0);
                    tanArray.SetElement <Vertex3f>(tg1, i1);
                    tanArray.SetElement <Vertex3f>(tg2, i2);

                    Vertex3f bt0 = bitanArray.GetElement <Vertex3f>(i0) + btVector;
                    Vertex3f bt1 = bitanArray.GetElement <Vertex3f>(i1) + btVector;
                    Vertex3f bt2 = bitanArray.GetElement <Vertex3f>(i2) + btVector;

                    bitanArray.SetElement <Vertex3f>(bt0, i0);
                    bitanArray.SetElement <Vertex3f>(bt1, i1);
                    bitanArray.SetElement <Vertex3f>(bt2, i2);

                    // Prepare for next triangle
                    i0 = i1;
                    i1 = i2;
                }
            }