diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CMY3DMeshFileLoader.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CMY3DMeshFileLoader.cpp | 882 |
1 files changed, 0 insertions, 882 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CMY3DMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CMY3DMeshFileLoader.cpp deleted file mode 100644 index b993d9a..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/CMY3DMeshFileLoader.cpp +++ /dev/null | |||
@@ -1,882 +0,0 @@ | |||
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 | |||
26 | namespace irr | ||
27 | { | ||
28 | namespace scene | ||
29 | { | ||
30 | |||
31 | static const u32 MY3D_ID = 0x4d593344; | ||
32 | static const u16 MY3D_VER = 0x0003; | ||
33 | static const u16 MY3D_SCENE_HEADER_ID = 0x1000; | ||
34 | static const u16 MY3D_MAT_LIST_ID = 0x2000; | ||
35 | static const u16 MY3D_MAT_HEADER_ID = 0x2100; | ||
36 | static const u16 MY3D_TEX_FNAME_ID = 0x2101; | ||
37 | static const u16 MY3D_TEXDATA_HEADER_ID = 0x2501; | ||
38 | static const u16 MY3D_TEXDATA_RLE_HEADER_ID = 0x2502; | ||
39 | static const u16 MY3D_MESH_LIST_ID = 0x3000; | ||
40 | static const u16 MY3D_MESH_HEADER_ID = 0x3100; | ||
41 | static const u16 MY3D_VERTS_ID = 0x3101; | ||
42 | static const u16 MY3D_FACES_ID = 0x3102; | ||
43 | static const u16 MY3D_TVERTS_ID = 0x3103; | ||
44 | static const u16 MY3D_TFACES_ID = 0x3104; | ||
45 | static const u16 MY3D_FILE_END_ID = 0xFFFF; | ||
46 | |||
47 | static const unsigned long MY3D_TEXDATA_COMPR_NONE_ID = 0x4e4f4e45; | ||
48 | static const unsigned long MY3D_TEXDATA_COMPR_SIMPLE_ID = 0x53494d50; | ||
49 | static const unsigned long MY3D_TEXDATA_COMPR_RLE_ID = 0x20524c45; | ||
50 | |||
51 | static const unsigned long MY3D_PIXEL_FORMAT_24 = 0x5f32345f; | ||
52 | static const unsigned long MY3D_PIXEL_FORMAT_16 = 0x5f31365f; | ||
53 | |||
54 | CMY3DMeshFileLoader::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 | |||
66 | CMY3DMeshFileLoader::~CMY3DMeshFileLoader() | ||
67 | { | ||
68 | if (FileSystem) | ||
69 | FileSystem->drop(); | ||
70 | } | ||
71 | |||
72 | |||
73 | bool CMY3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | ||
74 | { | ||
75 | return core::hasFileExtension ( filename, "my3d" ); | ||
76 | } | ||
77 | |||
78 | |||
79 | IAnimatedMesh* 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 | |||
666 | video::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 | |||
850 | CMY3DMeshFileLoader::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 | |||
861 | SMeshBufferLightMap* 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 | |||
872 | const 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 | |||