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