////////////////////////////////////////////////////////////////////////// // GaBallComponent //virtual void GaBallComponent::update( BcReal Tick ) { // Setup rotation. BcQuat Rotation; Rotation.fromEular( Rotation_, 0.0f, 0.0f ); Rotation_ += Tick; //getParentEntity()->setRotation( Rotation ); // Move ball. const BcVec3d& Position = getParentEntity()->getMatrix().translation(); BcVec3d NewPosition = Position + Velocity_ * Tick; if( NewPosition.x() < -18.0f || NewPosition.x() > 18.0f ) { NewPosition -= BcVec3d( Velocity_.x(), 0.0f, 0.0f ) * Tick; Velocity_.x( -Velocity_.x() ); } if( NewPosition.z() < -10.0f || NewPosition.z() > 10.0f ) { NewPosition -= BcVec3d( 0.0f, 0.0f, Velocity_.z() ) * Tick; Velocity_.z( -Velocity_.z() ); } getParentEntity()->setPosition( NewPosition ); }
void BcMat4d::rotation( const BcVec3d& Angles ) { BcReal sy, sp, sr; BcReal cy, cp, cr; sy = BcSin( Angles.y() ); sp = BcSin( Angles.x() ); sr = BcSin( Angles.z() ); cy = BcCos( Angles.y() ); cp = BcCos( Angles.x() ); cr = BcCos( Angles.z() ); Row0_.set( cy * cr + sy * sp * sr, -cy * sr + sy * sp * cr, sy * cp, 0.0f ); Row1_.set( sr * cp, cr * cp, -sp, 0.0f ); Row2_.set( -sy * cr + cy * sp * sr, sr * sy + cy * sp * cr, cy * cp, 0.0f ); }
////////////////////////////////////////////////////////////////////////// // 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; }
void BcMat4d::scale( const BcVec3d& Scale ) { scale( BcVec4d( Scale.x(), Scale.y(), Scale.z(), 1.0f ) ); }
void BcMat4d::translation( const BcVec3d& Translation ) { translation( BcVec4d( Translation.x(), Translation.y(), Translation.z(), 1.0f ) ); }
////////////////////////////////////////////////////////////////////////// // 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; }
////////////////////////////////////////////////////////////////////////// // buildBindPose void MD5MeshLoader::buildBindPose( MdlNode* pNode, BcU32 iMesh ) { // Skin the mesh. MD5_Joint* pJoints = pJoint( 0 ); MD5_Mesh* pMeshes = pMesh( iMesh ); // This node is a mesh if we have 1 joint, skin if we have more. MdlMesh* pMesh = NULL; if( nJoints_ == 1 ) { pNode->type( eNT_MESH ); pMesh = pNode->pMeshObject(); } else { pNode->type( eNT_SKIN ); pMesh = pNode->pSkinObject(); } // Add material. MdlMaterial Material; Material.default3d(); Material.Name_ = pMeshes->Shader_; BcU32 iMaterial = pMesh->addMaterial( Material ); // Add indices. for( BcU32 i = 0; i < pMeshes->nIndices_; ++i ) { MdlIndex Index; Index.iMaterial_ = iMaterial; Index.iVertex_ = pMeshes->pIndices_[ i ]; pMesh->addIndex( Index ); } BcVec3d WeightPos; for ( BcU32 i = 0; i < pMeshes->nVerts_; ++i ) { MD5_Vert* pMD5Vert = &pMeshes->pVerts_[ i ]; BcVec3d Position( 0.0f, 0.0f, 0.0f ); // Setup vertex. MdlVertex Vert; Vert.bUV_ = BcTrue; Vert.UV_.x( pMD5Vert->U_ ); Vert.UV_.y( pMD5Vert->V_ ); for ( BcU32 j = 0; j < 4; ++j ) { Vert.Weights_[ j ] = 0.0f; Vert.iJoints_[ j ] = 0; } // Get bind pose vertex. Vert.nWeights_ = 0; for ( BcU32 j = 0; j < pMD5Vert->nWeights_; ++j ) { if ( j > 4 ) { break; } BcU32 WeightIndex = pMD5Vert->WeightIndex_ + j; MD5_Weight* pMD5Weight = &pMeshes->pWeights_[ WeightIndex ]; // Fix up a joint. MD5_Joint* pJoint = &pJoints[ pMD5Weight->JointID_ ]; BcVec3d JointTran( pJoint->TX_, pJoint->TY_, pJoint->TZ_ ); BcQuat JointRot( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f ); JointRot.calcFromXYZ(); // const BcReal WeightVal = pMD5Weight->Weight_; WeightPos.set( pMD5Weight->X_, pMD5Weight->Y_, pMD5Weight->Z_ ); JointRot.rotateVector( WeightPos ); Position += ( WeightPos + JointTran ) * WeightVal; // Setup vertex indices and weights: Vert.iJoints_[ j ] = pMD5Weight->JointID_; Vert.Weights_[ j ] = WeightVal; Vert.nWeights_++; } // Correct weights. BcReal WeightTotal = 0.0f; for( BcU32 j = 0; j < Vert.nWeights_; ++j ) { WeightTotal += Vert.Weights_[ j ]; } for( BcU32 j = 0; j < Vert.nWeights_; ++j ) { Vert.Weights_[ j ] = Vert.Weights_[ j ] / WeightTotal; } Vert.bPosition_ = BcTrue; Vert.Position_ = Position; pMesh->addVertex( Vert ); } pMesh->sortIndicesByMaterial(); pMesh->buildNormals(); pMesh->buildTangents(); // Setup AABB to be larger than the skin to account for motion. BcAABB AABB = pMesh->findAABB(); AABB.min( AABB.min() * 1.5f ); AABB.max( AABB.max() * 1.5f ); pNode->aabb( AABB ); // TODO: Refine into bone palettes properly. }