vrshoot

view libs/assimp/B3DImporter.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
6 Copyright (c) 2006-2012, assimp team
8 All rights reserved.
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the following
12 conditions are met:
14 * Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
18 * Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
23 * Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 ---------------------------------------------------------------------------
40 */
42 /** @file B3DImporter.cpp
43 * @brief Implementation of the b3d importer class
44 */
46 #include "AssimpPCH.h"
47 #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
49 // internal headers
50 #include "B3DImporter.h"
51 #include "TextureTransform.h"
52 #include "ConvertToLHProcess.h"
54 using namespace Assimp;
55 using namespace std;
57 static const aiImporterDesc desc = {
58 "BlitzBasic 3D Importer",
59 "",
60 "",
61 "http://www.blitzbasic.com/",
62 aiImporterFlags_SupportBinaryFlavour,
63 0,
64 0,
65 0,
66 0,
67 "b3d"
68 };
70 // (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings
71 #ifdef _MSC_VER
72 # pragma warning (disable: 4018)
73 #endif
75 //#define DEBUG_B3D
77 // ------------------------------------------------------------------------------------------------
78 bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
80 size_t pos=pFile.find_last_of( '.' );
81 if( pos==string::npos ) return false;
83 string ext=pFile.substr( pos+1 );
84 if( ext.size()!=3 ) return false;
86 return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
87 }
89 // ------------------------------------------------------------------------------------------------
90 // Loader meta information
91 const aiImporterDesc* B3DImporter::GetInfo () const
92 {
93 return &desc;
94 }
96 #ifdef DEBUG_B3D
97 extern "C"{ void _stdcall AllocConsole(); }
98 #endif
99 // ------------------------------------------------------------------------------------------------
100 void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){
102 #ifdef DEBUG_B3D
103 AllocConsole();
104 freopen( "conin$","r",stdin );
105 freopen( "conout$","w",stdout );
106 freopen( "conout$","w",stderr );
107 cout<<"Hello world from the B3DImporter!"<<endl;
108 #endif
110 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
112 // Check whether we can read from the file
113 if( file.get() == NULL)
114 throw DeadlyImportError( "Failed to open B3D file " + pFile + ".");
116 // check whether the .b3d file is large enough to contain
117 // at least one chunk.
118 size_t fileSize = file->FileSize();
119 if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small.");
121 _pos=0;
122 _buf.resize( fileSize );
123 file->Read( &_buf[0],1,fileSize );
124 _stack.clear();
126 ReadBB3D( pScene );
127 }
129 // ------------------------------------------------------------------------------------------------
130 void B3DImporter::Oops(){
131 throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
132 }
134 // ------------------------------------------------------------------------------------------------
135 void B3DImporter::Fail( string str ){
136 #ifdef DEBUG_B3D
137 cout<<"Error in B3D file data: "<<str<<endl;
138 #endif
139 throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str );
140 }
142 // ------------------------------------------------------------------------------------------------
143 int B3DImporter::ReadByte(){
144 if( _pos<_buf.size() ) return _buf[_pos++];
145 Fail( "EOF" );
146 return 0;
147 }
149 // ------------------------------------------------------------------------------------------------
150 int B3DImporter::ReadInt(){
151 if( _pos+4<=_buf.size() ){
152 int n=*(int*)&_buf[_pos];
153 _pos+=4;
154 return n;
155 }
156 Fail( "EOF" );
157 return 0;
158 }
160 // ------------------------------------------------------------------------------------------------
161 float B3DImporter::ReadFloat(){
162 if( _pos+4<=_buf.size() ){
163 float n=*(float*)&_buf[_pos];
164 _pos+=4;
165 return n;
166 }
167 Fail( "EOF" );
168 return 0.0f;
169 }
171 // ------------------------------------------------------------------------------------------------
172 aiVector2D B3DImporter::ReadVec2(){
173 float x=ReadFloat();
174 float y=ReadFloat();
175 return aiVector2D( x,y );
176 }
178 // ------------------------------------------------------------------------------------------------
179 aiVector3D B3DImporter::ReadVec3(){
180 float x=ReadFloat();
181 float y=ReadFloat();
182 float z=ReadFloat();
183 return aiVector3D( x,y,z );
184 }
186 // ------------------------------------------------------------------------------------------------
187 aiQuaternion B3DImporter::ReadQuat(){
188 // (aramis_acg) Fix to adapt the loader to changed quat orientation
189 float w=-ReadFloat();
190 float x=ReadFloat();
191 float y=ReadFloat();
192 float z=ReadFloat();
193 return aiQuaternion( w,x,y,z );
194 }
196 // ------------------------------------------------------------------------------------------------
197 string B3DImporter::ReadString(){
198 string str;
199 while( _pos<_buf.size() ){
200 char c=(char)ReadByte();
201 if( !c ) return str;
202 str+=c;
203 }
204 Fail( "EOF" );
205 return string();
206 }
208 // ------------------------------------------------------------------------------------------------
209 string B3DImporter::ReadChunk(){
210 string tag;
211 for( int i=0;i<4;++i ){
212 tag+=char( ReadByte() );
213 }
214 #ifdef DEBUG_B3D
215 // cout<<"ReadChunk:"<<tag<<endl;
216 #endif
217 unsigned sz=(unsigned)ReadInt();
218 _stack.push_back( _pos+sz );
219 return tag;
220 }
222 // ------------------------------------------------------------------------------------------------
223 void B3DImporter::ExitChunk(){
224 _pos=_stack.back();
225 _stack.pop_back();
226 }
228 // ------------------------------------------------------------------------------------------------
229 unsigned B3DImporter::ChunkSize(){
230 return _stack.back()-_pos;
231 }
232 // ------------------------------------------------------------------------------------------------
234 template<class T>
235 T *B3DImporter::to_array( const vector<T> &v ){
236 if( !v.size() ) return 0;
237 T *p=new T[v.size()];
238 for( size_t i=0;i<v.size();++i ){
239 p[i]=v[i];
240 }
241 return p;
242 }
244 // ------------------------------------------------------------------------------------------------
245 void B3DImporter::ReadTEXS(){
246 while( ChunkSize() ){
247 string name=ReadString();
248 /*int flags=*/ReadInt();
249 /*int blend=*/ReadInt();
250 /*aiVector2D pos=*/ReadVec2();
251 /*aiVector2D scale=*/ReadVec2();
252 /*float rot=*/ReadFloat();
254 _textures.push_back( name );
255 }
256 }
258 // ------------------------------------------------------------------------------------------------
259 void B3DImporter::ReadBRUS(){
260 int n_texs=ReadInt();
261 if( n_texs<0 || n_texs>8 ){
262 Fail( "Bad texture count" );
263 }
264 while( ChunkSize() ){
265 string name=ReadString();
266 aiVector3D color=ReadVec3();
267 float alpha=ReadFloat();
268 float shiny=ReadFloat();
269 /*int blend=**/ReadInt();
270 int fx=ReadInt();
272 aiMaterial *mat=new aiMaterial;
273 _materials.push_back( mat );
275 // Name
276 aiString ainame( name );
277 mat->AddProperty( &ainame,AI_MATKEY_NAME );
279 // Diffuse color
280 mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE );
282 // Opacity
283 mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY );
285 // Specular color
286 aiColor3D speccolor( shiny,shiny,shiny );
287 mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR );
289 // Specular power
290 float specpow=shiny*128;
291 mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS );
293 // Double sided
294 if( fx & 0x10 ){
295 int i=1;
296 mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED );
297 }
299 //Textures
300 for( int i=0;i<n_texs;++i ){
301 int texid=ReadInt();
302 if( texid<-1 || (texid>=0 && texid>=static_cast<int>(_textures.size())) ){
303 Fail( "Bad texture id" );
304 }
305 if( i==0 && texid>=0 ){
306 aiString texname( _textures[texid] );
307 mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
308 }
309 }
310 }
311 }
313 // ------------------------------------------------------------------------------------------------
314 void B3DImporter::ReadVRTS(){
315 _vflags=ReadInt();
316 _tcsets=ReadInt();
317 _tcsize=ReadInt();
318 if( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){
319 Fail( "Bad texcoord data" );
320 }
322 int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
323 int n_verts=ChunkSize()/sz;
325 int v0=_vertices.size();
326 _vertices.resize( v0+n_verts );
328 for( int i=0;i<n_verts;++i ){
329 Vertex &v=_vertices[v0+i];
331 memset( v.bones,0,sizeof(v.bones) );
332 memset( v.weights,0,sizeof(v.weights) );
334 v.vertex=ReadVec3();
336 if( _vflags & 1 ) v.normal=ReadVec3();
338 if( _vflags & 2 ) ReadQuat(); //skip v 4bytes...
340 for( int i=0;i<_tcsets;++i ){
341 float t[4]={0,0,0,0};
342 for( int j=0;j<_tcsize;++j ){
343 t[j]=ReadFloat();
344 }
345 t[1]=1-t[1];
346 if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] );
347 }
348 }
349 }
351 // ------------------------------------------------------------------------------------------------
352 void B3DImporter::ReadTRIS( int v0 ){
353 int matid=ReadInt();
354 if( matid==-1 ){
355 matid=0;
356 }else if( matid<0 || matid>=(int)_materials.size() ){
357 #ifdef DEBUG_B3D
358 cout<<"material id="<<matid<<endl;
359 #endif
360 Fail( "Bad material id" );
361 }
363 aiMesh *mesh=new aiMesh;
364 _meshes.push_back( mesh );
366 mesh->mMaterialIndex=matid;
367 mesh->mNumFaces=0;
368 mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE;
370 int n_tris=ChunkSize()/12;
371 aiFace *face=mesh->mFaces=new aiFace[n_tris];
373 for( int i=0;i<n_tris;++i ){
374 int i0=ReadInt()+v0;
375 int i1=ReadInt()+v0;
376 int i2=ReadInt()+v0;
377 if( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){
378 #ifdef DEBUG_B3D
379 cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl;
380 #endif
381 Fail( "Bad triangle index" );
382 continue;
383 }
384 face->mNumIndices=3;
385 face->mIndices=new unsigned[3];
386 face->mIndices[0]=i0;
387 face->mIndices[1]=i1;
388 face->mIndices[2]=i2;
389 ++mesh->mNumFaces;
390 ++face;
391 }
392 }
394 // ------------------------------------------------------------------------------------------------
395 void B3DImporter::ReadMESH(){
396 /*int matid=*/ReadInt();
398 int v0=_vertices.size();
400 while( ChunkSize() ){
401 string t=ReadChunk();
402 if( t=="VRTS" ){
403 ReadVRTS();
404 }else if( t=="TRIS" ){
405 ReadTRIS( v0 );
406 }
407 ExitChunk();
408 }
409 }
411 // ------------------------------------------------------------------------------------------------
412 void B3DImporter::ReadBONE( int id ){
413 while( ChunkSize() ){
414 int vertex=ReadInt();
415 float weight=ReadFloat();
416 if( vertex<0 || vertex>=(int)_vertices.size() ){
417 Fail( "Bad vertex index" );
418 }
420 Vertex &v=_vertices[vertex];
421 int i;
422 for( i=0;i<4;++i ){
423 if( !v.weights[i] ){
424 v.bones[i]=id;
425 v.weights[i]=weight;
426 break;
427 }
428 }
429 #ifdef DEBUG_B3D
430 if( i==4 ){
431 cout<<"Too many bone weights"<<endl;
432 }
433 #endif
434 }
435 }
437 // ------------------------------------------------------------------------------------------------
438 void B3DImporter::ReadKEYS( aiNodeAnim *nodeAnim ){
439 vector<aiVectorKey> trans,scale;
440 vector<aiQuatKey> rot;
441 int flags=ReadInt();
442 while( ChunkSize() ){
443 int frame=ReadInt();
444 if( flags & 1 ){
445 trans.push_back( aiVectorKey( frame,ReadVec3() ) );
446 }
447 if( flags & 2 ){
448 scale.push_back( aiVectorKey( frame,ReadVec3() ) );
449 }
450 if( flags & 4 ){
451 rot.push_back( aiQuatKey( frame,ReadQuat() ) );
452 }
453 }
455 if( flags & 1 ){
456 nodeAnim->mNumPositionKeys=trans.size();
457 nodeAnim->mPositionKeys=to_array( trans );
458 }
460 if( flags & 2 ){
461 nodeAnim->mNumScalingKeys=scale.size();
462 nodeAnim->mScalingKeys=to_array( scale );
463 }
465 if( flags & 4 ){
466 nodeAnim->mNumRotationKeys=rot.size();
467 nodeAnim->mRotationKeys=to_array( rot );
468 }
469 }
471 // ------------------------------------------------------------------------------------------------
472 void B3DImporter::ReadANIM(){
473 /*int flags=*/ReadInt();
474 int frames=ReadInt();
475 float fps=ReadFloat();
477 aiAnimation *anim=new aiAnimation;
478 _animations.push_back( anim );
480 anim->mDuration=frames;
481 anim->mTicksPerSecond=fps;
482 }
484 // ------------------------------------------------------------------------------------------------
485 aiNode *B3DImporter::ReadNODE( aiNode *parent ){
487 string name=ReadString();
488 aiVector3D t=ReadVec3();
489 aiVector3D s=ReadVec3();
490 aiQuaternion r=ReadQuat();
492 aiMatrix4x4 trans,scale,rot;
494 aiMatrix4x4::Translation( t,trans );
495 aiMatrix4x4::Scaling( s,scale );
496 rot=aiMatrix4x4( r.GetMatrix() );
498 aiMatrix4x4 tform=trans * rot * scale;
500 int nodeid=_nodes.size();
502 aiNode *node=new aiNode( name );
503 _nodes.push_back( node );
505 node->mParent=parent;
506 node->mTransformation=tform;
508 aiNodeAnim *nodeAnim=0;
509 vector<unsigned> meshes;
510 vector<aiNode*> children;
512 while( ChunkSize() ){
513 string t=ReadChunk();
514 if( t=="MESH" ){
515 int n=_meshes.size();
516 ReadMESH();
517 for( int i=n;i<(int)_meshes.size();++i ){
518 meshes.push_back( i );
519 }
520 }else if( t=="BONE" ){
521 ReadBONE( nodeid );
522 }else if( t=="ANIM" ){
523 ReadANIM();
524 }else if( t=="KEYS" ){
525 if( !nodeAnim ){
526 nodeAnim=new aiNodeAnim;
527 _nodeAnims.push_back( nodeAnim );
528 nodeAnim->mNodeName=node->mName;
529 }
530 ReadKEYS( nodeAnim );
531 }else if( t=="NODE" ){
532 aiNode *child=ReadNODE( node );
533 children.push_back( child );
534 }
535 ExitChunk();
536 }
538 node->mNumMeshes=meshes.size();
539 node->mMeshes=to_array( meshes );
541 node->mNumChildren=children.size();
542 node->mChildren=to_array( children );
544 return node;
545 }
547 // ------------------------------------------------------------------------------------------------
548 void B3DImporter::ReadBB3D( aiScene *scene ){
550 _textures.clear();
551 _materials.size();
553 _vertices.clear();
554 _meshes.clear();
556 _nodes.clear();
557 _nodeAnims.clear();
558 _animations.clear();
560 string t=ReadChunk();
561 if( t=="BB3D" ){
562 int version=ReadInt();
564 if (!DefaultLogger::isNullLogger()) {
565 char dmp[128];
566 sprintf(dmp,"B3D file format version: %i",version);
567 DefaultLogger::get()->info(dmp);
568 }
570 while( ChunkSize() ){
571 string t=ReadChunk();
572 if( t=="TEXS" ){
573 ReadTEXS();
574 }else if( t=="BRUS" ){
575 ReadBRUS();
576 }else if( t=="NODE" ){
577 ReadNODE( 0 );
578 }
579 ExitChunk();
580 }
581 }
582 ExitChunk();
584 if( !_nodes.size() ) Fail( "No nodes" );
586 if( !_meshes.size() ) Fail( "No meshes" );
588 //Fix nodes/meshes/bones
589 for(size_t i=0;i<_nodes.size();++i ){
590 aiNode *node=_nodes[i];
592 for( size_t j=0;j<node->mNumMeshes;++j ){
593 aiMesh *mesh=_meshes[node->mMeshes[j]];
595 int n_tris=mesh->mNumFaces;
596 int n_verts=mesh->mNumVertices=n_tris * 3;
598 aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0;
599 if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ];
600 if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
602 aiFace *face=mesh->mFaces;
604 vector< vector<aiVertexWeight> > vweights( _nodes.size() );
606 for( int i=0;i<n_verts;i+=3 ){
607 for( int j=0;j<3;++j ){
608 Vertex &v=_vertices[face->mIndices[j]];
610 *mv++=v.vertex;
611 if( mn ) *mn++=v.normal;
612 if( mc ) *mc++=v.texcoords;
614 face->mIndices[j]=i+j;
616 for( int k=0;k<4;++k ){
617 if( !v.weights[k] ) break;
619 int bone=v.bones[k];
620 float weight=v.weights[k];
622 vweights[bone].push_back( aiVertexWeight(i+j,weight) );
623 }
624 }
625 ++face;
626 }
628 vector<aiBone*> bones;
629 for(size_t i=0;i<vweights.size();++i ){
630 vector<aiVertexWeight> &weights=vweights[i];
631 if( !weights.size() ) continue;
633 aiBone *bone=new aiBone;
634 bones.push_back( bone );
636 aiNode *bnode=_nodes[i];
638 bone->mName=bnode->mName;
639 bone->mNumWeights=weights.size();
640 bone->mWeights=to_array( weights );
642 aiMatrix4x4 mat=bnode->mTransformation;
643 while( bnode->mParent ){
644 bnode=bnode->mParent;
645 mat=bnode->mTransformation * mat;
646 }
647 bone->mOffsetMatrix=mat.Inverse();
648 }
649 mesh->mNumBones=bones.size();
650 mesh->mBones=to_array( bones );
651 }
652 }
654 //nodes
655 scene->mRootNode=_nodes[0];
657 //material
658 if( !_materials.size() ){
659 _materials.push_back( new aiMaterial );
660 }
661 scene->mNumMaterials=_materials.size();
662 scene->mMaterials=to_array( _materials );
664 //meshes
665 scene->mNumMeshes=_meshes.size();
666 scene->mMeshes=to_array( _meshes );
668 //animations
669 if( _animations.size()==1 && _nodeAnims.size() ){
671 aiAnimation *anim=_animations.back();
672 anim->mNumChannels=_nodeAnims.size();
673 anim->mChannels=to_array( _nodeAnims );
675 scene->mNumAnimations=_animations.size();
676 scene->mAnimations=to_array( _animations );
677 }
679 // convert to RH
680 MakeLeftHandedProcess makeleft;
681 makeleft.Execute( scene );
683 FlipWindingOrderProcess flip;
684 flip.Execute( scene );
685 }
687 #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER