////////////////////////////////////////////////////////////////////////// // getResource ReObjectRef< CsResource > CsCore::getResource( const BcChar* pFullName ) { ReObjectRef< CsResource > Handle; if( pFullName != NULL ) { BcChar FullNameBuffer[ 1024 ]; BcAssertMsg( BcStrLength( pFullName ) < sizeof( FullNameBuffer ), "CsPackageImporter: Full name too long." ); BcStrCopy( FullNameBuffer, pFullName ); BcChar* pPackageNameBuffer = NULL; BcChar* pResourceNameBuffer = NULL; BcChar* pTypeNameBuffer = NULL; BcAssertMsg( BcStrStr( FullNameBuffer, "." ) != NULL, "CsCore: Missing package from \"%s\"", FullNameBuffer ); BcAssertMsg( BcStrStr( FullNameBuffer, ":" ) != NULL, "CsCore: Missing type from \"%s\"", FullNameBuffer ); pPackageNameBuffer = &FullNameBuffer[ 0 ]; pResourceNameBuffer = BcStrStr( FullNameBuffer, "." ); pTypeNameBuffer = BcStrStr( FullNameBuffer, ":" ); *pResourceNameBuffer++ = '\0'; *pTypeNameBuffer++ = '\0'; BcName PackageName = pPackageNameBuffer; BcName ResourceName = pResourceNameBuffer; internalFindResource( PackageName, ResourceName, ReManager::GetClass( pTypeNameBuffer ), Handle ); BcAssertMsg( Handle.isValid(), "CsCore: Unable to find \"%s\"", FullNameBuffer ); } return Handle; }
////////////////////////////////////////////////////////////////////////// // internalWrite //virtual void BcLogFile::internalWrite( const BcChar* pText ) { BcLog::internalWrite( pText ); if( OutputFile_.isOpen() ) { OutputFile_.write( pText, BcStrLength( pText ) ); internalFlush(); } }
////////////////////////////////////////////////////////////////////////// // load MdlAnim* MD5AnimLoader::load( const BcChar* FileName, const BcChar* NodeName ) { BcFile File; BcBool Ret; ParseMode_ = PM_MAIN; BcU32 iJoint = 0; BcU32 iBound = 0; BcU32 iFrame = 0; BcU32 iAnimComp = 0; File.open( FileName ); BcChar Buffer[1024]; BcChar Command[1024]; BcChar* pBuffer; // Begin the parsage. while( !File.eof() ) { // Parse a line without the spaces at the start or tabs. { pBuffer = &Buffer[0]; BcChar TheChar = 0; BcBool bAtSentence = BcFalse; while( TheChar != 10 && !File.eof() ) { File.read( &TheChar, 1 ); if ( TheChar != '\t' ) { bAtSentence = BcTrue; } if ( TheChar != 10 && TheChar != 13 && bAtSentence ) { *pBuffer = TheChar; ++pBuffer; Ret = ( pBuffer < ( Buffer + 1024 ) ); BcAssert( Ret ); if( !Ret ) { return NULL; } } } // Terminate it. *pBuffer = 0; ++pBuffer; } sscanf( Buffer, "%s", Command ); if ( BcStrLength( Buffer ) == 0 ) { Command[ 0 ] = 0; } switch( ParseMode_ ) { case PM_MAIN: { if( BcStrCompare( "numJoints", Command ) ) { sscanf( Buffer, "numJoints %u", &nJoints_ ); pJoints_ = new MD5_Joint[ nJoints_ ]; for( BcU32 i = 0; i < nFrames_; ++i ) { pFrames_[ i ].nKeys_ = nJoints_; pFrames_[ i ].pKeys_ = new MD5_Joint[ nJoints_ ]; } } else if( BcStrCompare( "numFrames", Command ) ) { sscanf( Buffer, "numFrames %u", &nFrames_ ); nBounds_ = nFrames_; pFrames_ = new MD5_Frame[ nFrames_ ]; pBounds_ = new MD5_Bound[ nBounds_ ]; } else if( BcStrCompare( "frameRate", Command ) ) { sscanf( Buffer, "frameRate %f", &FrameRate_ ); } else if( BcStrCompare( "numAnimatedComponents", Command ) ) { sscanf( Buffer, "numAnimatedComponents %u", &nAnimComponents_ ); pAnimComponents_ = new BcF32[ nAnimComponents_ ]; } else if( BcStrCompare( "hierarchy", Command ) ) { ParseMode_ = PM_HIERARCHY; iJoint = 0; } else if( BcStrCompare( "bounds", Command ) ) { ParseMode_ = PM_BOUNDS; iBound = 0; } else if( BcStrCompare( "baseframe", Command ) ) { ParseMode_ = PM_BASEFRAME; iJoint = 0; } else if ( BcStrCompare( "frame", Command ) ) { ParseMode_ = PM_FRAME; iJoint = 0; iAnimComp = 0; } } break; case PM_HIERARCHY: { if( BcStrCompare( "}", Command ) ) { ParseMode_ = PM_MAIN; } else { BcAssert( iJoint < nJoints_ ); sscanf( Buffer, "%s %u %u %u", &pJoints_[ iJoint ].Name_[0], &pJoints_[ iJoint ].ParentID_, &pJoints_[ iJoint ].AnimMask_, &pJoints_[ iJoint ].AnimOffset_ ); ++iJoint; } } break; case PM_BOUNDS: { if( BcStrCompare( "}", Command ) ) { ParseMode_ = PM_MAIN; } else { BcAssert( iBound < nBounds_ ); sscanf( Buffer, "( %f %f %f ) ( %f %f %f )", &pBounds_[ iBound ].MinX_, &pBounds_[ iBound ].MinY_, &pBounds_[ iBound ].MinZ_, &pBounds_[ iBound ].MaxX_, &pBounds_[ iBound ].MaxY_, &pBounds_[ iBound ].MaxZ_ ); iBound++; } } break; case PM_BASEFRAME: { if( BcStrCompare( "}", Command ) ) { ParseMode_ = PM_MAIN; } else { BcAssert( iJoint < nJoints_ ); sscanf( Buffer, "( %f %f %f ) ( %f %f %f )", &pJoints_[ iJoint ].TX_, &pJoints_[ iJoint ].TY_, &pJoints_[ iJoint ].TZ_, &pJoints_[ iJoint ].QX_, &pJoints_[ iJoint ].QY_, &pJoints_[ iJoint ].QZ_ ); iJoint++; } } break; case PM_FRAME: { if( BcStrCompare( "}", Command ) ) { // Setup all joints. BcAssert( iFrame < nFrames_ ); MD5_Frame* pFrame = &pFrames_[ iFrame++ ]; for( BcU32 i = 0; i < nJoints_; ++i ) { // Copy from base. pFrame->pKeys_[ i ] = pJoints_[ i ]; // Parse from anim data. BcF32* pData = &pAnimComponents_[ pFrame->pKeys_[ i ].AnimOffset_ ]; BcU32 iVal = 0; BcU32 AnimMask = pFrame->pKeys_[ i ].AnimMask_; if( AnimMask & 1 ) { pFrame->pKeys_[ i ].TX_ = pData[ iVal++ ]; } if( AnimMask & 2 ) { pFrame->pKeys_[ i ].TY_ = pData[ iVal++ ]; } if( AnimMask & 4 ) { pFrame->pKeys_[ i ].TZ_ = pData[ iVal++ ]; } if( AnimMask & 8 ) { pFrame->pKeys_[ i ].QX_ = pData[ iVal++ ]; } if( AnimMask & 16 ) { pFrame->pKeys_[ i ].QY_ = pData[ iVal++ ]; } if( AnimMask & 32 ) { pFrame->pKeys_[ i ].QZ_ = pData[ iVal++ ]; } } ParseMode_ = PM_MAIN; } else { BcF32 Data[]= { 1e6f, 1e6f, 1e6f, 1e6f, 1e6f, 1e6f, }; // NOTE: This may not actually work.. sscanf( Buffer, "%f %f %f %f %f %f", &Data[0], &Data[1], &Data[2], &Data[3], &Data[4], &Data[5] ); // Parse into array. for( BcU32 i = 0; i < 6; ++i ) { if( Data[i] < 1e6f ) { BcAssert( iAnimComp < nAnimComponents_ ); pAnimComponents_[ iAnimComp ] = Data[i]; iAnimComp++; } else { break; } } } } break; } } // Create animation. MdlAnim* pAnimation = new MdlAnim(); // Build up all nodes. for( BcU32 i = 0; i < nJoints_; ++i ) { MdlAnimNode Node; BcStrCopy( Node.Name_, pJoints_[ i ].Name_ ); if( pJoints_[ i ].ParentID_ != -1 ) { BcStrCopy( Node.Parent_, pJoints_[ pJoints_[ i ].ParentID_ ].Name_ ); } else { Node.Parent_[ 0 ] = '\0'; } for( BcU32 j = 0; j < nFrames_; ++j ) { MD5_Joint* pJoint = &pFrames_[ j ].pKeys_[ i ]; MdlAnimKey Key; Key.R_.set( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f ); Key.S_.set( 1.0f, 1.0f, 1.0f ); Key.T_.set( pJoint->TX_, pJoint->TY_, pJoint->TZ_ ); Key.R_.calcFromXYZ(); Node.KeyList_.push_back( Key ); } pAnimation->addNode( Node ); } // Cleanup nJoints_ = 0; delete [] pJoints_; pJoints_ = NULL; nBounds_ = 0; delete [] pBounds_; pBounds_ = NULL; nAnimComponents_ = 0; delete [] pAnimComponents_; pAnimComponents_ = NULL; for( BcU32 i = 0; i < nFrames_; ++i ) { delete [] pFrames_[ i ].pKeys_; } nFrames_ = 0; delete [] pFrames_; pFrames_ = NULL; // /* BcMat4d RootTransform; RootTransform.identity(); pRootNode->makeRelativeTransform( RootTransform ); */ return pAnimation;//pRootNode; }
////////////////////////////////////////////////////////////////////////// // load MdlNode* MD5MeshLoader::load( const BcChar* FileName, const BcChar* NodeName ) { BcFile File; BcBool Ret; ParseMode_ = PM_MAIN; BcU32 iJoint = 0; BcU32 iMesh = 0; BcU32 iVert = 0; BcU32 iInd = 0; BcU32 iWeight = 0; if( File.open( FileName ) == BcFalse ) { return NULL; } BcChar Buffer[1024]; BcChar Command[1024]; BcChar* pBuffer; // Begin the parsage. while( !File.eof() ) { // Parse a line without the spaces at the start or tabs. { pBuffer = &Buffer[0]; BcChar TheChar = 0; BcBool bAtSentence = BcFalse; while( TheChar != 10 && !File.eof() ) { File.read( &TheChar, 1 ); if ( TheChar != '\t' ) { bAtSentence = BcTrue; } if ( TheChar != 10 && TheChar != 13 && bAtSentence ) { *pBuffer = TheChar; ++pBuffer; Ret = ( pBuffer < ( Buffer + 1024 ) ); BcAssert( Ret ); if( !Ret ) { return NULL; } } } // Terminate it. *pBuffer = 0; ++pBuffer; } sscanf( Buffer, "%s", Command ); if ( BcStrLength( Buffer ) == 0 ) { Command[ 0 ] = 0; } switch( ParseMode_ ) { case PM_MAIN: { if( BcStrCompare( "numJoints", Command ) ) { sscanf( Buffer, "numJoints %u", &nJoints_ ); pJoints_ = new MD5_Joint[ nJoints_ ]; } else if( BcStrCompare( "numMeshes", Command ) ) { sscanf( Buffer, "numMeshes %u", &nMeshes_ ); pMeshes_ = new MD5_Mesh[ nMeshes_ ]; } else if( BcStrCompare( "joints", Command ) ) { ParseMode_ = PM_JOINTS; } else if( BcStrCompare( "mesh", Command ) ) { ParseMode_ = PM_MESH; iVert = 0; iInd = 0; iWeight = 0; } } break; case PM_JOINTS: { if( BcStrCompare( "}", Command ) ) { ParseMode_ = PM_MAIN; } else { // Parse a joint off. BcAssert( iJoint < nJoints_ ); MD5_Joint* pJoint = &pJoints_[ iJoint ]; sscanf( Buffer, "%s %i ( %f %f %f ) ( %f %f %f )", pJoint->Name_, &pJoint->ParentID_, &pJoint->TX_, &pJoint->TY_, &pJoint->TZ_, &pJoint->QX_, &pJoint->QY_, &pJoint->QZ_ ); ++iJoint; } } break; case PM_MESH: { if( BcStrCompare( "}", Command ) ) { ++iMesh; ParseMode_ = PM_MAIN; } else { BcAssert( iMesh < nMeshes_ ); MD5_Mesh* pMesh = &pMeshes_[ iMesh ]; if ( BcStrCompare( "shader", Command ) ) { sscanf( Buffer, "shader \"%s", pMesh->Shader_ ); BcU32 i = BcStrLength( pMesh->Shader_ ) - 1; pMesh->Shader_[ i ] = '\0'; } else if ( BcStrCompare( "numverts", Command ) ) { sscanf( Buffer, "numverts %u", &pMesh->nVerts_ ); pMesh->pVerts_ = new MD5_Vert[ pMesh->nVerts_ ]; } else if ( BcStrCompare( "vert", Command ) ) { // Parse a vert off BcAssert( iVert < pMesh->nVerts_ ); MD5_Vert* pVert = &pMesh->pVerts_[ iVert ]; sscanf( Buffer, "vert %i ( %f %f ) %i %i", &pVert->Index_, &pVert->U_, &pVert->V_, &pVert->WeightIndex_, &pVert->nWeights_ ); ++iVert; } else if ( BcStrCompare( "numtris", Command ) ) { sscanf( Buffer, "numtris %u", &pMesh->nIndices_ ); pMesh->nIndices_ *= 3; pMesh->pIndices_ = new BcU32[ pMesh->nIndices_ ]; } else if ( BcStrCompare( "tri", Command ) ) { // Parse a vert off BcAssert( iInd < pMesh->nIndices_ ); BcU32 Index; BcU32* pIndex = &pMesh->pIndices_[ iInd ]; sscanf( Buffer, "tri %i %i %i %i", &Index, &pIndex[0], &pIndex[1], &pIndex[2] ); iInd += 3; } else if ( BcStrCompare( "numweights", Command ) ) { sscanf( Buffer, "numweights %u", &pMesh->nWeights_ ); pMesh->pWeights_ = new MD5_Weight[ pMesh->nWeights_ ]; } else if ( BcStrCompare( "weight", Command ) ) { // Parse a vert off BcAssert( iWeight < pMesh->nWeights_ ); MD5_Weight* pWeight = &pMesh->pWeights_[ iWeight ]; sscanf( Buffer, "weight %i %i %f ( %f %f %f )", &pWeight->Index_, &pWeight->JointID_, &pWeight->Weight_, &pWeight->X_, &pWeight->Y_, &pWeight->Z_ ); ++iWeight; } } } break; } } // Now that we are loaded we can build the node graph. MdlNode* pRootNode = new MdlNode(); pRootNode->name( NodeName ); for( BcU32 i = 0; i < nMeshes_; ++i ) { buildBindPose( pRootNode, i ); } // Parent joints up. //if( nJoints_ > 1 ) { for( BcU32 i = 0; i < nJoints_; ++i ) { MD5_Joint* pJoint = &pJoints_[ i ]; MdlNode* pNode = new MdlNode(); pNode->name( pJoint->Name_ ); pNode->type( eNT_JOINT ); // Build the transform and inverse bind pose. BcQuat JointRot( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f ); JointRot.calcFromXYZ(); BcMat4d JointRotation; BcMat4d JointTranslate; BcMat4d JointTransform; BcMat4d InverseBindpose; JointRot.asMatrix4d( JointRotation ); JointTranslate.identity(); JointTranslate.row3( BcVec4d( pJoint->TX_, pJoint->TY_, pJoint->TZ_, 1.0f ) ); JointTransform = JointRotation * JointTranslate; InverseBindpose = JointTransform; InverseBindpose.inverse(); pNode->absoluteTransform( JointTransform ); pNode->inverseBindpose( InverseBindpose ); if( pJoint->ParentID_ != BcErrorCode ) { pRootNode->parentNode( pNode, pJoints_[ pJoint->ParentID_ ].Name_ ); } else { // Parent to root. pRootNode->parentNode( pNode, pRootNode->name() ); } } } // Cleanup nJoints_ = 0; delete [] pJoints_; pJoints_ = NULL; for( BcU32 i = 0; i < nMeshes_; ++i ) { delete [] pMeshes_[ i ].pIndices_; delete [] pMeshes_[ i ].pVerts_; delete [] pMeshes_[ i ].pWeights_; } nMeshes_ = 0; delete [] pMeshes_; pMeshes_ = NULL; // BcMat4d RootTransform; RootTransform.identity(); pRootNode->makeRelativeTransform( RootTransform ); return pRootNode; }