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