From a2418291496d30c147d79ffc4af0df432e880163 Mon Sep 17 00:00:00 2001 From: marksibly Date: Tue, 2 Jun 2009 05:08:24 +0000 Subject: [PATCH] Implemented anims/bones git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@427 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/B3DImporter.cpp | 496 +++++++++++++++++++++++++++++++------------ code/B3DImporter.h | 49 +++-- 2 files changed, 397 insertions(+), 148 deletions(-) diff --git a/code/B3DImporter.cpp b/code/B3DImporter.cpp index 5fce720e1..56acdeafd 100644 --- a/code/B3DImporter.cpp +++ b/code/B3DImporter.cpp @@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; using namespace std; +//#define DEBUG_B3D + // ------------------------------------------------------------------------------------------------ bool B3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const{ @@ -71,9 +73,20 @@ void B3DImporter::GetExtensionList( std::string& append ){ append.append("*.b3d"); } +#ifdef DEBUG_B3D + extern "C"{ void _stdcall AllocConsole(); } +#endif // ------------------------------------------------------------------------------------------------ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){ +#ifdef DEBUG_B3D + AllocConsole(); + freopen( "conin$","r",stdin ); + freopen( "conout$","w",stdout ); + freopen( "conout$","w",stderr ); + cout<<"Hello world from the B3DImporter!"< file( pIOHandler->Open( pFile)); // Check whether we can read from the file @@ -89,57 +102,27 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS _buf.resize( fileSize ); file->Read( &_buf[0],1,fileSize ); _stack.clear(); - _textures.clear(); - _materials.size(); - _vertices.clear(); - _meshes.clear(); - ReadBB3D(); - - //materials - if( _materials.size() ){ - aiMaterial **mats=new aiMaterial*[_materials.size()]; - for( unsigned i=0;i<_materials.size();++i ){ - mats[i]=_materials[i]; - } - pScene->mNumMaterials=_materials.size(); - pScene->mMaterials=mats; - } - - //meshes - if( _meshes.size() ){ - aiMesh **meshes=new aiMesh*[_meshes.size()]; - for( unsigned i=0;i<_meshes.size();++i ){ - meshes[i]=_meshes[i]; - } - pScene->mNumMeshes=_meshes.size(); - pScene->mMeshes=meshes; - }else{ - throw new ImportErrorException( "B3D: No meshes loaded" ); - } + ReadBB3D( pScene ); +} - //create root node - aiNode *node=new aiNode( "root" ); - - node->mNumMeshes=_meshes.size(); - node->mMeshes=new unsigned[_meshes.size()]; - for( unsigned i=0;i<_meshes.size();++i ){ - node->mMeshes[i]=i; - } - pScene->mRootNode=node; +// ------------------------------------------------------------------------------------------------ +void B3DImporter::Oops(){ + throw new ImportErrorException( "B3D Importer - INTERNAL ERROR" ); +} - // convert to RH - MakeLeftHandedProcess monster_maker; - monster_maker.Execute(pScene); - - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); +// ------------------------------------------------------------------------------------------------ +void B3DImporter::Fail( string str ){ +#ifdef DEBUG_B3D + cout<<"Error in B3D file data: "< +T *B3DImporter::to_array( const vector &v ){ + if( !v.size() ) return 0; + T *p=new T[v.size()]; + for( int i=0;i8 ){ + Fail( "Bad texture count" ); + } while( ChunkSize() ){ string name=ReadString(); - Vec4 color=ReadVec4(); + aiVector3D color=ReadVec3(); + float alpha=ReadFloat(); float shiny=ReadFloat(); int blend=ReadInt(); int fx=ReadInt(); @@ -257,11 +252,10 @@ void B3DImporter::ReadBRUS(){ mat->AddProperty( &ainame,AI_MATKEY_NAME ); // Diffuse color - aiColor3D diffcolor( color.x,color.y,color.z ); - mat->AddProperty( &diffcolor,1,AI_MATKEY_COLOR_DIFFUSE ); + mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE ); // Opacity - mat->AddProperty( &color.w,1,AI_MATKEY_OPACITY ); + mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY ); // Specular color aiColor3D speccolor( shiny,shiny,shiny ); @@ -280,10 +274,11 @@ void B3DImporter::ReadBRUS(){ //Textures for( int i=0;i=0 && texid<(int)_textures.size() ){ - //just use tex 0 for now - const Texture &tex=_textures[texid]; - aiString texname( tex.name ); + if( texid<-1 || (texid>=0 && texid>=_textures.size()) ){ + Fail( "Bad texture id" ); + } + if( i==0 && texid>=0 ){ + aiString texname( _textures[texid] ); mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) ); } } @@ -292,75 +287,80 @@ void B3DImporter::ReadBRUS(){ // ------------------------------------------------------------------------------------------------ void B3DImporter::ReadVRTS(){ - _vertFlags=ReadInt(); - _tcSets=ReadInt(); - _tcSize=ReadInt(); + _vflags=ReadInt(); + _tcsets=ReadInt(); + _tcsize=ReadInt(); + if( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){ + Fail( "Bad texcoord data" ); + } - if( _tcSets<0 || _tcSets>4 || _tcSize<0 || _tcSize>4 ) throw new ImportErrorException( "B3D Param Error" ); + int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4); + int n_verts=ChunkSize()/sz; - while( ChunkSize() ){ - Vertex vert; + _vertices.clear(); + _vertices.resize( n_verts ); - vert.position=ReadVec3(); + for( int i=0;i=_materials.size() ){ +#ifdef DEBUG_B3D + cout<<"material id="<mMaterialIndex=matid; - mesh->mNumVertices=n_verts; mesh->mNumFaces=n_tris; mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE; - aiVector3D *mv,*mn=0,*mc=0; - - mv=mesh->mVertices=new aiVector3D[n_verts]; - if( _vertFlags & 1 ) mn=mesh->mNormals=new aiVector3D[n_verts]; - if( _tcSets ) mc=mesh->mTextureCoords[0]=new aiVector3D[n_verts]; - aiFace *face=mesh->mFaces=new aiFace[n_tris]; - for( unsigned i=0;imNumIndices=3; - unsigned *ip=face->mIndices=new unsigned[3]; - int v[3]; - v[0]=ReadInt(); - v[1]=ReadInt(); - v[2]=ReadInt(); - for( unsigned j=0;j<3;++j ){ - int k=v[j]; - const Vertex &v=_vertices[k]; - memcpy( mv++,&v.position.x,12 ); - if( mn ) memcpy( mn++,&v.normal.x,12 ); - if( mc ) memcpy( mc++,&v.texcoords.x,12 ); - *ip++=i+j; + for( int i=0;i=_vertices.size() || i1<0 || i1>=_vertices.size() || i2<0 || i2>=_vertices.size() ){ +#ifdef DEBUG_B3D + cout<<"i0="<mNumIndices=3; + face->mIndices=new unsigned[3]; + face->mIndices[0]=i0; + face->mIndices[1]=i1; + face->mIndices[2]=i2; ++face; } } @@ -369,40 +369,168 @@ void B3DImporter::ReadTRIS(){ void B3DImporter::ReadMESH(){ int matid=ReadInt(); - _vertices.clear(); - + int v0=_vertices.size(); + while( ChunkSize() ){ string t=ReadChunk(); if( t=="VRTS" ){ ReadVRTS(); }else if( t=="TRIS" ){ - ReadTRIS(); + ReadTRIS( v0 ); } ExitChunk(); } - - _vertices.clear(); } // ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadNODE(){ +void B3DImporter::ReadBONE( int id ){ + while( ChunkSize() ){ + int vertex=ReadInt(); + float weight=ReadFloat(); + if( vertex<0 || vertex>=_vertices.size() ){ + Fail( "Bad vertex index" ); + } + + Vertex &v=_vertices[vertex]; + int i; + for( i=0;i<4;++i ){ + if( !v.weights[i] ){ + v.bones[i]=id; + v.weights[i]=weight; + break; + } + } +#ifdef DEBUG_B3D + if( i==4 ){ + cout<<"Too many bone weights"< trans,scale; + vector rot; + int flags=ReadInt(); + while( ChunkSize() ){ + int frame=ReadInt(); + if( flags & 1 ){ + trans.push_back( aiVectorKey( frame,ReadVec3() ) ); + } + if( flags & 2 ){ + scale.push_back( aiVectorKey( frame,ReadVec3() ) ); + } + if( flags & 4 ){ + rot.push_back( aiQuatKey( frame,ReadQuat() ) ); + } + } + + if( flags & 1 ){ + nodeAnim->mNumPositionKeys=trans.size(); + nodeAnim->mPositionKeys=to_array( trans ); + } + + if( flags & 2 ){ + nodeAnim->mNumScalingKeys=scale.size(); + nodeAnim->mScalingKeys=to_array( scale ); + } + + if( flags & 4 ){ + nodeAnim->mNumRotationKeys=rot.size(); + nodeAnim->mRotationKeys=to_array( rot ); + } +} + +// ------------------------------------------------------------------------------------------------ +void B3DImporter::ReadANIM(){ + int flags=ReadInt(); + int frames=ReadInt(); + float fps=ReadFloat(); + + aiAnimation *anim=new aiAnimation; + _animations.push_back( anim ); + + anim->mDuration=frames; + anim->mTicksPerSecond=fps; +} + +// ------------------------------------------------------------------------------------------------ +aiNode *B3DImporter::ReadNODE( aiNode *parent ){ string name=ReadString(); - Vec3 trans=ReadVec3(); - Vec3 scale=ReadVec3(); - Vec4 rot=ReadVec4(); + aiVector3D t=ReadVec3(); + aiVector3D s=ReadVec3(); + aiQuaternion r=ReadQuat(); + + aiMatrix4x4 trans,scale,rot; + + aiMatrix4x4::Translation( t,trans ); + aiMatrix4x4::Scaling( s,scale ); + rot=aiMatrix4x4( r.GetMatrix() ); + + aiMatrix4x4 tform=trans * rot * scale; + + int nodeid=_nodes.size(); + + aiNode *node=new aiNode( name ); + _nodes.push_back( node ); + + node->mParent=parent; + node->mTransformation=tform; + + aiNodeAnim *nodeAnim=0; + vector meshes; + vector children; while( ChunkSize() ){ string t=ReadChunk(); if( t=="MESH" ){ + int n=_meshes.size(); ReadMESH(); + for( int i=n;i<_meshes.size();++i ){ + meshes.push_back( i ); + } + }else if( t=="BONE" ){ + ReadBONE( nodeid ); + }else if( t=="ANIM" ){ + ReadANIM(); + }else if( t=="KEYS" ){ + if( !nodeAnim ){ + nodeAnim=new aiNodeAnim; + _nodeAnims.push_back( nodeAnim ); + nodeAnim->mNodeName=node->mName; + } + ReadKEYS( nodeAnim ); + }else if( t=="NODE" ){ + aiNode *child=ReadNODE( node ); + children.push_back( child ); } ExitChunk(); } + + node->mNumMeshes=meshes.size(); + node->mMeshes=to_array( meshes ); + + node->mNumChildren=children.size(); + node->mChildren=to_array( children ); + + return node; } // ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadBB3D(){ +void B3DImporter::ReadBB3D( aiScene *scene ){ + + _textures.clear(); + _materials.size(); + + _vertices.clear(); + _meshes.clear(); + + _nodes.clear(); + _nodeAnims.clear(); + _animations.clear(); + string t=ReadChunk(); if( t=="BB3D" ){ int version=ReadInt(); @@ -413,12 +541,114 @@ void B3DImporter::ReadBB3D(){ }else if( t=="BRUS" ){ ReadBRUS(); }else if( t=="NODE" ){ - ReadNODE(); + ReadNODE( 0 ); } ExitChunk(); } } ExitChunk(); + + if( !_nodes.size() ) Fail( "No nodes" ); + + if( !_meshes.size() ) Fail( "No meshes" ); + + //Fix nodes/meshes/bones + for( int i=0;i<_nodes.size();++i ){ + aiNode *node=_nodes[i]; + + for( int j=0;jmNumMeshes;++j ){ + aiMesh *mesh=_meshes[node->mMeshes[j]]; + + int n_tris=mesh->mNumFaces; + int n_verts=mesh->mNumVertices=n_tris * 3; + + aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0; + if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ]; + if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ]; + + aiFace *face=mesh->mFaces; + + vector< vector > vweights( _nodes.size() ); + + for( int i=0;imIndices[j]]; + + *mv++=v.vertex; + if( mn ) *mn++=v.normal; + if( mc ) *mc++=v.texcoords; + + face->mIndices[j]=i+j; + + for( int k=0;k<4;++k ){ + if( !v.weights[k] ) break; + + int bone=v.bones[k]; + float weight=v.weights[k]; + + vweights[bone].push_back( aiVertexWeight(i+j,weight) ); + } + } + ++face; + } + + vector bones; + for( int i=0;i &weights=vweights[i]; + if( !weights.size() ) continue; + + aiBone *bone=new aiBone; + bones.push_back( bone ); + + aiNode *bnode=_nodes[i]; + + bone->mName=bnode->mName; + bone->mNumWeights=weights.size(); + bone->mWeights=to_array( weights ); + + aiMatrix4x4 mat=bnode->mTransformation; + while( bnode->mParent ){ + bnode=bnode->mParent; + mat=bnode->mTransformation * mat; + } + bone->mOffsetMatrix=mat.Inverse(); + } + mesh->mNumBones=bones.size(); + mesh->mBones=to_array( bones ); + } + } + + //nodes + scene->mRootNode=_nodes[0]; + + //materials + if( !_materials.size() ){ + _materials.push_back( new MaterialHelper ); + } + scene->mNumMaterials=_materials.size(); + scene->mMaterials=to_array( _materials ); + + //meshes + scene->mNumMeshes=_meshes.size(); + scene->mMeshes=to_array( _meshes ); + + //animations + if( _animations.size()==1 && _nodeAnims.size() ){ + + aiAnimation *anim=_animations.back(); + anim->mNumChannels=_nodeAnims.size(); + anim->mChannels=to_array( _nodeAnims ); + + scene->mNumAnimations=_animations.size(); + scene->mAnimations=to_array( _animations ); + } + + // convert to RH + MakeLeftHandedProcess makeleft; + makeleft.Execute( scene ); + + FlipWindingOrderProcess flip; + flip.Execute( scene ); } #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER diff --git a/code/B3DImporter.h b/code/B3DImporter.h index 71f0114cf..478de1f1e 100644 --- a/code/B3DImporter.h +++ b/code/B3DImporter.h @@ -65,41 +65,60 @@ protected: private: - struct Vec2{ float x,y; }; - struct Vec3{ float x,y,z; }; - struct Vec4{ float x,y,z,w; }; - struct Texture{ std::string name; }; - struct Vertex{ Vec3 position,normal,texcoords; }; - int ReadByte(); int ReadInt(); float ReadFloat(); - Vec2 ReadVec2(); - Vec3 ReadVec3(); - Vec4 ReadVec4(); + aiVector2D ReadVec2(); + aiVector3D ReadVec3(); + aiQuaternion ReadQuat(); std::string ReadString(); std::string ReadChunk(); void ExitChunk(); unsigned ChunkSize(); + template + T *to_array( const std::vector &v ); + + struct Vertex{ + aiVector3D vertex; + aiVector3D normal; + aiVector3D texcoords; + unsigned char bones[4]; + float weights[4]; + }; + + void Oops(); + void Fail( std::string str ); + void ReadTEXS(); void ReadBRUS(); + void ReadVRTS(); - void ReadTRIS(); + void ReadTRIS( int v0 ); void ReadMESH(); - void ReadNODE(); - void ReadBB3D(); + void ReadBONE( int id ); + void ReadKEYS( aiNodeAnim *nodeAnim ); + void ReadANIM(); + + aiNode *ReadNODE( aiNode *parent ); + + void ReadBB3D( aiScene *scene ); unsigned _pos; unsigned _size; std::vector _buf; std::vector _stack; - int _vertFlags,_tcSets,_tcSize; - std::vector _textures; - std::vector _materials; + std::vector _textures; + std::vector _materials; + + int _vflags,_tcsets,_tcsize; std::vector _vertices; + + std::vector _nodes; std::vector _meshes; + std::vector _nodeAnims; + std::vector _animations; }; }