#include "std.hpp" #include "loader_x.hpp" #include "meshmodel.hpp" #include "animation.hpp" #include "pivot.hpp" #include //#include #include "../gxruntime/GraphicsRuntime.hpp" #include #include #include #include extern gxRuntime *gx_runtime; static map frames_map; static int anim_len; static bool conv,flip_tris; static Transform conv_tform; static bool collapse,animonly; static void parseAnimKey(ID3DXFileData *fileData, MeshModel *e) { DWORD sz;int *data; if( fileData->GetData( 0,&sz,(void**)&data )<0 ) return; int type=*data++; int cnt=*data++; Animation anim=e->getAnimation(); for( int k=0;kanim_len ) anim_len=time; switch( type ){ case 0: if( n==4 ){ Quat rot=*(Quat*)data; if( conv ){ if( fabs(rot.w)<1-FLT_EPSILON ){ rot.normalize(); //quat-to-axis/angle float half=acosf( rot.w ); if( flip_tris ) half=-half; rot=Quat( cosf( half ),(conv_tform.m*rot.v).normalized()*sinf( half ) ); }else rot=Quat(); } anim.setRotationKey( time,rot ); } break; case 1: if( n==3 ){ Vector scl=*(Vector*)data; if( conv ) scl=conv_tform.m * scl; scl.x=fabs(scl.x);scl.y=fabs(scl.y);scl.z=fabs(scl.z); anim.setScaleKey( time,scl ); } break; case 2: if( n==3 ){ Vector pos=*(Vector*)data; if( conv ) pos=conv_tform*pos; anim.setPositionKey( time,pos ); } break; } data+=n; } e->setAnimation( anim ); } static void parseAnim(ID3DXFileData *fileData) { const GUID *guid; IDirectXFileObject *childObj; IDirectXFileData *childData; IDirectXFileDataReference *childRef; MeshModel *frame=0; //find the frame reference for( ;fileData->GetNextObject( &childObj )>=0;childObj->Release() ){ if( childObj->QueryInterface( IID_IDirectXFileDataReference,(void**)&childRef )>=0 ){ if( childRef->Resolve( &childData )>=0 ){ if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMFrame ){ char name[80];DWORD len=80; if( childData->GetName( name,&len )>=0 ){ map::iterator it=frames_map.find( name ); if( it!=frames_map.end() ) frame=it->second; } } } childData->Release(); } childRef->Release(); }else if( frame && childObj->QueryInterface( IID_IDirectXFileData,(void**)&childData )>=0 ){ if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMAnimationKey ){ parseAnimKey( childData,frame ); } } childData->Release(); } } } static void parseAnimSet( IDirectXFileData *fileData ){ const GUID *guid; IDirectXFileObject *childObj; IDirectXFileData *childData; for( ;fileData->GetNextObject( &childObj )>=0;childObj->Release() ){ if( childObj->QueryInterface( IID_IDirectXFileData,(void**)&childData )<0 ) continue; if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMAnimation ){ parseAnim( childData ); } } childData->Release(); } } static Brush parseMaterial( IDirectXFileData *fileData ){ const GUID *guid; IDirectXFileObject *childObj; IDirectXFileData *childData; Brush brush; DWORD sz;float *data; if( fileData->GetData( 0,&sz,(void**)&data )<0 ) return brush; brush.setColor( Vector( data[0],data[1],data[2] ) ); if( data[3] ) brush.setAlpha( data[3] ); for( ;fileData->GetNextObject( &childObj )>=0;childObj->Release() ){ if( childObj->QueryInterface( IID_IDirectXFileData,(void**)&childData )<0 ) continue; if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMTextureFilename ){ DWORD sz;char **data; if( childData->GetData( 0,&sz,(void**)&data )>=0 ){ brush.setTexture( 0,Texture( *data,0 ),0 ); brush.setColor( Vector( 1,1,1 ) ); } } } childData->Release(); } return brush; } static void parseMaterialList( IDirectXFileData *fileData,vector &mats ){ const GUID *guid; IDirectXFileObject *childObj; IDirectXFileData *childData; IDirectXFileDataReference *childRef; //iterate through child objects... for( ;fileData->GetNextObject( &childObj )>=0;childObj->Release() ){ if( childObj->QueryInterface( IID_IDirectXFileData,(void**)&childData )>=0 ){ if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMMaterial ){ mats.push_back( parseMaterial( childData ) ); } } childData->Release(); }else if( childObj->QueryInterface( IID_IDirectXFileDataReference,(void**)&childRef )>=0 ){ if( childRef->Resolve( &childData )>=0 ){ if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMMaterial ){ mats.push_back( parseMaterial( childData ) ); } } childData->Release(); } childRef->Release(); } } } struct FaceX{ int *data,mat_index; FaceX( int *d ):data(d),mat_index(0){} }; static void parseMesh( IDirectXFileData *fileData,MeshModel *mesh ){ const GUID *guid; IDirectXFileObject *childObj; IDirectXFileData *childData; DWORD sz;int *data; if( fileData->GetData( 0,&sz,(void**)&data )<0 ) return; //stuff... vector faces; vector mats; MeshLoader::beginMesh(); //setup vertices int num_verts=*data++; int k; for( k=0;kGetNextObject( &childObj )>=0;childObj->Release() ){ if( childObj->QueryInterface( IID_IDirectXFileData,(void**)&childData )<0 ) continue; if( childData->GetType( &guid )>=0 ){ DWORD sz;int *data; if( childData->GetData( 0,&sz,(void**)&data )>=0 ){ if( *guid==TID_D3DRMMeshMaterialList ){ int num_mats=*data++; int num_faces=*data++; for( int k=0;kRelease(); } if( !mats.size() ) mats.push_back( Brush() ); for( size_t k=0;kupdateNormals(); } static MeshModel *parseFrame( IDirectXFileData *fileData ){ MeshModel *e=new MeshModel(); const GUID *guid; IDirectXFileObject *childObj; IDirectXFileData *childData; char name[80];DWORD len=80; if( fileData->GetName( name,&len )<0 ) return e; e->SetName( name ); frames_map[name]=e; //iterate through child objects... for( ;fileData->GetNextObject( &childObj )>=0;childObj->Release() ){ if( childObj->QueryInterface( IID_IDirectXFileData,(void**)&childData )<0 ) continue; if( childData->GetType( &guid )>=0 ){ if( *guid==TID_D3DRMFrameTransformMatrix ){ DWORD size;D3DMATRIX *data; if( childData->GetData( 0,&size,(void**)&data )>=0 ){ Transform tform=Transform( Matrix( Vector( data->_11,data->_12,data->_13 ), Vector( data->_21,data->_22,data->_23 ), Vector( data->_31,data->_32,data->_33 ) ), Vector( data->_41,data->_42,data->_43 ) ); if( conv ) tform=conv_tform * tform * -conv_tform; e->SetLocalTransform( tform ); } }else if( *guid==TID_D3DRMMesh ){ if( !animonly ) parseMesh( childData,e ); }else if( *guid==TID_D3DRMFrame ){ MeshModel *t=parseFrame( childData ); t->SetParent( e ); } } childData->Release(); } return e; } static MeshModel *parseFile( const string &file ){ const GUID *guid; IDirectXFile *xfile; IDirectXFileData *fileData; IDirectXFileEnumObject *enumObj; if( DirectXFileCreate( &xfile )<0 ) return 0; if( xfile->RegisterTemplates( (VOID*)D3DRM_XTEMPLATES,D3DRM_XTEMPLATE_BYTES )<0 ){ xfile->Release();return 0; } if( xfile->CreateEnumObject( (void*)file.c_str(),DXFILELOAD_FROMFILE,&enumObj )<0 ){ xfile->Release();return 0; } anim_len=0; MeshModel *e=new MeshModel(); for( ;enumObj->GetNextDataObject( &fileData )>=0;fileData->Release() ){ if( fileData->GetType( &guid )<0 ) continue; if( *guid==TID_D3DRMMesh ){ if( !animonly) parseMesh( fileData,e ); }else if( *guid==TID_D3DRMFrame ){ MeshModel *t=parseFrame( fileData ); t->SetParent( e ); }else if( *guid==TID_D3DRMAnimationSet ){ if( !collapse ) parseAnimSet( fileData ); } } if( !collapse ){ e->setAnimator( new Animator( e,anim_len ) ); } enumObj->Release(); xfile->Release(); return e; } MeshModel *Loader_X::load( const string &filename,const Transform &t,int hint ){ conv_tform=t; conv=flip_tris=false; if( conv_tform!=Transform() ){ conv=true; if( conv_tform.m.i.cross(conv_tform.m.j).dot(conv_tform.m.k)<0 ) flip_tris=true; } collapse=!!(hint&MeshLoader::HINT_COLLAPSE); animonly=!!(hint&MeshLoader::HINT_ANIMONLY); MeshModel *e=parseFile( filename ); frames_map.clear(); return e; }