TangentSpaceVectors的创建

//-----------------------------------------------------------------------------
// Name: createTangentSpaceVectors()
// Desc: Given a vertex (v1) and two other vertices (v2 & v3) which define a 
//       triangle, this function will return Tangent, BiNormal, and Normal, 
//       vectors which can be used to define the tangent matrix for the first 
//       vertex's position (v1).
//
// Args: v1        - vertex 1
//       v2        - vertex 2
//       v3        - vertex 3
//       v1u, v1v  - texture-coordinates of vertex 1
//       v2u, v2v  - texture-coordinates of vertex 2
//       v3u, v3v  - texture-coordinates of vertex 3
//       vTangent  - When the function returns, this will be set as the tangent vector
//       vBiNormal - When the function returns, this will be set as the binormal vector
//       vNormal   - When the function returns, this will be set as the normal vector
//
// Note: This function is based on an article by By Jakob Gath and Sbren Dreijer.
// http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.php
//------------------------------------------------------------------------------


void createTangentSpaceVectors( vector3f *v1,
                                vector3f *v2,
                                vector3f *v3,
                                float v1u, float v1v,
                                float v2u, float v2v,
                                float v3u, float v3v,
                                vector3f *vTangent,
                                vector3f *vBiNormal,
                                vector3f *vNormal )
{
    // Create edge vectors from vertex 1 to vectors 2 and 3.
    vector3f vDirVec_v2_to_v1 = *v2 - *v1;
    vector3f vDirVec_v3_to_v1 = *v3 - *v1;


    // Create edge vectors from the texture coordinates of vertex 1 to vector 2.
    float vDirVec_v2u_to_v1u = v2u - v1u;
    float vDirVec_v2v_to_v1v = v2v - v1v;


    // Create edge vectors from the texture coordinates of vertex 1 to vector 3.
    float vDirVec_v3u_to_v1u = v3u - v1u;
    float vDirVec_v3v_to_v1v = v3v - v1v;


    float fDenominator = vDirVec_v2u_to_v1u * vDirVec_v3v_to_v1v - 
                         vDirVec_v3u_to_v1u * vDirVec_v2v_to_v1v;


    if( fDenominator < 0.0001f && fDenominator > -0.0001f )
    {
        // We're too close to zero and we're at risk of a divide-by-zero! 
        // Set the tangent matrix to the identity matrix and do nothing.
        *vTangent  = vector3f( 1.0f, 0.0f, 0.0f );
        *vBiNormal = vector3f( 0.0f, 1.0f, 0.0f );
        *vNormal   = vector3f( 0.0f, 0.0f, 1.0f );
    }
    else
    {
        // Calculate and cache the reciprocal value
        float fScale1 = 1.0f / fDenominator;


        vector3f T;
        vector3f B;
        vector3f N;


        T = vector3f((vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.x - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.x) * fScale1,
                     (vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.y - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.y) * fScale1,
                     (vDirVec_v3v_to_v1v * vDirVec_v2_to_v1.z - vDirVec_v2v_to_v1v * vDirVec_v3_to_v1.z) * fScale1);


        B = vector3f((-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.x + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.x) * fScale1,
                     (-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.y + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.y) * fScale1,
                     (-vDirVec_v3u_to_v1u * vDirVec_v2_to_v1.z + vDirVec_v2u_to_v1u * vDirVec_v3_to_v1.z) * fScale1);


        // The normal N is calculated as the cross product between T and B
        N = crossProduct( T, B );


        // Calculate and cache the reciprocal value
        float fScale2 = 1.0f / ((T.x * B.y * N.z - T.z * B.y * N.x) + 
                                (B.x * N.y * T.z - B.z * N.y * T.x) + 
                                (N.x * T.y * B.z - N.z * T.y * B.x));


        //
        // Use the temporary T (Tangent), (B) Binormal, and N (Normal) vectors 
        // to calculate the inverse of the tangent matrix that they represent.
        // The inverse of the tangent matrix is what we want since we need that
        // to transform the light's vector into tangent-space.
        //


        (*vTangent).x =   crossProduct( B, N ).x * fScale2;
        (*vTangent).y = -(crossProduct( N, T ).x * fScale2);
        (*vTangent).z =   crossProduct( T, B ).x * fScale2;
        (*vTangent).normalize();


        (*vBiNormal).x = -(crossProduct( B, N ).y * fScale2);
        (*vBiNormal).y =   crossProduct( N, T ).y * fScale2;
        (*vBiNormal).z = -(crossProduct( T, B ).y * fScale2);
        (*vBiNormal).normalize();


        (*vNormal).x =   crossProduct( B, N ).z * fScale2;
        (*vNormal).y = -(crossProduct( N, T ).z * fScale2);
        (*vNormal).z =   crossProduct( T, B ).z * fScale2;
        (*vNormal).normalize();


        //
        // NOTE: Since the texture-space of Direct3D and OpenGL are laid-out 
        //       differently, a single normal map can't look right in both 
        //       unless you make some adjustments somewhere.
        //
        //       You can adjust or fix this problem in three ways:
        //
        //       1. Create two normal maps: one for OpenGL and one for Direct3D.
        //       2. Flip the normal map image over as you load it into a texture 
        //          object.
        //       3. Flip the binormal over when computing the tangent-space
        //          matrix.
        //
        // Since the normal map used by this sample was created for Direct3D,
        // I've decided to simply flip the binormal.
        //
        *vBiNormal = *vBiNormal * -1.0f;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值