aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CMY3DMeshFileLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CMY3DMeshFileLoader.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CMY3DMeshFileLoader.cpp882
1 files changed, 882 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CMY3DMeshFileLoader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CMY3DMeshFileLoader.cpp
new file mode 100644
index 0000000..7044721
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CMY3DMeshFileLoader.cpp
@@ -0,0 +1,882 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4//
5// This file was originally written by ZDimitor.
6
7//-----------------------------------------------------------------------------
8// This tool created by ZDimitor everyone can use it as wants
9//-----------------------------------------------------------------------------
10
11#include "IrrCompileConfig.h"
12#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
13
14#include "CMY3DMeshFileLoader.h"
15
16#include "SAnimatedMesh.h"
17#include "SMeshBuffer.h"
18#include "IReadFile.h"
19#include "IAttributes.h"
20
21#include "CMY3DHelper.h"
22#include "os.h"
23
24// v3.15 - May 16, 2005
25
26namespace irr
27{
28namespace scene
29{
30
31static const u32 MY3D_ID = 0x4d593344;
32static const u16 MY3D_VER = 0x0003;
33static const u16 MY3D_SCENE_HEADER_ID = 0x1000;
34static const u16 MY3D_MAT_LIST_ID = 0x2000;
35static const u16 MY3D_MAT_HEADER_ID = 0x2100;
36static const u16 MY3D_TEX_FNAME_ID = 0x2101;
37static const u16 MY3D_TEXDATA_HEADER_ID = 0x2501;
38static const u16 MY3D_TEXDATA_RLE_HEADER_ID = 0x2502;
39static const u16 MY3D_MESH_LIST_ID = 0x3000;
40static const u16 MY3D_MESH_HEADER_ID = 0x3100;
41static const u16 MY3D_VERTS_ID = 0x3101;
42static const u16 MY3D_FACES_ID = 0x3102;
43static const u16 MY3D_TVERTS_ID = 0x3103;
44static const u16 MY3D_TFACES_ID = 0x3104;
45static const u16 MY3D_FILE_END_ID = 0xFFFF;
46
47static const unsigned long MY3D_TEXDATA_COMPR_NONE_ID = 0x4e4f4e45;
48static const unsigned long MY3D_TEXDATA_COMPR_SIMPLE_ID = 0x53494d50;
49static const unsigned long MY3D_TEXDATA_COMPR_RLE_ID = 0x20524c45;
50
51static const unsigned long MY3D_PIXEL_FORMAT_24 = 0x5f32345f;
52static const unsigned long MY3D_PIXEL_FORMAT_16 = 0x5f31365f;
53
54CMY3DMeshFileLoader::CMY3DMeshFileLoader(ISceneManager* scmgr, io::IFileSystem* fs)
55 : SceneManager(scmgr), FileSystem(fs)
56{
57 #ifdef _DEBUG
58 setDebugName("CMY3DMeshFileLoader");
59 #endif
60
61 if (FileSystem)
62 FileSystem->grab();
63}
64
65
66CMY3DMeshFileLoader::~CMY3DMeshFileLoader()
67{
68 if (FileSystem)
69 FileSystem->drop();
70}
71
72
73bool CMY3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
74{
75 return core::hasFileExtension ( filename, "my3d" );
76}
77
78
79IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file)
80{
81 MaterialEntry.clear();
82 MeshBufferEntry.clear();
83 ChildNodes.clear();
84
85 // working directory (from which we load the scene)
86 core::stringc filepath = FileSystem->getFileDir(file->getFileName());
87 if (filepath==".")
88 filepath="";
89 else
90 filepath.append("/");
91
92 // read file into memory
93 SMyFileHeader fileHeader;
94 file->read(&fileHeader, sizeof(SMyFileHeader));
95#ifdef __BIG_ENDIAN__
96 fileHeader.MyId = os::Byteswap::byteswap(fileHeader.MyId);
97 fileHeader.Ver = os::Byteswap::byteswap(fileHeader.Ver);
98#endif
99
100 if (fileHeader.MyId!=MY3D_ID || fileHeader.Ver!=MY3D_VER)
101 {
102 os::Printer::log("Bad MY3D file header, loading failed!", ELL_ERROR);
103 return 0;
104 }
105
106 u16 id;
107
108 file->read(&id, sizeof(id));
109#ifdef __BIG_ENDIAN__
110 id = os::Byteswap::byteswap(id);
111#endif
112
113 if (id!=MY3D_SCENE_HEADER_ID)
114 {
115 os::Printer::log("Cannot find MY3D_SCENE_HEADER_ID, loading failed!", ELL_ERROR);
116 return 0;
117 }
118
119 SMySceneHeader sceneHeader;
120 file->read(&sceneHeader, sizeof(SMySceneHeader));
121#ifdef __BIG_ENDIAN__
122 sceneHeader.MaterialCount = os::Byteswap::byteswap(sceneHeader.MaterialCount);
123 sceneHeader.MeshCount = os::Byteswap::byteswap(sceneHeader.MeshCount);
124#endif
125
126 file->read(&id, sizeof(id));
127#ifdef __BIG_ENDIAN__
128 id = os::Byteswap::byteswap(id);
129#endif
130
131 if (id!=MY3D_MAT_LIST_ID)
132 {
133 os::Printer::log("Can not find MY3D_MAT_LIST_ID, loading failed!", ELL_ERROR);
134 return 0;
135 }
136
137 core::stringc texturePath =
138 SceneManager->getParameters()->getAttributeAsString(MY3D_TEXTURE_PATH);
139
140 file->read(&id, sizeof(id));
141#ifdef __BIG_ENDIAN__
142 id = os::Byteswap::byteswap(id);
143#endif
144
145 c8 namebuf[256];
146 for (s32 m=0; m<sceneHeader.MaterialCount; ++m)
147 {
148 if (id != MY3D_MAT_HEADER_ID)
149 {
150 os::Printer::log("Cannot find MY3D_MAT_HEADER_ID, loading failed!", ELL_ERROR);
151 return 0;
152 }
153
154 // read material header
155 MaterialEntry.push_back(SMyMaterialEntry());
156 SMyMaterialEntry& me=MaterialEntry.getLast();
157 file->read(&(me.Header), sizeof(SMyMaterialHeader));
158
159 // read next identificator
160 file->read(&id, sizeof(id));
161#ifdef __BIG_ENDIAN__
162 id = os::Byteswap::byteswap(id);
163#endif
164
165 bool gotLightMap=false, gotMainMap=false;
166
167 for (u32 t=0; t<me.Header.TextureCount; ++t)
168 {
169 if (id==MY3D_TEX_FNAME_ID)
170 file->read(namebuf, 256);
171 else
172 {
173 me.Texture2 = readEmbeddedLightmap(file, namebuf);
174 if (!me.Texture2)
175 return 0;
176 gotLightMap = true;
177 }
178
179 const core::stringc name(namebuf);
180 const s32 pos = name.findLast('.');
181 const core::stringc LightingMapStr = "LightingMap";
182 const s32 ls = LightingMapStr.size();
183 const bool isSubString = (LightingMapStr == name.subString(core::max_(0, (pos - ls)), ls));
184 if ((isSubString || (name[pos-1]=='m' &&
185 name[pos-2]=='l' && name[pos-3]=='_')) &&
186 !gotLightMap)
187 {
188 const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
189 SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
190
191 me.Texture2FileName = texturePath.size() ? texturePath : filepath;
192 me.Texture2FileName.append("Lightmaps/");
193 me.Texture2FileName.append(name);
194
195 if (name.size())
196 me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName);
197
198 me.MaterialType = video::EMT_LIGHTMAP_M2;
199 gotLightMap = true;
200
201 SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
202 }
203 else
204 if (!gotLightMap && gotMainMap)
205 {
206 me.Texture2FileName = texturePath.size() ? texturePath : filepath;
207 me.Texture2FileName.append(name);
208
209 if (name.size())
210 me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName);
211
212 me.MaterialType = video::EMT_REFLECTION_2_LAYER;
213 }
214 else
215 if (!gotMainMap && !gotLightMap)
216 {
217 me.Texture1FileName = filepath;
218 me.Texture1FileName.append(name);
219 if (name.size())
220 me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName);
221
222 gotMainMap = true;
223 me.MaterialType = video::EMT_SOLID;
224 }
225 else
226 if (gotLightMap)
227 {
228 me.MaterialType = video::EMT_LIGHTMAP_M2;
229 }
230
231 file->read(&id, sizeof(id));
232#ifdef __BIG_ENDIAN__
233 id = os::Byteswap::byteswap(id);
234#endif
235 }
236
237 // override material types based on their names
238 if (!strncmp(me.Header.Name, "AlphaChannel-", 13))
239 me.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
240 else
241 if (!strncmp(me.Header.Name, "SphereMap-", 10))
242 me.MaterialType = video::EMT_SPHERE_MAP;
243 }
244
245 // loading meshes
246
247 if (id!=MY3D_MESH_LIST_ID)
248 {
249 os::Printer::log("Can not find MY3D_MESH_LIST_ID, loading failed!", ELL_ERROR);
250 return 0;
251 }
252
253 file->read(&id, sizeof(id));
254#ifdef __BIG_ENDIAN__
255 id = os::Byteswap::byteswap(id);
256#endif
257
258 for (s32 mesh_id=0; mesh_id<sceneHeader.MeshCount; mesh_id++)
259 {
260 // Warning!!! In some cases MY3D exporter uncorrectly calculates
261 // MeshCount (it's a problem, has to be solved) thats why
262 // i added this code line
263 if (id!=MY3D_MESH_HEADER_ID)
264 break;
265
266 if (id!=MY3D_MESH_HEADER_ID)
267 {
268 os::Printer::log("Can not find MY3D_MESH_HEADER_ID, loading failed!", ELL_ERROR);
269 return 0;
270 }
271
272 SMyMeshHeader meshHeader;
273 file->read(&meshHeader, sizeof(SMyMeshHeader));
274
275 core::array <SMyVertex> Vertex;
276 core::array <SMyFace> Face;
277 core::array <SMyTVertex> TVertex1, TVertex2;
278 core::array <SMyFace> TFace1, TFace2;
279
280 s32 vertsNum=0;
281 s32 facesNum=0;
282
283 // vertices
284 file->read(&id, sizeof(id));
285#ifdef __BIG_ENDIAN__
286 id = os::Byteswap::byteswap(id);
287#endif
288 if (id!=MY3D_VERTS_ID)
289 {
290 os::Printer::log("Can not find MY3D_VERTS_ID, loading failed!", ELL_ERROR);
291 return 0;
292 }
293
294 file->read(&vertsNum, sizeof(vertsNum));
295 Vertex.set_used(vertsNum);
296 file->read(Vertex.pointer(), sizeof(SMyVertex)*vertsNum);
297
298 // faces
299 file->read(&id, sizeof(id));
300#ifdef __BIG_ENDIAN__
301 id = os::Byteswap::byteswap(id);
302#endif
303 if (id!=MY3D_FACES_ID)
304 {
305 os::Printer::log("Can not find MY3D_FACES_ID, loading failed!", ELL_ERROR);
306 return 0;
307 }
308
309 file->read(&facesNum, sizeof(facesNum));
310 Face.set_used(facesNum);
311 file->read(Face.pointer(), sizeof(SMyFace)*facesNum);
312
313 // reading texture channels
314 for (s32 tex=0; tex<(s32)meshHeader.TChannelCnt; tex++)
315 {
316 // Max 2 texture channels allowed (but in format .my3d can be more)
317 s32 tVertsNum=0, tFacesNum=0;
318
319 // reading texture coords
320 file->read(&id, sizeof(id));
321#ifdef __BIG_ENDIAN__
322 id = os::Byteswap::byteswap(id);
323#endif
324
325 if (id!=MY3D_TVERTS_ID)
326 {
327 core::stringc msg="Can not find MY3D_TVERTS_ID (";
328 msg.append(core::stringc(tex));
329 msg.append("texture channel), loading failed!");
330 os::Printer::log(msg.c_str(), ELL_ERROR);
331 return 0;
332 }
333
334 file->read(&tVertsNum, sizeof(tVertsNum));
335
336 if (tex==0)
337 {
338 // 1st texture channel
339 TVertex1.set_used(tVertsNum);
340 file->read(TVertex1.pointer(), sizeof(SMyTVertex)*tVertsNum);
341 }
342 else
343 if (tex==1)
344 {
345 // 2nd texture channel
346 TVertex2.set_used(tVertsNum);
347 file->read(TVertex2.pointer(), sizeof(SMyTVertex)*tVertsNum);
348 }
349 else
350 {
351 // skip other texture channels
352 file->seek(file->getPos()+sizeof(SMyTVertex)*tVertsNum);
353 }
354
355 // reading texture faces
356 file->read(&id, sizeof(id));
357#ifdef __BIG_ENDIAN__
358 id = os::Byteswap::byteswap(id);
359#endif
360
361 if (id!=MY3D_TFACES_ID)
362 {
363 core::stringc msg="Can not find MY3D_TFACES_ID (";
364 msg.append(core::stringc(tex));
365 msg.append("texture channel), loading failed!");
366 os::Printer::log(msg.c_str(), ELL_ERROR);
367 return 0;
368 }
369
370 file->read(&tFacesNum, sizeof(tFacesNum));
371
372 if (tex==0)
373 {
374 // 1st texture channel
375 TFace1.set_used(tFacesNum);
376 file->read(TFace1.pointer(), sizeof(SMyFace)*tFacesNum);
377 }
378 else if (tex==1)
379 {
380 // 2nd texture channel
381 TFace2.set_used(tFacesNum);
382 file->read(TFace2.pointer(), sizeof(SMyFace)*tFacesNum);
383 }
384 else
385 {
386 // skip other texture channels
387 file->seek(file->getPos()+sizeof(SMyFace)*tFacesNum);
388 }
389 }
390
391 // trying to find material
392
393 SMyMaterialEntry* matEnt = getMaterialEntryByIndex(meshHeader.MatIndex);
394
395 // creating geometry for the mesh
396
397 // trying to find mesh buffer for this material
398 SMeshBufferLightMap* buffer = getMeshBufferByMaterialIndex(meshHeader.MatIndex);
399
400 if (!buffer ||
401 (buffer->Vertices.size()+vertsNum) > SceneManager->getVideoDriver()->getMaximalPrimitiveCount())
402 {
403 // creating new mesh buffer for this material
404 buffer = new scene::SMeshBufferLightMap();
405
406 buffer->Material.MaterialType = video::EMT_LIGHTMAP_M2; // EMT_LIGHTMAP_M4 also possible
407 buffer->Material.Wireframe = false;
408 buffer->Material.Lighting = false;
409
410 if (matEnt)
411 {
412 buffer->Material.MaterialType = matEnt->MaterialType;
413
414 if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER)
415 {
416 buffer->Material.Lighting = true;
417 buffer->Material.setTexture(1, matEnt->Texture1);
418 buffer->Material.setTexture(0, matEnt->Texture2);
419 }
420 else
421 {
422 buffer->Material.setTexture(0, matEnt->Texture1);
423 buffer->Material.setTexture(1, matEnt->Texture2);
424 }
425
426 if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL)
427 {
428 buffer->Material.BackfaceCulling = true;
429 buffer->Material.Lighting = true;
430 }
431 else
432 if (buffer->Material.MaterialType == video::EMT_SPHERE_MAP)
433 {
434 buffer->Material.Lighting = true;
435 }
436
437 buffer->Material.AmbientColor = video::SColor(
438 matEnt->Header.AmbientColor.A, matEnt->Header.AmbientColor.R,
439 matEnt->Header.AmbientColor.G, matEnt->Header.AmbientColor.B
440 );
441 buffer->Material.DiffuseColor = video::SColor(
442 matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R,
443 matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B
444 );
445 buffer->Material.EmissiveColor = video::SColor(
446 matEnt->Header.EmissiveColor.A, matEnt->Header.EmissiveColor.R,
447 matEnt->Header.EmissiveColor.G, matEnt->Header.EmissiveColor.B
448 );
449 buffer->Material.SpecularColor = video::SColor(
450 matEnt->Header.SpecularColor.A, matEnt->Header.SpecularColor.R,
451 matEnt->Header.SpecularColor.G, matEnt->Header.SpecularColor.B
452 );
453 }
454 else
455 {
456 buffer->Material.setTexture(0, 0);
457 buffer->Material.setTexture(1, 0);
458
459 buffer->Material.AmbientColor = video::SColor(255, 255, 255, 255);
460 buffer->Material.DiffuseColor = video::SColor(255, 255, 255, 255);
461 buffer->Material.EmissiveColor = video::SColor(0, 0, 0, 0);
462 buffer->Material.SpecularColor = video::SColor(0, 0, 0, 0);
463 }
464
465 if (matEnt && matEnt->Header.Transparency!=0)
466 {
467 if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER )
468 {
469 buffer->Material.MaterialType = video::EMT_TRANSPARENT_REFLECTION_2_LAYER;
470 buffer->Material.Lighting = true;
471 buffer->Material.BackfaceCulling = true;
472 }
473 else
474 {
475 buffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
476 buffer->Material.Lighting = false;
477 buffer->Material.BackfaceCulling = false;
478 }
479 }
480 else if (
481 !buffer->Material.getTexture(1) &&
482 buffer->Material.MaterialType != video::EMT_TRANSPARENT_ALPHA_CHANNEL &&
483 buffer->Material.MaterialType != video::EMT_SPHERE_MAP)
484 {
485 buffer->Material.MaterialType = video::EMT_SOLID;
486 buffer->Material.Lighting = true;
487 }
488
489 MeshBufferEntry.push_back(
490 SMyMeshBufferEntry(meshHeader.MatIndex, buffer));
491 }
492
493 video::S3DVertex2TCoords VertexA, VertexB, VertexC;
494
495 // vertices (A, B, C) color
496 video::SColor vert_color;
497 if (matEnt &&
498 (buffer->Material.MaterialType == video::EMT_TRANSPARENT_VERTEX_ALPHA ||
499 buffer->Material.MaterialType == video::EMT_TRANSPARENT_REFLECTION_2_LAYER))
500 {
501 video::SColor color(
502 matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R,
503 matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B);
504
505 vert_color = color.getInterpolated(video::SColor(0,0,0,0),
506 1-matEnt->Header.Transparency);
507 }
508 else
509 {
510 vert_color = buffer->Material.DiffuseColor;
511 }
512
513 VertexA.Color = VertexB.Color = VertexC.Color = vert_color;
514
515 if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL)
516 {
517 buffer->Indices.reallocate(buffer->Indices.size()+6*facesNum);
518 buffer->Vertices.reallocate(buffer->Vertices.size()+6*facesNum);
519 }
520 else
521 {
522 buffer->Indices.reallocate(buffer->Indices.size()+3*facesNum);
523 buffer->Vertices.reallocate(buffer->Vertices.size()+3*facesNum);
524 }
525 for (int f=0; f<facesNum; f++)
526 {
527 // vertex A
528
529 VertexA.Pos.X = Vertex[Face[f].C].Coord.X;
530 VertexA.Pos.Y = Vertex[Face[f].C].Coord.Y;
531 VertexA.Pos.Z = Vertex[Face[f].C].Coord.Z;
532
533 VertexA.Normal.X = Vertex[Face[f].C].Normal.X;
534 VertexA.Normal.Y = Vertex[Face[f].C].Normal.Y;
535 VertexA.Normal.Z = Vertex[Face[f].C].Normal.Z;
536
537 if (meshHeader.TChannelCnt>0)
538 {
539 VertexA.TCoords.X = TVertex1[TFace1[f].C].TCoord.X;
540 VertexA.TCoords.Y = TVertex1[TFace1[f].C].TCoord.Y;
541 }
542
543 if (meshHeader.TChannelCnt>1)
544 {
545 VertexA.TCoords2.X = TVertex2[TFace2[f].C].TCoord.X;
546 VertexA.TCoords2.Y = TVertex2[TFace2[f].C].TCoord.Y;
547 }
548
549 // vertex B
550
551 VertexB.Pos.X = Vertex[Face[f].B].Coord.X;
552 VertexB.Pos.Y = Vertex[Face[f].B].Coord.Y;
553 VertexB.Pos.Z = Vertex[Face[f].B].Coord.Z;
554
555 VertexB.Normal.X = Vertex[Face[f].B].Normal.X;
556 VertexB.Normal.Y = Vertex[Face[f].B].Normal.Y;
557 VertexB.Normal.Z = Vertex[Face[f].B].Normal.Z;
558
559 if (meshHeader.TChannelCnt>0)
560 {
561 VertexB.TCoords.X = TVertex1[TFace1[f].B].TCoord.X;
562 VertexB.TCoords.Y = TVertex1[TFace1[f].B].TCoord.Y;
563 }
564
565 if (meshHeader.TChannelCnt>1)
566 {
567 VertexB.TCoords2.X = TVertex2[TFace2[f].B].TCoord.X;
568 VertexB.TCoords2.Y = TVertex2[TFace2[f].B].TCoord.Y;
569 }
570
571 // vertex C
572
573 VertexC.Pos.X = Vertex[Face[f].A].Coord.X;
574 VertexC.Pos.Y = Vertex[Face[f].A].Coord.Y;
575 VertexC.Pos.Z = Vertex[Face[f].A].Coord.Z;
576
577 VertexC.Normal.X = Vertex[Face[f].A].Normal.X;
578 VertexC.Normal.Y = Vertex[Face[f].A].Normal.Y;
579 VertexC.Normal.Z = Vertex[Face[f].A].Normal.Z;
580
581 if (meshHeader.TChannelCnt>0)
582 {
583 VertexC.TCoords.X = TVertex1[TFace1[f].A].TCoord.X;
584 VertexC.TCoords.Y = TVertex1[TFace1[f].A].TCoord.Y;
585 }
586 if (meshHeader.TChannelCnt>1)
587 {
588 VertexC.TCoords2.X = TVertex2[TFace2[f].A].TCoord.X;
589 VertexC.TCoords2.Y = TVertex2[TFace2[f].A].TCoord.Y;
590 }
591
592 // store 3d data in mesh buffer
593
594 buffer->Indices.push_back(buffer->Vertices.size());
595 buffer->Vertices.push_back(VertexA);
596
597 buffer->Indices.push_back(buffer->Vertices.size());
598 buffer->Vertices.push_back(VertexB);
599
600 buffer->Indices.push_back(buffer->Vertices.size());
601 buffer->Vertices.push_back(VertexC);
602
603 //*****************************************************************
604 // !!!!!! W A R N I N G !!!!!!!
605 //*****************************************************************
606 // For materials with alpha channel we duplicate all faces.
607 // This has be done for proper lighting calculation of the back faces.
608 // So you must remember this while you creating your models !!!!!
609 //*****************************************************************
610 // !!!!!! W A R N I N G !!!!!!!
611 //*****************************************************************
612
613 if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL)
614 {
615 VertexA.Normal = core::vector3df(-VertexA.Normal.X, -VertexA.Normal.Y, -VertexA.Normal.Z);
616 VertexB.Normal = core::vector3df(-VertexB.Normal.X, -VertexB.Normal.Y, -VertexB.Normal.Z);
617 VertexC.Normal = core::vector3df(-VertexC.Normal.X, -VertexC.Normal.Y, -VertexC.Normal.Z);
618
619 buffer->Indices.push_back(buffer->Vertices.size());
620 buffer->Vertices.push_back(VertexC);
621
622 buffer->Indices.push_back(buffer->Vertices.size());
623 buffer->Vertices.push_back(VertexB);
624
625 buffer->Indices.push_back(buffer->Vertices.size());
626 buffer->Vertices.push_back(VertexA);
627 }
628 }
629 file->read(&id, sizeof(id));
630#ifdef __BIG_ENDIAN__
631 id = os::Byteswap::byteswap(id);
632#endif
633 }
634
635 // creating mesh
636 SMesh* mesh = new SMesh();
637
638 for (u32 num=0; num<MeshBufferEntry.size(); ++num)
639 {
640 SMeshBufferLightMap* buffer = MeshBufferEntry[num].MeshBuffer;
641
642 if (!buffer)
643 continue;
644
645 mesh->addMeshBuffer(buffer);
646
647 buffer->recalculateBoundingBox();
648 buffer->drop();
649 }
650
651 mesh->recalculateBoundingBox();
652
653 if (id != MY3D_FILE_END_ID)
654 os::Printer::log("Loading finished, but can not find MY3D_FILE_END_ID token.", ELL_WARNING);
655
656 SAnimatedMesh* am = new SAnimatedMesh();
657
658 am->addMesh(mesh);
659 mesh->drop();
660 am->recalculateBoundingBox();
661
662 return am;
663}
664
665
666video::ITexture* CMY3DMeshFileLoader::readEmbeddedLightmap(io::IReadFile* file, char* namebuf)
667{
668 static int LightMapIndex=0;
669 u16 id;
670 file->read(&id, sizeof(id));
671#ifdef __BIG_ENDIAN__
672 id = os::Byteswap::byteswap(id);
673#endif
674 if (id!=MY3D_TEXDATA_HEADER_ID)
675 {
676 os::Printer::log("Can not find MY3D_TEXDATA_HEADER_ID, loading failed!", ELL_ERROR);
677 return 0;
678 }
679
680 SMyTexDataHeader texDataHeader;
681
682 file->read(&texDataHeader, sizeof(SMyTexDataHeader));
683
684 strcpy(texDataHeader.Name, namebuf);
685
686 char LightMapName[255];
687 sprintf(LightMapName,"My3D.Lightmap.%d",++LightMapIndex);
688
689 core::stringc pixFormatStr;
690 if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
691 pixFormatStr = "24bit,";
692 else
693 if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_16)
694 pixFormatStr = "16bit,";
695 else
696 {
697 core::stringc msg="Unknown format of image data (";
698 msg.append(LightMapName);
699 msg.append("), loading failed!");
700 os::Printer::log(msg.c_str(), ELL_ERROR);
701 return 0;
702 }
703
704 if (texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_NONE_ID &&
705 texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_RLE_ID &&
706 texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_SIMPLE_ID )
707 {
708 os::Printer::log("Unknown method of compression image data, loading failed!", ELL_ERROR);
709 return 0;
710 }
711
712 const u32 num_pixels = texDataHeader.Width*texDataHeader.Height;
713
714 void* data = 0;
715
716 if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_NONE_ID)
717 {
718 // none compressed image data
719 if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
720 {
721 data = (void*) new SMyPixelColor24[num_pixels];
722 file->read(data, sizeof(SMyPixelColor24)*num_pixels);
723 }
724 else
725 {
726 data = (void*) new SMyPixelColor16[num_pixels];
727 file->read(data, sizeof(SMyPixelColor16)*num_pixels);
728 }
729 }
730 else
731 if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_RLE_ID)
732 {
733 // read RLE header identificator
734 file->read(&id, sizeof(id));
735#ifdef __BIG_ENDIAN__
736 id = os::Byteswap::byteswap(id);
737#endif
738 if (id!=MY3D_TEXDATA_RLE_HEADER_ID)
739 {
740 os::Printer::log("Can not find MY3D_TEXDATA_RLE_HEADER_ID, loading failed!", ELL_ERROR);
741 return 0;
742 }
743
744 // read RLE header
745 SMyRLEHeader rleHeader;
746 file->read(&rleHeader, sizeof(SMyRLEHeader));
747
748 //allocate memory for input and output buffers
749 void *input_buffer = (void*) new unsigned char[rleHeader.nEncodedBytes];
750 void *output_buffer = (void*) new unsigned char[rleHeader.nDecodedBytes];
751
752 // read encoded data
753 file->read(input_buffer, rleHeader.nEncodedBytes);
754
755 // decode data
756 data = 0;//(void*) new unsigned char[rleHeader.nDecodedBytes];
757 s32 decodedBytes = core::rle_decode(
758 (unsigned char*)input_buffer, rleHeader.nEncodedBytes,
759 (unsigned char*)output_buffer, rleHeader.nDecodedBytes);
760
761 if (decodedBytes!=(s32)rleHeader.nDecodedBytes)
762 {
763 os::Printer::log("Error extracting data from RLE compression, loading failed!", ELL_ERROR);
764 return 0;
765 }
766
767 // free input buffer
768 delete [] (unsigned char*)input_buffer;
769
770 // here decoded data
771 data = output_buffer;
772 }
773 else if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_SIMPLE_ID)
774 {
775 // simple compressed image data
776 if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
777 data = (void*) new SMyPixelColor24[num_pixels];
778 else
779 data = (void*) new SMyPixelColor16[num_pixels];
780
781 u32 nReadedPixels=0, nToRead=0;
782 while (true)
783 {
784 file->read(&nToRead, sizeof(nToRead));
785
786 if ((nReadedPixels+nToRead) > num_pixels)
787 break;
788
789 if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
790 {
791 SMyPixelColor24 col24;
792 file->read(&col24, sizeof(SMyPixelColor24));
793 for (u32 p=0; p<nToRead; p++)
794 {
795 ((SMyPixelColor24*)data)[nReadedPixels+p] =
796 SMyPixelColor24(col24.r, col24.g, col24.b);
797 }
798 }
799 else
800 {
801 SMyPixelColor16 col16;
802 file->read(&col16, sizeof(SMyPixelColor16));
803 for (u32 p=0; p<nToRead; p++)
804 ((SMyPixelColor16*)data)[nReadedPixels+p].argb = col16.argb;
805 }
806
807 nReadedPixels+=nToRead;
808
809 if (nReadedPixels >= num_pixels)
810 break;
811 }
812
813 if (nReadedPixels != num_pixels)
814 {
815 os::Printer::log("Image data seems to be corrupted, loading failed!", ELL_ERROR);
816 return 0;
817 }
818 }
819
820 //! Creates a software image from a byte array.
821 video::IImage* light_img = 0;
822
823 if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
824 {
825 // 24 bit lightmap format
826 light_img = SceneManager->getVideoDriver()->createImageFromData(
827 video::ECF_R8G8B8,
828 core::dimension2d<u32>(texDataHeader.Width, texDataHeader.Height),
829 data, true);
830 }
831 else
832 {
833 // 16 bit lightmap format
834 light_img = SceneManager->getVideoDriver()->createImageFromData(
835 video::ECF_A1R5G5B5,
836 core::dimension2d<u32>(texDataHeader.Width, texDataHeader.Height),
837 data, true);
838 }
839
840 const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
841 SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
842 video::ITexture* lmtex = SceneManager->getVideoDriver()->addTexture(LightMapName, light_img);
843 SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
844
845 light_img->drop();
846 return lmtex;
847}
848
849
850CMY3DMeshFileLoader::SMyMaterialEntry* CMY3DMeshFileLoader::getMaterialEntryByIndex(u32 matInd)
851{
852 for (u32 m=0; m<MaterialEntry.size(); ++m)
853 if (MaterialEntry[m].Header.Index == matInd)
854 return &MaterialEntry[m];
855
856 return 0;
857}
858
859
860
861SMeshBufferLightMap* CMY3DMeshFileLoader::getMeshBufferByMaterialIndex(u32 matInd)
862{
863 for (u32 m=0; m<MeshBufferEntry.size(); ++m)
864 {
865 if (MeshBufferEntry[m].MaterialIndex == (s32)matInd)
866 return MeshBufferEntry[m].MeshBuffer;
867 }
868 return 0;
869}
870
871
872const core::array<ISceneNode*>& CMY3DMeshFileLoader::getChildNodes() const
873{
874 return ChildNodes;
875}
876
877
878} // end namespace scnene
879} // end namespace irr
880
881#endif // _IRR_COMPILE_WITH_MY3D_LOADER_
882