Ejemplo n.º 1
0
//////////////////////////////////////////////////////////////////////////
// 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;
}