]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CB3DMeshFileLoader.cpp
Merging r5975 through r6036 from trunk to ogl-es branch.
[irrlicht.git] / source / Irrlicht / CB3DMeshFileLoader.cpp
1 // Copyright (C) 2006-2012 Luke Hoschke\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 // B3D Mesh loader\r
6 // File format designed by Mark Sibly for the Blitz3D engine and has been\r
7 // declared public domain\r
8 \r
9 #include "IrrCompileConfig.h"\r
10 #ifdef _IRR_COMPILE_WITH_B3D_LOADER_\r
11 \r
12 #include "CB3DMeshFileLoader.h"\r
13 #include "CMeshTextureLoader.h"\r
14 \r
15 #include "IVideoDriver.h"\r
16 #include "IFileSystem.h"\r
17 #include "os.h"\r
18 \r
19 #ifdef _DEBUG\r
20 #define _B3D_READER_DEBUG\r
21 #endif\r
22 \r
23 namespace irr\r
24 {\r
25 namespace scene\r
26 {\r
27 \r
28 //! Constructor\r
29 CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr)\r
30 : SceneManager(smgr), AnimatedMesh(0), B3DFile(0), NormalsInFile(false),\r
31         HasVertexColors(false), ShowWarning(true)\r
32 {\r
33         #ifdef _DEBUG\r
34         setDebugName("CB3DMeshFileLoader");\r
35         #endif\r
36 \r
37         TextureLoader = new CMeshTextureLoader( SceneManager->getFileSystem(), SceneManager->getVideoDriver() );\r
38 }\r
39 \r
40 \r
41 //! returns true if the file maybe is able to be loaded by this class\r
42 //! based on the file extension (e.g. ".bsp")\r
43 bool CB3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const\r
44 {\r
45         return core::hasFileExtension ( filename, "b3d" );\r
46 }\r
47 \r
48 \r
49 //! creates/loads an animated mesh from the file.\r
50 //! \return Pointer to the created mesh. Returns 0 if loading failed.\r
51 //! If you no longer need the mesh, you should call IAnimatedMesh::drop().\r
52 //! See IReferenceCounted::drop() for more information.\r
53 IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* file)\r
54 {\r
55         if (!file)\r
56                 return 0;\r
57 \r
58         if ( getMeshTextureLoader() )\r
59                 getMeshTextureLoader()->setMeshFile(file);\r
60 \r
61         B3DFile = file;\r
62         AnimatedMesh = new scene::CSkinnedMesh();\r
63         ShowWarning = true; // If true a warning is issued if too many textures are used\r
64         VerticesStart=0;\r
65 \r
66         if ( load() )\r
67         {\r
68                 AnimatedMesh->finalize();\r
69         }\r
70         else\r
71         {\r
72                 AnimatedMesh->drop();\r
73                 AnimatedMesh = 0;\r
74         }\r
75 \r
76         return AnimatedMesh;\r
77 }\r
78 \r
79 \r
80 bool CB3DMeshFileLoader::load()\r
81 {\r
82         B3dStack.clear();\r
83 \r
84         NormalsInFile=false;\r
85         HasVertexColors=false;\r
86 \r
87         //------ Get header ------\r
88 \r
89         SB3dChunkHeader header;\r
90         B3DFile->read(&header, sizeof(header));\r
91 #ifdef __BIG_ENDIAN__\r
92         header.size = os::Byteswap::byteswap(header.size);\r
93 #endif\r
94 \r
95         if ( strncmp( header.name, "BB3D", 4 ) != 0 )\r
96         {\r
97                 os::Printer::log("File is not a b3d file. Loading failed (No header found)", B3DFile->getFileName(), ELL_ERROR);\r
98                 return false;\r
99         }\r
100 \r
101         // Add main chunk...\r
102         B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));\r
103 \r
104         // Get file version, but ignore it, as it's not important with b3d files...\r
105         s32 fileVersion;\r
106         B3DFile->read(&fileVersion, sizeof(fileVersion));\r
107 #ifdef __BIG_ENDIAN__\r
108         fileVersion = os::Byteswap::byteswap(fileVersion);\r
109 #endif\r
110 \r
111         //------ Read main chunk ------\r
112 \r
113         while ( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos() )\r
114         {\r
115                 B3DFile->read(&header, sizeof(header));\r
116 #ifdef __BIG_ENDIAN__\r
117                 header.size = os::Byteswap::byteswap(header.size);\r
118 #endif\r
119                 B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));\r
120 \r
121                 if ( strncmp( B3dStack.getLast().name, "TEXS", 4 ) == 0 )\r
122                 {\r
123                         if (!readChunkTEXS())\r
124                                 return false;\r
125                 }\r
126                 else if ( strncmp( B3dStack.getLast().name, "BRUS", 4 ) == 0 )\r
127                 {\r
128                         if (!readChunkBRUS())\r
129                                 return false;\r
130                 }\r
131                 else if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 )\r
132                 {\r
133                         if (!readChunkNODE((CSkinnedMesh::SJoint*)0) )\r
134                                 return false;\r
135                 }\r
136                 else\r
137                 {\r
138                         os::Printer::log("Unknown chunk found in mesh base - skipping");\r
139                         B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);\r
140                         B3dStack.erase(B3dStack.size()-1);\r
141                 }\r
142         }\r
143 \r
144         B3dStack.clear();\r
145 \r
146         BaseVertices.clear();\r
147         AnimatedVertices_VertexID.clear();\r
148         AnimatedVertices_BufferID.clear();\r
149 \r
150         Materials.clear();\r
151         Textures.clear();\r
152 \r
153         return true;\r
154 }\r
155 \r
156 \r
157 bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint)\r
158 {\r
159         CSkinnedMesh::SJoint *joint = AnimatedMesh->addJoint(inJoint);\r
160         readString(joint->Name);\r
161 \r
162 #ifdef _B3D_READER_DEBUG\r
163         core::stringc logStr;\r
164         for ( u32 i=1; i < B3dStack.size(); ++i )\r
165                 logStr += "-";\r
166         logStr += "read ChunkNODE";\r
167         os::Printer::log(logStr.c_str(), joint->Name.c_str(), ELL_DEBUG);\r
168 #endif\r
169 \r
170         f32 position[3], scale[3], rotation[4];\r
171 \r
172         readFloats(position, 3);\r
173         readFloats(scale, 3);\r
174         readFloats(rotation, 4);\r
175 \r
176         joint->Animatedposition = core::vector3df(position[0],position[1],position[2]) ;\r
177         joint->Animatedscale = core::vector3df(scale[0],scale[1],scale[2]);\r
178         joint->Animatedrotation = core::quaternion(rotation[1], rotation[2], rotation[3], rotation[0]);\r
179 \r
180         //Build LocalMatrix:\r
181 \r
182         core::matrix4 positionMatrix;\r
183         positionMatrix.setTranslation( joint->Animatedposition );\r
184         core::matrix4 scaleMatrix;\r
185         scaleMatrix.setScale( joint->Animatedscale );\r
186         core::matrix4 rotationMatrix;\r
187         joint->Animatedrotation.getMatrix_transposed(rotationMatrix);\r
188 \r
189         joint->LocalMatrix = positionMatrix * rotationMatrix * scaleMatrix;\r
190 \r
191         if (inJoint)\r
192                 joint->GlobalMatrix = inJoint->GlobalMatrix * joint->LocalMatrix;\r
193         else\r
194                 joint->GlobalMatrix = joint->LocalMatrix;\r
195 \r
196         while(B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats\r
197         {\r
198                 SB3dChunkHeader header;\r
199                 B3DFile->read(&header, sizeof(header));\r
200 #ifdef __BIG_ENDIAN__\r
201                 header.size = os::Byteswap::byteswap(header.size);\r
202 #endif\r
203 \r
204                 B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));\r
205 \r
206                 if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 )\r
207                 {\r
208                         if (!readChunkNODE(joint))\r
209                                 return false;\r
210                 }\r
211                 else if ( strncmp( B3dStack.getLast().name, "MESH", 4 ) == 0 )\r
212                 {\r
213                         VerticesStart=BaseVertices.size();\r
214                         if (!readChunkMESH(joint))\r
215                                 return false;\r
216                 }\r
217                 else if ( strncmp( B3dStack.getLast().name, "BONE", 4 ) == 0 )\r
218                 {\r
219                         if (!readChunkBONE(joint))\r
220                                 return false;\r
221                 }\r
222                 else if ( strncmp( B3dStack.getLast().name, "KEYS", 4 ) == 0 )\r
223                 {\r
224                         if(!readChunkKEYS(joint))\r
225                                 return false;\r
226                 }\r
227                 else if ( strncmp( B3dStack.getLast().name, "ANIM", 4 ) == 0 )\r
228                 {\r
229                         if (!readChunkANIM())\r
230                                 return false;\r
231                 }\r
232                 else\r
233                 {\r
234                         os::Printer::log("Unknown chunk found in node chunk - skipping");\r
235                         B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);\r
236                         B3dStack.erase(B3dStack.size()-1);\r
237                 }\r
238         }\r
239 \r
240         B3dStack.erase(B3dStack.size()-1);\r
241 \r
242         return true;\r
243 }\r
244 \r
245 \r
246 bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *inJoint)\r
247 {\r
248 #ifdef _B3D_READER_DEBUG\r
249         core::stringc logStr;\r
250         for ( u32 i=1; i < B3dStack.size(); ++i )\r
251                 logStr += "-";\r
252         logStr += "read ChunkMESH";\r
253         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
254 #endif\r
255 \r
256         s32 brushID;\r
257         B3DFile->read(&brushID, sizeof(brushID));\r
258 #ifdef __BIG_ENDIAN__\r
259         brushID = os::Byteswap::byteswap(brushID);\r
260 #endif\r
261 \r
262         NormalsInFile=false;\r
263         HasVertexColors=false;\r
264 \r
265         while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats\r
266         {\r
267                 SB3dChunkHeader header;\r
268                 B3DFile->read(&header, sizeof(header));\r
269 #ifdef __BIG_ENDIAN__\r
270                 header.size = os::Byteswap::byteswap(header.size);\r
271 #endif\r
272 \r
273                 B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));\r
274 \r
275                 if ( strncmp( B3dStack.getLast().name, "VRTS", 4 ) == 0 )\r
276                 {\r
277                         if (!readChunkVRTS(inJoint))\r
278                                 return false;\r
279                 }\r
280                 else if ( strncmp( B3dStack.getLast().name, "TRIS", 4 ) == 0 )\r
281                 {\r
282                         scene::SSkinMeshBuffer *meshBuffer = AnimatedMesh->addMeshBuffer();\r
283 \r
284                         if (brushID!=-1)\r
285                         {\r
286                                 loadTextures(Materials[brushID]);\r
287                                 meshBuffer->Material=Materials[brushID].Material;\r
288                         }\r
289 \r
290                         if(readChunkTRIS(meshBuffer,AnimatedMesh->getMeshBuffers().size()-1, VerticesStart)==false)\r
291                                 return false;\r
292 \r
293                         if (!NormalsInFile)\r
294                         {\r
295                                 s32 i;\r
296 \r
297                                 for ( i=0; i<(s32)meshBuffer->Indices.size(); i+=3)\r
298                                 {\r
299                                         core::plane3df p(meshBuffer->getVertex(meshBuffer->Indices[i+0])->Pos,\r
300                                                         meshBuffer->getVertex(meshBuffer->Indices[i+1])->Pos,\r
301                                                         meshBuffer->getVertex(meshBuffer->Indices[i+2])->Pos);\r
302 \r
303                                         meshBuffer->getVertex(meshBuffer->Indices[i+0])->Normal += p.Normal;\r
304                                         meshBuffer->getVertex(meshBuffer->Indices[i+1])->Normal += p.Normal;\r
305                                         meshBuffer->getVertex(meshBuffer->Indices[i+2])->Normal += p.Normal;\r
306                                 }\r
307 \r
308                                 for ( i = 0; i<(s32)meshBuffer->getVertexCount(); ++i )\r
309                                 {\r
310                                         meshBuffer->getVertex(i)->Normal.normalize();\r
311                                         BaseVertices[VerticesStart+i].Normal=meshBuffer->getVertex(i)->Normal;\r
312                                 }\r
313                         }\r
314                 }\r
315                 else\r
316                 {\r
317                         os::Printer::log("Unknown chunk found in mesh - skipping");\r
318                         B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);\r
319                         B3dStack.erase(B3dStack.size()-1);\r
320                 }\r
321         }\r
322 \r
323         B3dStack.erase(B3dStack.size()-1);\r
324 \r
325         return true;\r
326 }\r
327 \r
328 \r
329 /*\r
330 VRTS:\r
331   int flags                   ;1=normal values present, 2=rgba values present\r
332   int tex_coord_sets          ;texture coords per vertex (eg: 1 for simple U/V) max=8\r
333                                 but we only support 3\r
334   int tex_coord_set_size      ;components per set (eg: 2 for simple U/V) max=4\r
335   {\r
336   float x,y,z                 ;always present\r
337   float nx,ny,nz              ;vertex normal: present if (flags&1)\r
338   float red,green,blue,alpha  ;vertex color: present if (flags&2)\r
339   float tex_coords[tex_coord_sets][tex_coord_set_size]  ;tex coords\r
340   }\r
341 */\r
342 bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint)\r
343 {\r
344 #ifdef _B3D_READER_DEBUG\r
345         core::stringc logStr;\r
346         for ( u32 i=1; i < B3dStack.size(); ++i )\r
347                 logStr += "-";\r
348         logStr += "ChunkVRTS";\r
349         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
350 #endif\r
351 \r
352         const s32 max_tex_coords = 3;\r
353         s32 flags, tex_coord_sets, tex_coord_set_size;\r
354 \r
355         B3DFile->read(&flags, sizeof(flags));\r
356         B3DFile->read(&tex_coord_sets, sizeof(tex_coord_sets));\r
357         B3DFile->read(&tex_coord_set_size, sizeof(tex_coord_set_size));\r
358 #ifdef __BIG_ENDIAN__\r
359         flags = os::Byteswap::byteswap(flags);\r
360         tex_coord_sets = os::Byteswap::byteswap(tex_coord_sets);\r
361         tex_coord_set_size = os::Byteswap::byteswap(tex_coord_set_size);\r
362 #endif\r
363 \r
364         if (tex_coord_sets >= max_tex_coords || tex_coord_set_size >= 4) // Something is wrong\r
365         {\r
366                 os::Printer::log("tex_coord_sets or tex_coord_set_size too big", B3DFile->getFileName(), ELL_ERROR);\r
367                 return false;\r
368         }\r
369 \r
370         //------ Allocate Memory, for speed -----------//\r
371 \r
372         s32 numberOfReads = 3;\r
373 \r
374         if (flags & 1)\r
375         {\r
376                 NormalsInFile = true;\r
377                 numberOfReads += 3;\r
378         }\r
379         if (flags & 2)\r
380         {\r
381                 numberOfReads += 4;\r
382                 HasVertexColors=true;\r
383         }\r
384 \r
385         numberOfReads += tex_coord_sets*tex_coord_set_size;\r
386 \r
387         const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / numberOfReads;\r
388 \r
389         BaseVertices.reallocate(memoryNeeded + BaseVertices.size() + 1);\r
390         AnimatedVertices_VertexID.reallocate(memoryNeeded + AnimatedVertices_VertexID.size() + 1);\r
391 \r
392         //--------------------------------------------//\r
393 \r
394         while( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats\r
395         {\r
396                 f32 position[3];\r
397                 f32 normal[3]={0.f, 0.f, 0.f};\r
398                 f32 color[4]={1.0f, 1.0f, 1.0f, 1.0f};\r
399                 f32 tex_coords[max_tex_coords][4];\r
400 \r
401                 readFloats(position, 3);\r
402 \r
403                 if (flags & 1)\r
404                         readFloats(normal, 3);\r
405                 if (flags & 2)\r
406                         readFloats(color, 4);\r
407 \r
408                 for (s32 i=0; i<tex_coord_sets; ++i)\r
409                         readFloats(tex_coords[i], tex_coord_set_size);\r
410 \r
411                 f32 tu=0.0f, tv=0.0f;\r
412                 if (tex_coord_sets >= 1 && tex_coord_set_size >= 2)\r
413                 {\r
414                         tu=tex_coords[0][0];\r
415                         tv=tex_coords[0][1];\r
416                 }\r
417 \r
418                 f32 tu2=0.0f, tv2=0.0f;\r
419                 if (tex_coord_sets>1 && tex_coord_set_size>1)\r
420                 {\r
421                         tu2=tex_coords[1][0];\r
422                         tv2=tex_coords[1][1];\r
423                 }\r
424 \r
425                 // Create Vertex...\r
426                 video::S3DVertex2TCoords Vertex(position[0], position[1], position[2],\r
427                                 normal[0], normal[1], normal[2],\r
428                                 video::SColorf(color[0], color[1], color[2], color[3]).toSColor(),\r
429                                 tu, tv, tu2, tv2);\r
430 \r
431                 // Transform the Vertex position by nested node...\r
432                 inJoint->GlobalMatrix.transformVect(Vertex.Pos);\r
433                 inJoint->GlobalMatrix.rotateVect(Vertex.Normal);\r
434 \r
435                 //Add it...\r
436                 BaseVertices.push_back(Vertex);\r
437 \r
438                 AnimatedVertices_VertexID.push_back(-1);\r
439                 AnimatedVertices_BufferID.push_back(-1);\r
440         }\r
441 \r
442         B3dStack.erase(B3dStack.size()-1);\r
443 \r
444         return true;\r
445 }\r
446 \r
447 \r
448 bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *meshBuffer, u32 meshBufferID, s32 vertices_Start)\r
449 {\r
450 #ifdef _B3D_READER_DEBUG\r
451         core::stringc logStr;\r
452         for ( u32 i=1; i < B3dStack.size(); ++i )\r
453                 logStr += "-";\r
454         logStr += "ChunkTRIS";\r
455         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
456 #endif\r
457 \r
458         bool showVertexWarning=false;\r
459 \r
460         s32 triangle_brush_id; // Note: Irrlicht can't have different brushes for each triangle (using a workaround)\r
461         B3DFile->read(&triangle_brush_id, sizeof(triangle_brush_id));\r
462 #ifdef __BIG_ENDIAN__\r
463         triangle_brush_id = os::Byteswap::byteswap(triangle_brush_id);\r
464 #endif\r
465 \r
466         SB3dMaterial *B3dMaterial;\r
467 \r
468         if (triangle_brush_id != -1)\r
469         {\r
470                 loadTextures(Materials[triangle_brush_id]);\r
471                 B3dMaterial = &Materials[triangle_brush_id];\r
472                 meshBuffer->Material = B3dMaterial->Material;\r
473         }\r
474         else\r
475                 B3dMaterial = 0;\r
476 \r
477         const s32 memoryNeeded = B3dStack.getLast().length / sizeof(s32);\r
478         meshBuffer->Indices.reallocate(memoryNeeded + meshBuffer->Indices.size() + 1);\r
479 \r
480         while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats\r
481         {\r
482                 s32 vertex_id[3];\r
483 \r
484                 B3DFile->read(vertex_id, 3*sizeof(s32));\r
485 #ifdef __BIG_ENDIAN__\r
486                 vertex_id[0] = os::Byteswap::byteswap(vertex_id[0]);\r
487                 vertex_id[1] = os::Byteswap::byteswap(vertex_id[1]);\r
488                 vertex_id[2] = os::Byteswap::byteswap(vertex_id[2]);\r
489 #endif\r
490 \r
491                 //Make Ids global:\r
492                 vertex_id[0] += vertices_Start;\r
493                 vertex_id[1] += vertices_Start;\r
494                 vertex_id[2] += vertices_Start;\r
495 \r
496                 for(s32 i=0; i<3; ++i)\r
497                 {\r
498                         if ((u32)vertex_id[i] >= AnimatedVertices_VertexID.size())\r
499                         {\r
500                                 os::Printer::log("Illegal vertex index found", B3DFile->getFileName(), ELL_ERROR);\r
501                                 return false;\r
502                         }\r
503 \r
504                         if (AnimatedVertices_VertexID[ vertex_id[i] ] != -1)\r
505                         {\r
506                                 if ( AnimatedVertices_BufferID[ vertex_id[i] ] != (s32)meshBufferID ) //If this vertex is linked in a different meshbuffer\r
507                                 {\r
508                                         AnimatedVertices_VertexID[ vertex_id[i] ] = -1;\r
509                                         AnimatedVertices_BufferID[ vertex_id[i] ] = -1;\r
510                                         showVertexWarning=true;\r
511                                 }\r
512                         }\r
513                         if (AnimatedVertices_VertexID[ vertex_id[i] ] == -1) //If this vertex is not in the meshbuffer\r
514                         {\r
515                                 //Check for lightmapping:\r
516                                 if (BaseVertices[ vertex_id[i] ].TCoords2 != core::vector2df(0.f,0.f))\r
517                                         meshBuffer->convertTo2TCoords(); //Will only affect the meshbuffer the first time this is called\r
518 \r
519                                 //Add the vertex to the meshbuffer:\r
520                                 if (meshBuffer->VertexType == video::EVT_STANDARD)\r
521                                         meshBuffer->Vertices_Standard.push_back( BaseVertices[ vertex_id[i] ] );\r
522                                 else\r
523                                         meshBuffer->Vertices_2TCoords.push_back(BaseVertices[ vertex_id[i] ] );\r
524 \r
525                                 //create vertex id to meshbuffer index link:\r
526                                 AnimatedVertices_VertexID[ vertex_id[i] ] = meshBuffer->getVertexCount()-1;\r
527                                 AnimatedVertices_BufferID[ vertex_id[i] ] = meshBufferID;\r
528 \r
529                                 if (B3dMaterial)\r
530                                 {\r
531                                         // Apply Material/Color/etc...\r
532                                         video::S3DVertex *Vertex=meshBuffer->getVertex(meshBuffer->getVertexCount()-1);\r
533 \r
534                                         if (!HasVertexColors)\r
535                                                 Vertex->Color=B3dMaterial->Material.DiffuseColor;\r
536                                         else if (Vertex->Color.getAlpha() == 255)\r
537                                                 Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) );\r
538 \r
539                                         // Use texture's scale\r
540                                         if (B3dMaterial->Textures[0])\r
541                                         {\r
542                                                 Vertex->TCoords.X *= B3dMaterial->Textures[0]->Xscale;\r
543                                                 Vertex->TCoords.Y *= B3dMaterial->Textures[0]->Yscale;\r
544                                         }\r
545                                         /*\r
546                                         if (B3dMaterial->Textures[1])\r
547                                         {\r
548                                                 Vertex->TCoords2.X *=B3dMaterial->Textures[1]->Xscale;\r
549                                                 Vertex->TCoords2.Y *=B3dMaterial->Textures[1]->Yscale;\r
550                                         }\r
551                                         */\r
552                                 }\r
553                         }\r
554                 }\r
555 \r
556                 meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[0] ] );\r
557                 meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[1] ] );\r
558                 meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[2] ] );\r
559         }\r
560 \r
561         B3dStack.erase(B3dStack.size()-1);\r
562 \r
563         if (showVertexWarning)\r
564                 os::Printer::log("B3dMeshLoader: Warning, different meshbuffers linking to the same vertex, this will cause problems with animated meshes");\r
565 \r
566         return true;\r
567 }\r
568 \r
569 \r
570 bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint)\r
571 {\r
572 #ifdef _B3D_READER_DEBUG\r
573         core::stringc logStr;\r
574         for ( u32 i=1; i < B3dStack.size(); ++i )\r
575                 logStr += "-";\r
576         logStr += "read ChunkBONE";\r
577         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
578 #endif\r
579 \r
580         if (B3dStack.getLast().length > 8)\r
581         {\r
582                 while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats\r
583                 {\r
584                         u32 globalVertexID;\r
585                         f32 strength;\r
586                         B3DFile->read(&globalVertexID, sizeof(globalVertexID));\r
587                         B3DFile->read(&strength, sizeof(strength));\r
588 #ifdef __BIG_ENDIAN__\r
589                         globalVertexID = os::Byteswap::byteswap(globalVertexID);\r
590                         strength = os::Byteswap::byteswap(strength);\r
591 #endif\r
592                         globalVertexID += VerticesStart;\r
593 \r
594                         if (AnimatedVertices_VertexID[globalVertexID]==-1)\r
595                         {\r
596                                 os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)");\r
597                         }\r
598                         else if (strength >0)\r
599                         {\r
600                                 CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(inJoint);\r
601                                 weight->strength=strength;\r
602                                 //Find the meshbuffer and Vertex index from the Global Vertex ID:\r
603                                 weight->vertex_id = AnimatedVertices_VertexID[globalVertexID];\r
604                                 weight->buffer_id = AnimatedVertices_BufferID[globalVertexID];\r
605                         }\r
606                 }\r
607         }\r
608 \r
609         B3dStack.erase(B3dStack.size()-1);\r
610         return true;\r
611 }\r
612 \r
613 \r
614 bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint)\r
615 {\r
616 #ifdef _B3D_READER_DEBUG\r
617         // Only print first, that's just too much output otherwise\r
618         if ( !inJoint || (inJoint->PositionKeys.empty() && inJoint->ScaleKeys.empty() && inJoint->RotationKeys.empty()) )\r
619         {\r
620                 core::stringc logStr;\r
621                 for ( u32 i=1; i < B3dStack.size(); ++i )\r
622                         logStr += "-";\r
623                 logStr += "read ChunkKEYS";\r
624                 os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
625         }\r
626 #endif\r
627 \r
628         s32 flags;\r
629         B3DFile->read(&flags, sizeof(flags));\r
630 #ifdef __BIG_ENDIAN__\r
631         flags = os::Byteswap::byteswap(flags);\r
632 #endif\r
633 \r
634         CSkinnedMesh::SPositionKey *oldPosKey=0;\r
635         core::vector3df oldPos[2];\r
636         CSkinnedMesh::SScaleKey *oldScaleKey=0;\r
637         core::vector3df oldScale[2];\r
638         CSkinnedMesh::SRotationKey *oldRotKey=0;\r
639         core::quaternion oldRot[2];\r
640         bool isFirst[3]={true,true,true};\r
641         while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats\r
642         {\r
643                 s32 frame;\r
644 \r
645                 B3DFile->read(&frame, sizeof(frame));\r
646                 #ifdef __BIG_ENDIAN__\r
647                 frame = os::Byteswap::byteswap(frame);\r
648                 #endif\r
649 \r
650                 // Add key frames, frames in Irrlicht are zero-based\r
651                 f32 data[4];\r
652                 if (flags & 1)\r
653                 {\r
654                         readFloats(data, 3);\r
655                         if ((oldPosKey!=0) && (oldPos[0]==oldPos[1]))\r
656                         {\r
657                                 const core::vector3df pos(data[0], data[1], data[2]);\r
658                                 if (oldPos[1]==pos)\r
659                                         oldPosKey->frame = (f32)frame-1;\r
660                                 else\r
661                                 {\r
662                                         oldPos[0]=oldPos[1];\r
663                                         oldPosKey=AnimatedMesh->addPositionKey(inJoint);\r
664                                         oldPosKey->frame = (f32)frame-1;\r
665                                         oldPos[1].set(oldPosKey->position.set(pos));\r
666                                 }\r
667                         }\r
668                         else if (oldPosKey==0 && isFirst[0])\r
669                         {\r
670                                 oldPosKey=AnimatedMesh->addPositionKey(inJoint);\r
671                                 oldPosKey->frame = (f32)frame-1;\r
672                                 oldPos[0].set(oldPosKey->position.set(data[0], data[1], data[2]));\r
673                                 oldPosKey=0;\r
674                                 isFirst[0]=false;\r
675                         }\r
676                         else\r
677                         {\r
678                                 if (oldPosKey!=0)\r
679                                         oldPos[0]=oldPos[1];\r
680                                 oldPosKey=AnimatedMesh->addPositionKey(inJoint);\r
681                                 oldPosKey->frame = (f32)frame-1;\r
682                                 oldPos[1].set(oldPosKey->position.set(data[0], data[1], data[2]));\r
683                         }\r
684                 }\r
685                 if (flags & 2)\r
686                 {\r
687                         readFloats(data, 3);\r
688                         if ((oldScaleKey!=0) && (oldScale[0]==oldScale[1]))\r
689                         {\r
690                                 const core::vector3df scale(data[0], data[1], data[2]);\r
691                                 if (oldScale[1]==scale)\r
692                                         oldScaleKey->frame = (f32)frame-1;\r
693                                 else\r
694                                 {\r
695                                         oldScale[0]=oldScale[1];\r
696                                         oldScaleKey=AnimatedMesh->addScaleKey(inJoint);\r
697                                         oldScaleKey->frame = (f32)frame-1;\r
698                                         oldScale[1].set(oldScaleKey->scale.set(scale));\r
699                                 }\r
700                         }\r
701                         else if (oldScaleKey==0 && isFirst[1])\r
702                         {\r
703                                 oldScaleKey=AnimatedMesh->addScaleKey(inJoint);\r
704                                 oldScaleKey->frame = (f32)frame-1;\r
705                                 oldScale[0].set(oldScaleKey->scale.set(data[0], data[1], data[2]));\r
706                                 oldScaleKey=0;\r
707                                 isFirst[1]=false;\r
708                         }\r
709                         else\r
710                         {\r
711                                 if (oldScaleKey!=0)\r
712                                         oldScale[0]=oldScale[1];\r
713                                 oldScaleKey=AnimatedMesh->addScaleKey(inJoint);\r
714                                 oldScaleKey->frame = (f32)frame-1;\r
715                                 oldScale[1].set(oldScaleKey->scale.set(data[0], data[1], data[2]));\r
716                         }\r
717                 }\r
718                 if (flags & 4)\r
719                 {\r
720                         readFloats(data, 4);\r
721                         if ((oldRotKey!=0) && (oldRot[0]==oldRot[1]))\r
722                         {\r
723                                 // meant to be in this order since b3d stores W first\r
724                                 const core::quaternion rot(data[1], data[2], data[3], data[0]);\r
725                                 if (oldRot[1]==rot)\r
726                                         oldRotKey->frame = (f32)frame-1;\r
727                                 else\r
728                                 {\r
729                                         oldRot[0]=oldRot[1];\r
730                                         oldRotKey=AnimatedMesh->addRotationKey(inJoint);\r
731                                         oldRotKey->frame = (f32)frame-1;\r
732                                         oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0]));\r
733                                         oldRot[1].normalize();\r
734                                 }\r
735                         }\r
736                         else if (oldRotKey==0 && isFirst[2])\r
737                         {\r
738                                 oldRotKey=AnimatedMesh->addRotationKey(inJoint);\r
739                                 oldRotKey->frame = (f32)frame-1;\r
740                                 // meant to be in this order since b3d stores W first\r
741                                 oldRot[0].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0]));\r
742                                 oldRot[0].normalize();\r
743                                 oldRotKey=0;\r
744                                 isFirst[2]=false;\r
745                         }\r
746                         else\r
747                         {\r
748                                 if (oldRotKey!=0)\r
749                                         oldRot[0]=oldRot[1];\r
750                                 oldRotKey=AnimatedMesh->addRotationKey(inJoint);\r
751                                 oldRotKey->frame = (f32)frame-1;\r
752                                 // meant to be in this order since b3d stores W first\r
753                                 oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0]));\r
754                                 oldRot[1].normalize();\r
755                         }\r
756                 }\r
757         }\r
758 \r
759         B3dStack.erase(B3dStack.size()-1);\r
760         return true;\r
761 }\r
762 \r
763 \r
764 bool CB3DMeshFileLoader::readChunkANIM()\r
765 {\r
766 #ifdef _B3D_READER_DEBUG\r
767         core::stringc logStr;\r
768         for ( u32 i=1; i < B3dStack.size(); ++i )\r
769                 logStr += "-";\r
770         logStr += "read ChunkANIM";\r
771         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
772 #endif\r
773 \r
774         s32 animFlags; //not stored\used\r
775         s32 animFrames;//not stored\used\r
776         f32 animFPS; //not stored\used\r
777 \r
778         B3DFile->read(&animFlags, sizeof(s32));\r
779         B3DFile->read(&animFrames, sizeof(s32));\r
780         readFloats(&animFPS, 1);\r
781         if (animFPS>0.f)\r
782                 AnimatedMesh->setAnimationSpeed(animFPS);\r
783         os::Printer::log("FPS", io::path((double)animFPS), ELL_DEBUG);\r
784 \r
785         #ifdef __BIG_ENDIAN__\r
786                 animFlags = os::Byteswap::byteswap(animFlags);\r
787                 animFrames = os::Byteswap::byteswap(animFrames);\r
788         #endif\r
789 \r
790         B3dStack.erase(B3dStack.size()-1);\r
791         return true;\r
792 }\r
793 \r
794 \r
795 bool CB3DMeshFileLoader::readChunkTEXS()\r
796 {\r
797 #ifdef _B3D_READER_DEBUG\r
798         core::stringc logStr;\r
799         for ( u32 i=1; i < B3dStack.size(); ++i )\r
800                 logStr += "-";\r
801         logStr += "read ChunkTEXS";\r
802         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
803 #endif\r
804 \r
805         while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats\r
806         {\r
807                 Textures.push_back(SB3dTexture());\r
808                 SB3dTexture& B3dTexture = Textures.getLast();\r
809 \r
810                 readString(B3dTexture.TextureName);\r
811                 B3dTexture.TextureName.replace('\\','/');\r
812 #ifdef _B3D_READER_DEBUG\r
813                 os::Printer::log("read Texture", B3dTexture.TextureName.c_str(), ELL_DEBUG);\r
814 #endif\r
815 \r
816                 B3DFile->read(&B3dTexture.Flags, sizeof(s32));\r
817                 B3DFile->read(&B3dTexture.Blend, sizeof(s32));\r
818 #ifdef __BIG_ENDIAN__\r
819                 B3dTexture.Flags = os::Byteswap::byteswap(B3dTexture.Flags);\r
820                 B3dTexture.Blend = os::Byteswap::byteswap(B3dTexture.Blend);\r
821 #endif\r
822 #ifdef _B3D_READER_DEBUG\r
823                 os::Printer::log("Flags", core::stringc(B3dTexture.Flags).c_str(), ELL_DEBUG);\r
824                 os::Printer::log("Blend", core::stringc(B3dTexture.Blend).c_str(), ELL_DEBUG);\r
825 #endif\r
826                 readFloats(&B3dTexture.Xpos, 1);\r
827                 readFloats(&B3dTexture.Ypos, 1);\r
828                 readFloats(&B3dTexture.Xscale, 1);\r
829                 readFloats(&B3dTexture.Yscale, 1);\r
830                 readFloats(&B3dTexture.Angle, 1);\r
831         }\r
832 \r
833         B3dStack.erase(B3dStack.size()-1);\r
834 \r
835         return true;\r
836 }\r
837 \r
838 \r
839 bool CB3DMeshFileLoader::readChunkBRUS()\r
840 {\r
841 #ifdef _B3D_READER_DEBUG\r
842         core::stringc logStr;\r
843         for ( u32 i=1; i < B3dStack.size(); ++i )\r
844                 logStr += "-";\r
845         logStr += "read ChunkBRUS";\r
846         os::Printer::log(logStr.c_str(), ELL_DEBUG);\r
847 #endif\r
848 \r
849         u32 n_texs;\r
850         B3DFile->read(&n_texs, sizeof(u32));\r
851 #ifdef __BIG_ENDIAN__\r
852         n_texs = os::Byteswap::byteswap(n_texs);\r
853 #endif\r
854 \r
855         // number of texture ids read for Irrlicht\r
856         const u32 num_textures = core::min_(n_texs, video::MATERIAL_MAX_TEXTURES);\r
857         // number of bytes to skip (for ignored texture ids)\r
858         const u32 n_texs_offset = (num_textures<n_texs)?(n_texs-num_textures):0;\r
859 \r
860         while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats\r
861         {\r
862                 // This is what blitz basic calls a brush, like a Irrlicht Material\r
863 \r
864                 core::stringc name;\r
865                 readString(name);\r
866 #ifdef _B3D_READER_DEBUG\r
867                 os::Printer::log("read Material", name, ELL_DEBUG);\r
868 #endif\r
869                 Materials.push_back(SB3dMaterial());\r
870                 SB3dMaterial& B3dMaterial=Materials.getLast();\r
871 \r
872                 readFloats(&B3dMaterial.red, 1);\r
873                 readFloats(&B3dMaterial.green, 1);\r
874                 readFloats(&B3dMaterial.blue, 1);\r
875                 readFloats(&B3dMaterial.alpha, 1);\r
876                 readFloats(&B3dMaterial.shininess, 1);\r
877 \r
878                 B3DFile->read(&B3dMaterial.blend, sizeof(B3dMaterial.blend));\r
879                 B3DFile->read(&B3dMaterial.fx, sizeof(B3dMaterial.fx));\r
880 #ifdef __BIG_ENDIAN__\r
881                 B3dMaterial.blend = os::Byteswap::byteswap(B3dMaterial.blend);\r
882                 B3dMaterial.fx = os::Byteswap::byteswap(B3dMaterial.fx);\r
883 #endif\r
884 #ifdef _B3D_READER_DEBUG\r
885                 os::Printer::log("Blend", core::stringc(B3dMaterial.blend).c_str(), ELL_DEBUG);\r
886                 os::Printer::log("FX", core::stringc(B3dMaterial.fx).c_str(), ELL_DEBUG);\r
887 #endif\r
888 \r
889                 u32 i;\r
890                 for (i=0; i<num_textures; ++i)\r
891                 {\r
892                         s32 texture_id=-1;\r
893                         B3DFile->read(&texture_id, sizeof(s32));\r
894 #ifdef __BIG_ENDIAN__\r
895                         texture_id = os::Byteswap::byteswap(texture_id);\r
896 #endif\r
897                         //--- Get pointers to the texture, based on the IDs ---\r
898                         if ((u32)texture_id < Textures.size())\r
899                         {\r
900                                 B3dMaterial.Textures[i]=&Textures[texture_id];\r
901 #ifdef _B3D_READER_DEBUG\r
902                                 os::Printer::log("Layer", core::stringc(i).c_str(), ELL_DEBUG);\r
903                                 os::Printer::log("using texture", Textures[texture_id].TextureName.c_str(), ELL_DEBUG);\r
904 #endif\r
905                         }\r
906                         else\r
907                                 B3dMaterial.Textures[i]=0;\r
908                 }\r
909                 // skip other texture ids\r
910                 for (i=0; i<n_texs_offset; ++i)\r
911                 {\r
912                         s32 texture_id=-1;\r
913                         B3DFile->read(&texture_id, sizeof(s32));\r
914 #ifdef __BIG_ENDIAN__\r
915                         texture_id = os::Byteswap::byteswap(texture_id);\r
916 #endif\r
917                         if (ShowWarning && (texture_id != -1) && (n_texs>video::MATERIAL_MAX_TEXTURES))\r
918                         {\r
919                                 os::Printer::log("Too many textures used in one material", B3DFile->getFileName(), ELL_WARNING);\r
920                                 ShowWarning = false;\r
921                         }\r
922                 }\r
923 \r
924                 //Fixes problems when the lightmap is on the first texture:\r
925                 if (B3dMaterial.Textures[0] != 0)\r
926                 {\r
927                         if (B3dMaterial.Textures[0]->Flags & 65536) // 65536 = secondary UV\r
928                         {\r
929                                 SB3dTexture *TmpTexture;\r
930                                 TmpTexture = B3dMaterial.Textures[1];\r
931                                 B3dMaterial.Textures[1] = B3dMaterial.Textures[0];\r
932                                 B3dMaterial.Textures[0] = TmpTexture;\r
933                         }\r
934                 }\r
935 \r
936                 //If a preceeding texture slot is empty move the others down:\r
937                 for (i=num_textures; i>0; --i)\r
938                 {\r
939                         for (u32 j=i-1; j<num_textures-1; ++j)\r
940                         {\r
941                                 if (B3dMaterial.Textures[j+1] != 0 && B3dMaterial.Textures[j] == 0)\r
942                                 {\r
943                                         B3dMaterial.Textures[j] = B3dMaterial.Textures[j+1];\r
944                                         B3dMaterial.Textures[j+1] = 0;\r
945                                 }\r
946                         }\r
947                 }\r
948 \r
949                 //------ Convert blitz flags/blend to irrlicht -------\r
950 \r
951                 //Two textures:\r
952                 if (B3dMaterial.Textures[1])\r
953                 {\r
954                         if (B3dMaterial.alpha==1.f)\r
955                         {\r
956                                 if (B3dMaterial.Textures[1]->Blend == 5) //(Multiply 2)\r
957                                         B3dMaterial.Material.MaterialType = video::EMT_LIGHTMAP_M2;\r
958                                 else\r
959                                         B3dMaterial.Material.MaterialType = video::EMT_LIGHTMAP;\r
960                                 B3dMaterial.Material.Lighting = false;\r
961                         }\r
962                         else\r
963                         {\r
964                                 B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
965                                 B3dMaterial.Material.ZWriteEnable = video::EZW_OFF;\r
966                         }\r
967                 }\r
968                 else if (B3dMaterial.Textures[0]) //One texture:\r
969                 {\r
970                         // Flags & 0x1 is usual SOLID, 0x8 is mipmap (handled before)\r
971                         if (B3dMaterial.Textures[0]->Flags & 0x2) //(Alpha mapped)\r
972                         {\r
973                                 B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;\r
974                                 B3dMaterial.Material.ZWriteEnable = video::EZW_OFF;\r
975                         }\r
976                         else if (B3dMaterial.Textures[0]->Flags & 0x4) //(Masked)\r
977                                 B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; // TODO: create color key texture\r
978                         else if (B3dMaterial.Textures[0]->Flags & 0x40)\r
979                                 B3dMaterial.Material.MaterialType = video::EMT_SPHERE_MAP;\r
980                         else if (B3dMaterial.Textures[0]->Flags & 0x80)\r
981                                 B3dMaterial.Material.MaterialType = video::EMT_SPHERE_MAP; // TODO: Should be cube map\r
982                         else if (B3dMaterial.alpha == 1.f)\r
983                                 B3dMaterial.Material.MaterialType = video::EMT_SOLID;\r
984                         else\r
985                         {\r
986                                 B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
987                                 B3dMaterial.Material.ZWriteEnable = video::EZW_OFF;\r
988                         }\r
989                 }\r
990                 else //No texture:\r
991                 {\r
992                         if (B3dMaterial.alpha == 1.f)\r
993                                 B3dMaterial.Material.MaterialType = video::EMT_SOLID;\r
994                         else\r
995                         {\r
996                                 B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
997                                 B3dMaterial.Material.ZWriteEnable = video::EZW_OFF;\r
998                         }\r
999                 }\r
1000 \r
1001                 B3dMaterial.Material.DiffuseColor = video::SColorf(B3dMaterial.red, B3dMaterial.green, B3dMaterial.blue, B3dMaterial.alpha).toSColor();\r
1002                 B3dMaterial.Material.ColorMaterial=video::ECM_NONE;\r
1003 \r
1004                 //------ Material fx ------\r
1005 \r
1006                 if (B3dMaterial.fx & 1) //full-bright\r
1007                 {\r
1008                         B3dMaterial.Material.AmbientColor = video::SColor(255, 255, 255, 255);\r
1009                         B3dMaterial.Material.Lighting = false;\r
1010                 }\r
1011                 else\r
1012                         B3dMaterial.Material.AmbientColor = B3dMaterial.Material.DiffuseColor;\r
1013 \r
1014                 if (B3dMaterial.fx & 2) //use vertex colors instead of brush color\r
1015                         B3dMaterial.Material.ColorMaterial=video::ECM_DIFFUSE_AND_AMBIENT;\r
1016 \r
1017                 if (B3dMaterial.fx & 4) //flatshaded\r
1018                         B3dMaterial.Material.GouraudShading = false;\r
1019 \r
1020                 if (B3dMaterial.fx & 16) //disable backface culling\r
1021                         B3dMaterial.Material.BackfaceCulling = false;\r
1022 \r
1023                 if (B3dMaterial.fx & 32) //force vertex alpha-blending\r
1024                 {\r
1025                         B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
1026                         B3dMaterial.Material.ZWriteEnable = video::EZW_OFF;\r
1027                 }\r
1028 \r
1029                 B3dMaterial.Material.Shininess = B3dMaterial.shininess;\r
1030         }\r
1031 \r
1032         B3dStack.erase(B3dStack.size()-1);\r
1033 \r
1034         return true;\r
1035 }\r
1036 \r
1037 \r
1038 void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const\r
1039 {\r
1040         if ( getMeshTextureLoader() )\r
1041         {\r
1042                 if ( SceneManager->getParameters()->existsAttribute(B3D_TEXTURE_PATH) )\r
1043                         getMeshTextureLoader()->setTexturePath( SceneManager->getParameters()->getAttributeAsString(B3D_TEXTURE_PATH) );\r
1044         }\r
1045 \r
1046         const bool previous32BitTextureFlag = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT);\r
1047         SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);\r
1048 \r
1049         // read texture from disk\r
1050         // note that mipmaps might be disabled by Flags & 0x8\r
1051         const bool doMipMaps = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);\r
1052 \r
1053         for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)\r
1054         {\r
1055                 SB3dTexture* B3dTexture = material.Textures[i];\r
1056                 if (B3dTexture && B3dTexture->TextureName.size() && !material.Material.getTexture(i))\r
1057                 {\r
1058                         if (!SceneManager->getParameters()->getAttributeAsBool(B3D_LOADER_IGNORE_MIPMAP_FLAG))\r
1059                                 SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, (B3dTexture->Flags & 0x8) ? true:false);\r
1060                         {\r
1061                                 video::ITexture* tex = getMeshTextureLoader() ? getMeshTextureLoader()->getTexture(B3dTexture->TextureName) : NULL;\r
1062                                 material.Material.setTexture(i, tex);\r
1063                         }\r
1064                         if (material.Textures[i]->Flags & 0x10) // Clamp U\r
1065                                 material.Material.TextureLayer[i].TextureWrapU=video::ETC_CLAMP;\r
1066                         if (material.Textures[i]->Flags & 0x20) // Clamp V\r
1067                                 material.Material.TextureLayer[i].TextureWrapV=video::ETC_CLAMP;\r
1068                         if (material.Textures[i]->Flags & 0x20) // Clamp R\r
1069                                 material.Material.TextureLayer[i].TextureWrapW=video::ETC_CLAMP;\r
1070                 }\r
1071         }\r
1072 \r
1073         SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, doMipMaps);\r
1074         SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, previous32BitTextureFlag);\r
1075 }\r
1076 \r
1077 \r
1078 void CB3DMeshFileLoader::readString(core::stringc& newstring)\r
1079 {\r
1080         newstring="";\r
1081         while (B3DFile->getPos() <= B3DFile->getSize())\r
1082         {\r
1083                 c8 character;\r
1084                 B3DFile->read(&character, sizeof(character));\r
1085                 if (character==0)\r
1086                         return;\r
1087                 newstring.append(character);\r
1088         }\r
1089 }\r
1090 \r
1091 \r
1092 void CB3DMeshFileLoader::readFloats(f32* vec, u32 count)\r
1093 {\r
1094         B3DFile->read(vec, count*sizeof(f32));\r
1095         #ifdef __BIG_ENDIAN__\r
1096         for (u32 n=0; n<count; ++n)\r
1097                 vec[n] = os::Byteswap::byteswap(vec[n]);\r
1098         #endif\r
1099 }\r
1100 \r
1101 } // end namespace scene\r
1102 } // end namespace irr\r
1103 \r
1104 \r
1105 #endif // _IRR_COMPILE_WITH_B3D_LOADER_\r
1106 \r