////////////////////////////////////////////////////////////////////////// // lookAt void BcMat4d::lookAt( const BcVec3d& Position, const BcVec3d& LookAt, const BcVec3d& UpVec ) { const BcVec3d Front = ( Position - LookAt ).normal(); const BcVec3d Side = Front.cross( UpVec ).normal(); const BcVec3d Up = Side.cross( Front ).normal(); BcMat4d RotMatrix( BcVec4d( Side.x(), Up.x(), -Front.x(), 0.0f ), BcVec4d( Side.y(), Up.y(), -Front.y(), 0.0f ), BcVec4d( Side.z(), Up.z(), -Front.z(), 0.0f ), BcVec4d( 0.0f, 0.0f, 0.0f, 1.0f ) ); BcMat4d TransMatrix( BcVec4d( 1.0f, 0.0f, 0.0f, 0.0f ), BcVec4d( 0.0f, 1.0f, 0.0f, 0.0f ), BcVec4d( 0.0f, 0.0f, 1.0f, 0.0f ), BcVec4d( -Position.x(), -Position.y(), -Position.z(), 1.0f ) ); (*this) = TransMatrix * RotMatrix; }
////////////////////////////////////////////////////////////////////////// // buildTangents void MdlMesh::buildTangents() { BcVec3d* pTan1 = new BcVec3d[ aVertices_.size() * 2 ]; BcVec3d* pTan2 = pTan1 + aVertices_.size(); memset( pTan1, 0, sizeof( BcVec3d ) * aVertices_.size() * 2 ); for ( BcU32 i = 0; i < ( aIndices_.size() / 3 ); ++i ) { BcU32 TA = aIndices_[ ( i * 3 ) + 0 ].iVertex_; BcU32 TB = aIndices_[ ( i * 3 ) + 1 ].iVertex_; BcU32 TC = aIndices_[ ( i * 3 ) + 2 ].iVertex_; MdlVertex& VertA = aVertices_[ TA ]; MdlVertex& VertB = aVertices_[ TB ]; MdlVertex& VertC = aVertices_[ TC ]; BcVec3d VertPosA = VertA.Position_; BcVec3d VertPosB = VertB.Position_; BcVec3d VertPosC = VertC.Position_; BcVec2d VertUVA = VertA.UV_; BcVec2d VertUVB = VertB.UV_; BcVec2d VertUVC = VertC.UV_; BcReal X1 = VertPosB.x() - VertPosA.x(); BcReal X2 = VertPosC.x() - VertPosA.x(); BcReal Y1 = VertPosB.y() - VertPosA.y(); BcReal Y2 = VertPosC.y() - VertPosA.y(); BcReal Z1 = VertPosB.z() - VertPosA.z(); BcReal Z2 = VertPosC.z() - VertPosA.z(); BcReal S1 = VertUVB.x() - VertUVA.x(); BcReal S2 = VertUVC.x() - VertUVA.x(); BcReal T1 = VertUVB.y() - VertUVA.y(); BcReal T2 = VertUVC.y() - VertUVA.y(); BcReal InvR = ( S1 * T2 - S2 * T1 ); BcReal R = 1.0f / InvR; // Validation so it doesn't break everything, just set to a dummy value. if( BcAbs( InvR ) < 1e6f ) { R = 0.0f; } BcVec3d SDir( ( T2 * X1 - T1 * X2 ) * R, ( T2 * Y1 - T1 * Y2 ) * R, ( T2 * Z1 - T1 * Z2 ) * R ); BcVec3d TDir( ( S1 * X2 - S2 * X1 ) * R, ( S1 * Y2 - S2 * Y1 ) * R, ( S1 * Z2 - S2 * Z1 ) * R ); pTan1[ TA ] += SDir; pTan1[ TB ] += SDir; pTan1[ TC ] += SDir; pTan2[ TA ] += TDir; pTan2[ TB ] += TDir; pTan2[ TC ] += TDir; } for ( BcU32 i = 0; i < aVertices_.size(); ++i ) { MdlVertex& Vert = aVertices_[ i ]; BcVec3d Tangent; const BcVec3d N = Vert.Normal_; const BcVec3d& T = pTan1[ i ]; Tangent = ( T - N * N.dot( T ) ); Tangent.normalise(); // Calculate handedness BcReal W = ( N.cross( T ).dot( pTan2[ i ] ) < 0.0f ) ? -1.0f : 1.0f; if ( W < 0.0f ) { Tangent = -Tangent; } Vert.bTangent_ = BcTrue; Vert.Tangent_ = Tangent; // Validate, and create a dummy value. BcReal Mag = Tangent.magnitude(); if( BcAbs( Mag - 1.0f ) > 0.0001f ) { Vert.Tangent_.set( 0.0f, 0.0f, 0.0f ); } } delete[] pTan1; }