diff options
author | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
commit | f9158592e1478b2013afc7041d9ed041cf2d2f4a (patch) | |
tree | b16e389d7988700e21b4c9741044cefa536dcbae /libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp | |
parent | Libraries readme updated with change markers and more of the Irrlicht changes. (diff) | |
download | SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.zip SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.gz SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.bz2 SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.xz |
Update Irrlicht to 1.8.1. Include actual change markers this time. lol
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp | 1396 |
1 files changed, 0 insertions, 1396 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp deleted file mode 100644 index e1f312d..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp +++ /dev/null | |||
@@ -1,1396 +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 | #include "IrrCompileConfig.h" | ||
6 | #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ | ||
7 | |||
8 | #include "C3DSMeshFileLoader.h" | ||
9 | #include "os.h" | ||
10 | #include "SMeshBuffer.h" | ||
11 | #include "SAnimatedMesh.h" | ||
12 | #include "IReadFile.h" | ||
13 | #include "IVideoDriver.h" | ||
14 | #include "IMeshManipulator.h" | ||
15 | |||
16 | #ifdef _DEBUG | ||
17 | #define _IRR_DEBUG_3DS_LOADER_ | ||
18 | #endif | ||
19 | |||
20 | namespace irr | ||
21 | { | ||
22 | namespace scene | ||
23 | { | ||
24 | |||
25 | |||
26 | namespace | ||
27 | { | ||
28 | enum e3DSChunk | ||
29 | { | ||
30 | // Primary chunk | ||
31 | C3DS_MAIN3DS = 0x4D4D, | ||
32 | |||
33 | // Main Chunks | ||
34 | C3DS_EDIT3DS = 0x3D3D, | ||
35 | C3DS_KEYF3DS = 0xB000, | ||
36 | C3DS_VERSION = 0x0002, | ||
37 | C3DS_MESHVERSION = 0x3D3E, | ||
38 | |||
39 | // sub chunks of C3DS_EDIT3DS | ||
40 | C3DS_EDIT_MATERIAL = 0xAFFF, | ||
41 | C3DS_EDIT_OBJECT = 0x4000, | ||
42 | |||
43 | // sub chunks of C3DS_EDIT_MATERIAL | ||
44 | C3DS_MATNAME = 0xA000, | ||
45 | C3DS_MATAMBIENT = 0xA010, | ||
46 | C3DS_MATDIFFUSE = 0xA020, | ||
47 | C3DS_MATSPECULAR = 0xA030, | ||
48 | C3DS_MATSHININESS = 0xA040, | ||
49 | C3DS_MATSHIN2PCT = 0xA041, | ||
50 | C3DS_TRANSPARENCY = 0xA050, | ||
51 | C3DS_TRANSPARENCY_FALLOFF = 0xA052, | ||
52 | C3DS_REFL_BLUR = 0xA053, | ||
53 | C3DS_TWO_SIDE = 0xA081, | ||
54 | C3DS_WIRE = 0xA085, | ||
55 | C3DS_SHADING = 0xA100, | ||
56 | C3DS_MATTEXMAP = 0xA200, | ||
57 | C3DS_MATSPECMAP = 0xA204, | ||
58 | C3DS_MATOPACMAP = 0xA210, | ||
59 | C3DS_MATREFLMAP = 0xA220, | ||
60 | C3DS_MATBUMPMAP = 0xA230, | ||
61 | C3DS_MATMAPFILE = 0xA300, | ||
62 | C3DS_MAT_TEXTILING = 0xA351, | ||
63 | C3DS_MAT_USCALE = 0xA354, | ||
64 | C3DS_MAT_VSCALE = 0xA356, | ||
65 | C3DS_MAT_UOFFSET = 0xA358, | ||
66 | C3DS_MAT_VOFFSET = 0xA35A, | ||
67 | |||
68 | // subs of C3DS_EDIT_OBJECT | ||
69 | C3DS_OBJTRIMESH = 0x4100, | ||
70 | |||
71 | // subs of C3DS_OBJTRIMESH | ||
72 | C3DS_TRIVERT = 0x4110, | ||
73 | C3DS_POINTFLAGARRAY= 0x4111, | ||
74 | C3DS_TRIFACE = 0x4120, | ||
75 | C3DS_TRIFACEMAT = 0x4130, | ||
76 | C3DS_TRIUV = 0x4140, | ||
77 | C3DS_TRISMOOTH = 0x4150, | ||
78 | C3DS_TRIMATRIX = 0x4160, | ||
79 | C3DS_MESHCOLOR = 0x4165, | ||
80 | C3DS_DIRECT_LIGHT = 0x4600, | ||
81 | C3DS_DL_INNER_RANGE= 0x4659, | ||
82 | C3DS_DL_OUTER_RANGE= 0x465A, | ||
83 | C3DS_DL_MULTIPLIER = 0x465B, | ||
84 | C3DS_CAMERA = 0x4700, | ||
85 | C3DS_CAM_SEE_CONE = 0x4710, | ||
86 | C3DS_CAM_RANGES = 0x4720, | ||
87 | |||
88 | // subs of C3DS_KEYF3DS | ||
89 | C3DS_KF_HDR = 0xB00A, | ||
90 | C3DS_AMBIENT_TAG = 0xB001, | ||
91 | C3DS_OBJECT_TAG = 0xB002, | ||
92 | C3DS_CAMERA_TAG = 0xB003, | ||
93 | C3DS_TARGET_TAG = 0xB004, | ||
94 | C3DS_LIGHTNODE_TAG = 0xB005, | ||
95 | C3DS_KF_SEG = 0xB008, | ||
96 | C3DS_KF_CURTIME = 0xB009, | ||
97 | C3DS_KF_NODE_HDR = 0xB010, | ||
98 | C3DS_PIVOTPOINT = 0xB013, | ||
99 | C3DS_BOUNDBOX = 0xB014, | ||
100 | C3DS_MORPH_SMOOTH = 0xB015, | ||
101 | C3DS_POS_TRACK_TAG = 0xB020, | ||
102 | C3DS_ROT_TRACK_TAG = 0xB021, | ||
103 | C3DS_SCL_TRACK_TAG = 0xB022, | ||
104 | C3DS_NODE_ID = 0xB030, | ||
105 | |||
106 | // Viewport definitions | ||
107 | C3DS_VIEWPORT_LAYOUT = 0x7001, | ||
108 | C3DS_VIEWPORT_DATA = 0x7011, | ||
109 | C3DS_VIEWPORT_DATA_3 = 0x7012, | ||
110 | C3DS_VIEWPORT_SIZE = 0x7020, | ||
111 | |||
112 | // different color chunk types | ||
113 | C3DS_COL_RGB = 0x0010, | ||
114 | C3DS_COL_TRU = 0x0011, | ||
115 | C3DS_COL_LIN_24 = 0x0012, | ||
116 | C3DS_COL_LIN_F = 0x0013, | ||
117 | |||
118 | // percentage chunk types | ||
119 | C3DS_PERCENTAGE_I = 0x0030, | ||
120 | C3DS_PERCENTAGE_F = 0x0031, | ||
121 | |||
122 | C3DS_CHUNK_MAX = 0xFFFF | ||
123 | }; | ||
124 | } | ||
125 | |||
126 | |||
127 | //! Constructor | ||
128 | C3DSMeshFileLoader::C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs) | ||
129 | : SceneManager(smgr), FileSystem(fs), Vertices(0), Indices(0), SmoothingGroups(0), TCoords(0), | ||
130 | CountVertices(0), CountFaces(0), CountTCoords(0), Mesh(0) | ||
131 | { | ||
132 | |||
133 | #ifdef _DEBUG | ||
134 | setDebugName("C3DSMeshFileLoader"); | ||
135 | #endif | ||
136 | |||
137 | if (FileSystem) | ||
138 | FileSystem->grab(); | ||
139 | } | ||
140 | |||
141 | |||
142 | //! destructor | ||
143 | C3DSMeshFileLoader::~C3DSMeshFileLoader() | ||
144 | { | ||
145 | cleanUp(); | ||
146 | |||
147 | if (FileSystem) | ||
148 | FileSystem->drop(); | ||
149 | |||
150 | if (Mesh) | ||
151 | Mesh->drop(); | ||
152 | } | ||
153 | |||
154 | |||
155 | //! returns true if the file maybe is able to be loaded by this class | ||
156 | //! based on the file extension (e.g. ".bsp") | ||
157 | bool C3DSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | ||
158 | { | ||
159 | return core::hasFileExtension ( filename, "3ds" ); | ||
160 | } | ||
161 | |||
162 | |||
163 | //! creates/loads an animated mesh from the file. | ||
164 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | ||
165 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | ||
166 | //! See IReferenceCounted::drop() for more information. | ||
167 | IAnimatedMesh* C3DSMeshFileLoader::createMesh(io::IReadFile* file) | ||
168 | { | ||
169 | ChunkData data; | ||
170 | |||
171 | readChunkData(file, data); | ||
172 | |||
173 | if (data.header.id != C3DS_MAIN3DS ) | ||
174 | return 0; | ||
175 | |||
176 | CurrentMaterial.clear(); | ||
177 | Materials.clear(); | ||
178 | MeshBufferNames.clear(); | ||
179 | cleanUp(); | ||
180 | |||
181 | if (Mesh) | ||
182 | Mesh->drop(); | ||
183 | |||
184 | Mesh = new SMesh(); | ||
185 | |||
186 | if (readChunk(file, &data)) | ||
187 | { | ||
188 | // success | ||
189 | |||
190 | for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i) | ||
191 | { | ||
192 | SMeshBuffer* mb = ((SMeshBuffer*)Mesh->getMeshBuffer(i)); | ||
193 | // drop empty buffers | ||
194 | if (mb->getIndexCount() == 0 || mb->getVertexCount() == 0) | ||
195 | { | ||
196 | Mesh->MeshBuffers.erase(i--); | ||
197 | mb->drop(); | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | if (mb->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) | ||
202 | { | ||
203 | SMesh tmp; | ||
204 | tmp.addMeshBuffer(mb); | ||
205 | mb->drop(); | ||
206 | IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); | ||
207 | Mesh->MeshBuffers[i]=tangentMesh->getMeshBuffer(0); | ||
208 | // we need to grab because we replace the buffer manually. | ||
209 | Mesh->MeshBuffers[i]->grab(); | ||
210 | // clean up intermediate mesh struct | ||
211 | tangentMesh->drop(); | ||
212 | } | ||
213 | Mesh->MeshBuffers[i]->recalculateBoundingBox(); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | Mesh->recalculateBoundingBox(); | ||
218 | |||
219 | SAnimatedMesh* am = new SAnimatedMesh(); | ||
220 | am->Type = EAMT_3DS; | ||
221 | am->addMesh(Mesh); | ||
222 | am->recalculateBoundingBox(); | ||
223 | Mesh->drop(); | ||
224 | Mesh = 0; | ||
225 | return am; | ||
226 | } | ||
227 | |||
228 | Mesh->drop(); | ||
229 | Mesh = 0; | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | |||
235 | bool C3DSMeshFileLoader::readPercentageChunk(io::IReadFile* file, | ||
236 | ChunkData* chunk, f32& percentage) | ||
237 | { | ||
238 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
239 | os::Printer::log("Load percentage chunk.", ELL_DEBUG); | ||
240 | #endif | ||
241 | |||
242 | ChunkData data; | ||
243 | readChunkData(file, data); | ||
244 | |||
245 | short intpercentage; | ||
246 | float fpercentage; | ||
247 | |||
248 | switch(data.header.id) | ||
249 | { | ||
250 | case C3DS_PERCENTAGE_I: | ||
251 | { | ||
252 | // read short | ||
253 | file->read(&intpercentage, 2); | ||
254 | #ifdef __BIG_ENDIAN__ | ||
255 | intpercentage = os::Byteswap::byteswap(intpercentage); | ||
256 | #endif | ||
257 | percentage=intpercentage/100.0f; | ||
258 | data.read += 2; | ||
259 | } | ||
260 | break; | ||
261 | case C3DS_PERCENTAGE_F: | ||
262 | { | ||
263 | // read float | ||
264 | file->read(&fpercentage, sizeof(float)); | ||
265 | data.read += sizeof(float); | ||
266 | #ifdef __BIG_ENDIAN__ | ||
267 | percentage = os::Byteswap::byteswap(fpercentage); | ||
268 | #else | ||
269 | percentage = (f32)fpercentage; | ||
270 | #endif | ||
271 | } | ||
272 | break; | ||
273 | default: | ||
274 | { | ||
275 | // unknown percentage chunk | ||
276 | os::Printer::log("Unknown percentage chunk in 3Ds file.", ELL_WARNING); | ||
277 | file->seek(data.header.length - data.read, true); | ||
278 | data.read += data.header.length - data.read; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | chunk->read += data.read; | ||
283 | |||
284 | return true; | ||
285 | } | ||
286 | |||
287 | bool C3DSMeshFileLoader::readColorChunk(io::IReadFile* file, ChunkData* chunk, | ||
288 | video::SColor& out) | ||
289 | { | ||
290 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
291 | os::Printer::log("Load color chunk.", ELL_DEBUG); | ||
292 | #endif | ||
293 | ChunkData data; | ||
294 | readChunkData(file, data); | ||
295 | |||
296 | u8 c[3]; | ||
297 | f32 cf[3]; | ||
298 | |||
299 | switch(data.header.id) | ||
300 | { | ||
301 | case C3DS_COL_TRU: | ||
302 | case C3DS_COL_LIN_24: | ||
303 | { | ||
304 | // read 8 bit data | ||
305 | file->read(c, sizeof(c)); | ||
306 | out.set(255, c[0], c[1], c[2]); | ||
307 | data.read += sizeof(c); | ||
308 | } | ||
309 | break; | ||
310 | case C3DS_COL_RGB: | ||
311 | case C3DS_COL_LIN_F: | ||
312 | { | ||
313 | // read float data | ||
314 | file->read(cf, sizeof(cf)); | ||
315 | #ifdef __BIG_ENDIAN__ | ||
316 | cf[0] = os::Byteswap::byteswap(cf[0]); | ||
317 | cf[1] = os::Byteswap::byteswap(cf[1]); | ||
318 | cf[2] = os::Byteswap::byteswap(cf[2]); | ||
319 | #endif | ||
320 | out.set(255, (s32)(cf[0]*255.0f), (s32)(cf[1]*255.0f), (s32)(cf[2]*255.0f)); | ||
321 | data.read += sizeof(cf); | ||
322 | } | ||
323 | break; | ||
324 | default: | ||
325 | { | ||
326 | // unknown color chunk size | ||
327 | os::Printer::log("Unknown size of color chunk in 3Ds file.", ELL_WARNING); | ||
328 | file->seek(data.header.length - data.read, true); | ||
329 | data.read += data.header.length - data.read; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | chunk->read += data.read; | ||
334 | |||
335 | return true; | ||
336 | } | ||
337 | |||
338 | |||
339 | bool C3DSMeshFileLoader::readMaterialChunk(io::IReadFile* file, ChunkData* parent) | ||
340 | { | ||
341 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
342 | os::Printer::log("Load material chunk.", ELL_DEBUG); | ||
343 | #endif | ||
344 | u16 matSection=0; | ||
345 | |||
346 | while(parent->read < parent->header.length) | ||
347 | { | ||
348 | ChunkData data; | ||
349 | readChunkData(file, data); | ||
350 | |||
351 | switch(data.header.id) | ||
352 | { | ||
353 | case C3DS_MATNAME: | ||
354 | { | ||
355 | c8* c = new c8[data.header.length - data.read]; | ||
356 | file->read(c, data.header.length - data.read); | ||
357 | |||
358 | if (strlen(c)) | ||
359 | CurrentMaterial.Name = c; | ||
360 | |||
361 | data.read += data.header.length - data.read; | ||
362 | delete [] c; | ||
363 | } | ||
364 | break; | ||
365 | case C3DS_MATAMBIENT: | ||
366 | readColorChunk(file, &data, CurrentMaterial.Material.AmbientColor); | ||
367 | break; | ||
368 | case C3DS_MATDIFFUSE: | ||
369 | readColorChunk(file, &data, CurrentMaterial.Material.DiffuseColor); | ||
370 | break; | ||
371 | case C3DS_MATSPECULAR: | ||
372 | readColorChunk(file, &data, CurrentMaterial.Material.SpecularColor); | ||
373 | break; | ||
374 | case C3DS_MATSHININESS: | ||
375 | readPercentageChunk(file, &data, CurrentMaterial.Material.Shininess); | ||
376 | CurrentMaterial.Material.Shininess = (1.f-CurrentMaterial.Material.Shininess)*128.f; | ||
377 | break; | ||
378 | case C3DS_TRANSPARENCY: | ||
379 | { | ||
380 | f32 percentage; | ||
381 | readPercentageChunk(file, &data, percentage); | ||
382 | if (percentage>0.0f) | ||
383 | { | ||
384 | CurrentMaterial.Material.MaterialTypeParam=percentage; | ||
385 | CurrentMaterial.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | CurrentMaterial.Material.MaterialType=video::EMT_SOLID; | ||
390 | } | ||
391 | } | ||
392 | break; | ||
393 | case C3DS_WIRE: | ||
394 | CurrentMaterial.Material.Wireframe=true; | ||
395 | break; | ||
396 | case C3DS_TWO_SIDE: | ||
397 | CurrentMaterial.Material.BackfaceCulling=false; | ||
398 | break; | ||
399 | case C3DS_SHADING: | ||
400 | { | ||
401 | s16 flags; | ||
402 | file->read(&flags, 2); | ||
403 | #ifdef __BIG_ENDIAN__ | ||
404 | flags = os::Byteswap::byteswap(flags); | ||
405 | #endif | ||
406 | switch (flags) | ||
407 | { | ||
408 | case 0: | ||
409 | CurrentMaterial.Material.Wireframe=true; | ||
410 | break; | ||
411 | case 1: | ||
412 | CurrentMaterial.Material.Wireframe=false; | ||
413 | CurrentMaterial.Material.GouraudShading=false; | ||
414 | break; | ||
415 | case 2: | ||
416 | CurrentMaterial.Material.Wireframe=false; | ||
417 | CurrentMaterial.Material.GouraudShading=true; | ||
418 | break; | ||
419 | default: | ||
420 | // phong and metal missing | ||
421 | break; | ||
422 | } | ||
423 | data.read += data.header.length - data.read; | ||
424 | } | ||
425 | break; | ||
426 | case C3DS_MATTEXMAP: | ||
427 | case C3DS_MATSPECMAP: | ||
428 | case C3DS_MATOPACMAP: | ||
429 | case C3DS_MATREFLMAP: | ||
430 | case C3DS_MATBUMPMAP: | ||
431 | { | ||
432 | matSection=data.header.id; | ||
433 | // Should contain a percentage chunk, but does | ||
434 | // not always have it | ||
435 | s16 testval; | ||
436 | const long pos = file->getPos(); | ||
437 | file->read(&testval, 2); | ||
438 | #ifdef __BIG_ENDIAN__ | ||
439 | testval = os::Byteswap::byteswap(testval); | ||
440 | #endif | ||
441 | file->seek(pos, false); | ||
442 | if ((testval == C3DS_PERCENTAGE_I) || | ||
443 | (testval == C3DS_PERCENTAGE_F)) | ||
444 | switch (matSection) | ||
445 | { | ||
446 | case C3DS_MATTEXMAP: | ||
447 | readPercentageChunk(file, &data, CurrentMaterial.Strength[0]); | ||
448 | break; | ||
449 | case C3DS_MATSPECMAP: | ||
450 | readPercentageChunk(file, &data, CurrentMaterial.Strength[1]); | ||
451 | break; | ||
452 | case C3DS_MATOPACMAP: | ||
453 | readPercentageChunk(file, &data, CurrentMaterial.Strength[2]); | ||
454 | break; | ||
455 | case C3DS_MATBUMPMAP: | ||
456 | readPercentageChunk(file, &data, CurrentMaterial.Strength[4]); | ||
457 | break; | ||
458 | } | ||
459 | } | ||
460 | break; | ||
461 | case C3DS_MATMAPFILE: | ||
462 | { | ||
463 | // read texture file name | ||
464 | c8* c = new c8[data.header.length - data.read]; | ||
465 | file->read(c, data.header.length - data.read); | ||
466 | switch (matSection) | ||
467 | { | ||
468 | case C3DS_MATTEXMAP: | ||
469 | CurrentMaterial.Filename[0] = c; | ||
470 | break; | ||
471 | case C3DS_MATSPECMAP: | ||
472 | CurrentMaterial.Filename[1] = c; | ||
473 | break; | ||
474 | case C3DS_MATOPACMAP: | ||
475 | CurrentMaterial.Filename[2] = c; | ||
476 | break; | ||
477 | case C3DS_MATREFLMAP: | ||
478 | CurrentMaterial.Filename[3] = c; | ||
479 | break; | ||
480 | case C3DS_MATBUMPMAP: | ||
481 | CurrentMaterial.Filename[4] = c; | ||
482 | break; | ||
483 | } | ||
484 | data.read += data.header.length - data.read; | ||
485 | delete [] c; | ||
486 | } | ||
487 | break; | ||
488 | case C3DS_MAT_TEXTILING: | ||
489 | { | ||
490 | s16 flags; | ||
491 | file->read(&flags, 2); | ||
492 | #ifdef __BIG_ENDIAN__ | ||
493 | flags = os::Byteswap::byteswap(flags); | ||
494 | #endif | ||
495 | data.read += 2; | ||
496 | } | ||
497 | break; | ||
498 | case C3DS_MAT_USCALE: | ||
499 | case C3DS_MAT_VSCALE: | ||
500 | case C3DS_MAT_UOFFSET: | ||
501 | case C3DS_MAT_VOFFSET: | ||
502 | { | ||
503 | f32 value; | ||
504 | file->read(&value, 4); | ||
505 | #ifdef __BIG_ENDIAN__ | ||
506 | value = os::Byteswap::byteswap(value); | ||
507 | #endif | ||
508 | u32 i=0; | ||
509 | if (matSection != C3DS_MATTEXMAP) | ||
510 | i=1; | ||
511 | u32 j=0,k=0; | ||
512 | if (data.header.id == C3DS_MAT_VSCALE) | ||
513 | { | ||
514 | j=1; | ||
515 | k=1; | ||
516 | } | ||
517 | else if (data.header.id == C3DS_MAT_UOFFSET) | ||
518 | { | ||
519 | j=2; | ||
520 | k=0; | ||
521 | } | ||
522 | else if (data.header.id == C3DS_MAT_VOFFSET) | ||
523 | { | ||
524 | j=2; | ||
525 | k=1; | ||
526 | } | ||
527 | CurrentMaterial.Material.getTextureMatrix(i)(j,k)=value; | ||
528 | |||
529 | data.read += 4; | ||
530 | } | ||
531 | break; | ||
532 | default: | ||
533 | // ignore chunk | ||
534 | file->seek(data.header.length - data.read, true); | ||
535 | data.read += data.header.length - data.read; | ||
536 | } | ||
537 | |||
538 | parent->read += data.read; | ||
539 | } | ||
540 | |||
541 | Materials.push_back(CurrentMaterial); | ||
542 | CurrentMaterial.clear(); | ||
543 | |||
544 | return true; | ||
545 | } | ||
546 | |||
547 | |||
548 | |||
549 | bool C3DSMeshFileLoader::readTrackChunk(io::IReadFile* file, ChunkData& data, | ||
550 | IMeshBuffer* mb, const core::vector3df& pivot) | ||
551 | { | ||
552 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
553 | os::Printer::log("Load track chunk.", ELL_DEBUG); | ||
554 | #endif | ||
555 | u16 flags; | ||
556 | u32 flags2; | ||
557 | // Track flags | ||
558 | file->read(&flags, 2); | ||
559 | #ifdef __BIG_ENDIAN__ | ||
560 | flags = os::Byteswap::byteswap(flags); | ||
561 | #endif | ||
562 | file->read(&flags2, 4); | ||
563 | #ifdef __BIG_ENDIAN__ | ||
564 | flags2 = os::Byteswap::byteswap(flags2); | ||
565 | #endif | ||
566 | file->read(&flags2, 4); | ||
567 | #ifdef __BIG_ENDIAN__ | ||
568 | flags2 = os::Byteswap::byteswap(flags2); | ||
569 | #endif | ||
570 | // Num keys | ||
571 | file->read(&flags2, 4); | ||
572 | #ifdef __BIG_ENDIAN__ | ||
573 | flags2 = os::Byteswap::byteswap(flags2); | ||
574 | #endif | ||
575 | file->read(&flags2, 4); | ||
576 | #ifdef __BIG_ENDIAN__ | ||
577 | flags2 = os::Byteswap::byteswap(flags2); | ||
578 | #endif | ||
579 | // TCB flags | ||
580 | file->read(&flags, 2); | ||
581 | #ifdef __BIG_ENDIAN__ | ||
582 | flags = os::Byteswap::byteswap(flags); | ||
583 | #endif | ||
584 | data.read += 20; | ||
585 | |||
586 | f32 angle=0.0f; | ||
587 | if (data.header.id== C3DS_ROT_TRACK_TAG) | ||
588 | { | ||
589 | // Angle | ||
590 | file->read(&angle, sizeof(f32)); | ||
591 | #ifdef __BIG_ENDIAN__ | ||
592 | angle = os::Byteswap::byteswap(angle); | ||
593 | #endif | ||
594 | data.read += sizeof(f32); | ||
595 | } | ||
596 | core::vector3df vec; | ||
597 | file->read(&vec.X, sizeof(f32)); | ||
598 | file->read(&vec.Y, sizeof(f32)); | ||
599 | file->read(&vec.Z, sizeof(f32)); | ||
600 | #ifdef __BIG_ENDIAN__ | ||
601 | vec.X = os::Byteswap::byteswap(vec.X); | ||
602 | vec.Y = os::Byteswap::byteswap(vec.Y); | ||
603 | vec.Z = os::Byteswap::byteswap(vec.Z); | ||
604 | #endif | ||
605 | data.read += 12; | ||
606 | vec-=pivot; | ||
607 | |||
608 | // apply transformation to mesh buffer | ||
609 | if (false)//mb) | ||
610 | { | ||
611 | video::S3DVertex *vertices=(video::S3DVertex*)mb->getVertices(); | ||
612 | if (data.header.id==C3DS_POS_TRACK_TAG) | ||
613 | { | ||
614 | for (u32 i=0; i<mb->getVertexCount(); ++i) | ||
615 | vertices[i].Pos+=vec; | ||
616 | } | ||
617 | else if (data.header.id==C3DS_ROT_TRACK_TAG) | ||
618 | { | ||
619 | //TODO | ||
620 | } | ||
621 | else if (data.header.id==C3DS_SCL_TRACK_TAG) | ||
622 | { | ||
623 | //TODO | ||
624 | } | ||
625 | } | ||
626 | // skip further frames | ||
627 | file->seek(data.header.length - data.read, true); | ||
628 | data.read += data.header.length - data.read; | ||
629 | return true; | ||
630 | } | ||
631 | |||
632 | |||
633 | bool C3DSMeshFileLoader::readFrameChunk(io::IReadFile* file, ChunkData* parent) | ||
634 | { | ||
635 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
636 | os::Printer::log("Load frame chunk.", ELL_DEBUG); | ||
637 | #endif | ||
638 | ChunkData data; | ||
639 | |||
640 | //KF_HDR is always at the beginning | ||
641 | readChunkData(file, data); | ||
642 | if (data.header.id != C3DS_KF_HDR) | ||
643 | return false; | ||
644 | else | ||
645 | { | ||
646 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
647 | os::Printer::log("Load keyframe header.", ELL_DEBUG); | ||
648 | #endif | ||
649 | u16 version; | ||
650 | file->read(&version, 2); | ||
651 | #ifdef __BIG_ENDIAN__ | ||
652 | version = os::Byteswap::byteswap(version); | ||
653 | #endif | ||
654 | core::stringc name; | ||
655 | readString(file, data, name); | ||
656 | u32 flags; | ||
657 | file->read(&flags, 4); | ||
658 | #ifdef __BIG_ENDIAN__ | ||
659 | flags = os::Byteswap::byteswap(flags); | ||
660 | #endif | ||
661 | |||
662 | data.read += 4; | ||
663 | parent->read += data.read; | ||
664 | } | ||
665 | data.read=0; | ||
666 | |||
667 | IMeshBuffer* mb=0; | ||
668 | core::vector3df pivot,bboxCenter; | ||
669 | while(parent->read < parent->header.length) | ||
670 | { | ||
671 | readChunkData(file, data); | ||
672 | |||
673 | switch(data.header.id) | ||
674 | { | ||
675 | case C3DS_OBJECT_TAG: | ||
676 | { | ||
677 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
678 | os::Printer::log("Load object tag.", ELL_DEBUG); | ||
679 | #endif | ||
680 | mb=0; | ||
681 | pivot.set(0.0f, 0.0f, 0.0f); | ||
682 | } | ||
683 | break; | ||
684 | case C3DS_KF_SEG: | ||
685 | { | ||
686 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
687 | os::Printer::log("Load keyframe segment.", ELL_DEBUG); | ||
688 | #endif | ||
689 | u32 flags; | ||
690 | file->read(&flags, 4); | ||
691 | #ifdef __BIG_ENDIAN__ | ||
692 | flags = os::Byteswap::byteswap(flags); | ||
693 | #endif | ||
694 | file->read(&flags, 4); | ||
695 | #ifdef __BIG_ENDIAN__ | ||
696 | flags = os::Byteswap::byteswap(flags); | ||
697 | #endif | ||
698 | data.read += 8; | ||
699 | } | ||
700 | break; | ||
701 | case C3DS_KF_NODE_HDR: | ||
702 | { | ||
703 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
704 | os::Printer::log("Load keyframe node header.", ELL_DEBUG); | ||
705 | #endif | ||
706 | s16 flags; | ||
707 | c8* c = new c8[data.header.length - data.read-6]; | ||
708 | file->read(c, data.header.length - data.read-6); | ||
709 | |||
710 | // search mesh buffer to apply these transformations to | ||
711 | for (u32 i=0; i<MeshBufferNames.size(); ++i) | ||
712 | { | ||
713 | if (MeshBufferNames[i]==c) | ||
714 | { | ||
715 | mb=Mesh->getMeshBuffer(i); | ||
716 | break; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | file->read(&flags, 2); | ||
721 | #ifdef __BIG_ENDIAN__ | ||
722 | flags = os::Byteswap::byteswap(flags); | ||
723 | #endif | ||
724 | file->read(&flags, 2); | ||
725 | #ifdef __BIG_ENDIAN__ | ||
726 | flags = os::Byteswap::byteswap(flags); | ||
727 | #endif | ||
728 | file->read(&flags, 2); | ||
729 | #ifdef __BIG_ENDIAN__ | ||
730 | flags = os::Byteswap::byteswap(flags); | ||
731 | #endif | ||
732 | data.read += data.header.length - data.read; | ||
733 | delete [] c; | ||
734 | } | ||
735 | break; | ||
736 | case C3DS_KF_CURTIME: | ||
737 | { | ||
738 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
739 | os::Printer::log("Load keyframe current time.", ELL_DEBUG); | ||
740 | #endif | ||
741 | u32 flags; | ||
742 | file->read(&flags, 4); | ||
743 | #ifdef __BIG_ENDIAN__ | ||
744 | flags = os::Byteswap::byteswap(flags); | ||
745 | #endif | ||
746 | data.read += 4; | ||
747 | } | ||
748 | break; | ||
749 | case C3DS_NODE_ID: | ||
750 | { | ||
751 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
752 | os::Printer::log("Load node ID.", ELL_DEBUG); | ||
753 | #endif | ||
754 | u16 flags; | ||
755 | file->read(&flags, 2); | ||
756 | #ifdef __BIG_ENDIAN__ | ||
757 | flags = os::Byteswap::byteswap(flags); | ||
758 | #endif | ||
759 | data.read += 2; | ||
760 | } | ||
761 | break; | ||
762 | case C3DS_PIVOTPOINT: | ||
763 | { | ||
764 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
765 | os::Printer::log("Load pivot point.", ELL_DEBUG); | ||
766 | #endif | ||
767 | file->read(&pivot.X, sizeof(f32)); | ||
768 | file->read(&pivot.Y, sizeof(f32)); | ||
769 | file->read(&pivot.Z, sizeof(f32)); | ||
770 | #ifdef __BIG_ENDIAN__ | ||
771 | pivot.X = os::Byteswap::byteswap(pivot.X); | ||
772 | pivot.Y = os::Byteswap::byteswap(pivot.Y); | ||
773 | pivot.Z = os::Byteswap::byteswap(pivot.Z); | ||
774 | #endif | ||
775 | data.read += 12; | ||
776 | } | ||
777 | break; | ||
778 | case C3DS_BOUNDBOX: | ||
779 | { | ||
780 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
781 | os::Printer::log("Load bounding box.", ELL_DEBUG); | ||
782 | #endif | ||
783 | core::aabbox3df bbox; | ||
784 | // abuse bboxCenter as temporary variable | ||
785 | file->read(&bboxCenter.X, sizeof(f32)); | ||
786 | file->read(&bboxCenter.Y, sizeof(f32)); | ||
787 | file->read(&bboxCenter.Z, sizeof(f32)); | ||
788 | #ifdef __BIG_ENDIAN__ | ||
789 | bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); | ||
790 | bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); | ||
791 | bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); | ||
792 | #endif | ||
793 | bbox.reset(bboxCenter); | ||
794 | file->read(&bboxCenter.X, sizeof(f32)); | ||
795 | file->read(&bboxCenter.Y, sizeof(f32)); | ||
796 | file->read(&bboxCenter.Z, sizeof(f32)); | ||
797 | #ifdef __BIG_ENDIAN__ | ||
798 | bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); | ||
799 | bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); | ||
800 | bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); | ||
801 | #endif | ||
802 | bbox.addInternalPoint(bboxCenter); | ||
803 | bboxCenter=bbox.getCenter(); | ||
804 | data.read += 24; | ||
805 | } | ||
806 | break; | ||
807 | case C3DS_MORPH_SMOOTH: | ||
808 | { | ||
809 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
810 | os::Printer::log("Load morph smooth.", ELL_DEBUG); | ||
811 | #endif | ||
812 | f32 flag; | ||
813 | file->read(&flag, 4); | ||
814 | #ifdef __BIG_ENDIAN__ | ||
815 | flag = os::Byteswap::byteswap(flag); | ||
816 | #endif | ||
817 | data.read += 4; | ||
818 | } | ||
819 | break; | ||
820 | case C3DS_POS_TRACK_TAG: | ||
821 | case C3DS_ROT_TRACK_TAG: | ||
822 | case C3DS_SCL_TRACK_TAG: | ||
823 | readTrackChunk(file, data, mb, bboxCenter-pivot); | ||
824 | break; | ||
825 | default: | ||
826 | // ignore chunk | ||
827 | file->seek(data.header.length - data.read, true); | ||
828 | data.read += data.header.length - data.read; | ||
829 | } | ||
830 | |||
831 | parent->read += data.read; | ||
832 | data.read=0; | ||
833 | } | ||
834 | |||
835 | return true; | ||
836 | } | ||
837 | |||
838 | |||
839 | bool C3DSMeshFileLoader::readChunk(io::IReadFile* file, ChunkData* parent) | ||
840 | { | ||
841 | while(parent->read < parent->header.length) | ||
842 | { | ||
843 | ChunkData data; | ||
844 | readChunkData(file, data); | ||
845 | |||
846 | switch(data.header.id) | ||
847 | { | ||
848 | case C3DS_VERSION: | ||
849 | { | ||
850 | u16 version; | ||
851 | file->read(&version, sizeof(u16)); | ||
852 | #ifdef __BIG_ENDIAN__ | ||
853 | version = os::Byteswap::byteswap(version); | ||
854 | #endif | ||
855 | file->seek(data.header.length - data.read - 2, true); | ||
856 | data.read += data.header.length - data.read; | ||
857 | if (version != 0x03) | ||
858 | os::Printer::log("3ds file version is other than 3.", ELL_ERROR); | ||
859 | } | ||
860 | break; | ||
861 | case C3DS_EDIT_MATERIAL: | ||
862 | readMaterialChunk(file, &data); | ||
863 | break; | ||
864 | case C3DS_KEYF3DS: | ||
865 | readFrameChunk(file, &data); | ||
866 | break; | ||
867 | case C3DS_EDIT3DS: | ||
868 | break; | ||
869 | case C3DS_MESHVERSION: | ||
870 | case 0x01: | ||
871 | { | ||
872 | u32 version; | ||
873 | file->read(&version, sizeof(u32)); | ||
874 | #ifdef __BIG_ENDIAN__ | ||
875 | version = os::Byteswap::byteswap(version); | ||
876 | #endif | ||
877 | data.read += sizeof(u32); | ||
878 | } | ||
879 | break; | ||
880 | case C3DS_EDIT_OBJECT: | ||
881 | { | ||
882 | core::stringc name; | ||
883 | readString(file, data, name); | ||
884 | readObjectChunk(file, &data); | ||
885 | composeObject(file, name); | ||
886 | } | ||
887 | break; | ||
888 | |||
889 | default: | ||
890 | // ignore chunk | ||
891 | file->seek(data.header.length - data.read, true); | ||
892 | data.read += data.header.length - data.read; | ||
893 | } | ||
894 | |||
895 | parent->read += data.read; | ||
896 | } | ||
897 | |||
898 | return true; | ||
899 | } | ||
900 | |||
901 | |||
902 | bool C3DSMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData* parent) | ||
903 | { | ||
904 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
905 | os::Printer::log("Load object chunk.", ELL_DEBUG); | ||
906 | #endif | ||
907 | while(parent->read < parent->header.length) | ||
908 | { | ||
909 | ChunkData data; | ||
910 | readChunkData(file, data); | ||
911 | |||
912 | switch(data.header.id) | ||
913 | { | ||
914 | case C3DS_OBJTRIMESH: | ||
915 | readObjectChunk(file, &data); | ||
916 | break; | ||
917 | |||
918 | case C3DS_TRIVERT: | ||
919 | readVertices(file, data); | ||
920 | break; | ||
921 | |||
922 | case C3DS_POINTFLAGARRAY: | ||
923 | { | ||
924 | u16 numVertex, flags; | ||
925 | file->read(&numVertex, sizeof(u16)); | ||
926 | #ifdef __BIG_ENDIAN__ | ||
927 | numVertex= os::Byteswap::byteswap(numVertex); | ||
928 | #endif | ||
929 | for (u16 i=0; i<numVertex; ++i) | ||
930 | { | ||
931 | file->read(&flags, sizeof(u16)); | ||
932 | #ifdef __BIG_ENDIAN__ | ||
933 | flags = os::Byteswap::byteswap(flags); | ||
934 | #endif | ||
935 | } | ||
936 | data.read += (numVertex+1)*sizeof(u16); | ||
937 | } | ||
938 | break; | ||
939 | |||
940 | case C3DS_TRIFACE: | ||
941 | readIndices(file, data); | ||
942 | readObjectChunk(file, &data); // read smooth and material groups | ||
943 | break; | ||
944 | |||
945 | case C3DS_TRIFACEMAT: | ||
946 | readMaterialGroup(file, data); | ||
947 | break; | ||
948 | |||
949 | case C3DS_TRIUV: // getting texture coordinates | ||
950 | readTextureCoords(file, data); | ||
951 | break; | ||
952 | |||
953 | case C3DS_TRIMATRIX: | ||
954 | { | ||
955 | f32 mat[4][3]; | ||
956 | file->read(&mat, 12*sizeof(f32)); | ||
957 | TransformationMatrix.makeIdentity(); | ||
958 | for (int i=0; i<4; ++i) | ||
959 | { | ||
960 | for (int j=0; j<3; ++j) | ||
961 | { | ||
962 | #ifdef __BIG_ENDIAN__ | ||
963 | TransformationMatrix(i,j)=os::Byteswap::byteswap(mat[i][j]); | ||
964 | #else | ||
965 | TransformationMatrix(i,j)=mat[i][j]; | ||
966 | #endif | ||
967 | } | ||
968 | } | ||
969 | data.read += 12*sizeof(f32); | ||
970 | } | ||
971 | break; | ||
972 | case C3DS_MESHCOLOR: | ||
973 | { | ||
974 | u8 flag; | ||
975 | file->read(&flag, sizeof(u8)); | ||
976 | ++data.read; | ||
977 | } | ||
978 | break; | ||
979 | case C3DS_TRISMOOTH: // TODO | ||
980 | { | ||
981 | SmoothingGroups = new u32[CountFaces]; | ||
982 | file->read(SmoothingGroups, CountFaces*sizeof(u32)); | ||
983 | #ifdef __BIG_ENDIAN__ | ||
984 | for (u16 i=0; i<CountFaces; ++i) | ||
985 | SmoothingGroups[i] = os::Byteswap::byteswap(SmoothingGroups[i]); | ||
986 | #endif | ||
987 | data.read += CountFaces*sizeof(u32); | ||
988 | } | ||
989 | break; | ||
990 | |||
991 | default: | ||
992 | // ignore chunk | ||
993 | file->seek(data.header.length - data.read, true); | ||
994 | data.read += data.header.length - data.read; | ||
995 | } | ||
996 | |||
997 | parent->read += data.read; | ||
998 | } | ||
999 | |||
1000 | return true; | ||
1001 | } | ||
1002 | |||
1003 | |||
1004 | void C3DSMeshFileLoader::composeObject(io::IReadFile* file, const core::stringc& name) | ||
1005 | { | ||
1006 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
1007 | os::Printer::log("Compose object.", ELL_DEBUG); | ||
1008 | #endif | ||
1009 | if (Mesh->getMeshBufferCount() != Materials.size()) | ||
1010 | loadMaterials(file); | ||
1011 | |||
1012 | if (MaterialGroups.empty()) | ||
1013 | { | ||
1014 | // no material group, so add all | ||
1015 | SMaterialGroup group; | ||
1016 | group.faceCount = CountFaces; | ||
1017 | group.faces = new u16[group.faceCount]; | ||
1018 | for (u32 i=0; i<group.faceCount; ++i) | ||
1019 | group.faces[i] = i; | ||
1020 | MaterialGroups.push_back(group); | ||
1021 | |||
1022 | // if we've got no material, add one without a texture | ||
1023 | if (Materials.empty()) | ||
1024 | { | ||
1025 | SCurrentMaterial m; | ||
1026 | Materials.push_back(m); | ||
1027 | SMeshBuffer* mb = new scene::SMeshBuffer(); | ||
1028 | Mesh->addMeshBuffer(mb); | ||
1029 | mb->getMaterial() = Materials[0].Material; | ||
1030 | mb->drop(); | ||
1031 | // add an empty mesh buffer name | ||
1032 | MeshBufferNames.push_back(""); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | for (u32 i=0; i<MaterialGroups.size(); ++i) | ||
1037 | { | ||
1038 | SMeshBuffer* mb = 0; | ||
1039 | video::SMaterial* mat=0; | ||
1040 | u32 mbPos; | ||
1041 | // -3 because we add three vertices at once | ||
1042 | u32 maxPrimitives = core::min_(SceneManager->getVideoDriver()->getMaximalPrimitiveCount(), (u32)((1<<16)-1))-3; // currently hardcoded s16 max value for index pointers | ||
1043 | |||
1044 | // find mesh buffer for this group | ||
1045 | for (mbPos=0; mbPos<Materials.size(); ++mbPos) | ||
1046 | { | ||
1047 | if (MaterialGroups[i].MaterialName == Materials[mbPos].Name) | ||
1048 | { | ||
1049 | mb = (SMeshBuffer*)Mesh->getMeshBuffer(mbPos); | ||
1050 | mat=&Materials[mbPos].Material; | ||
1051 | MeshBufferNames[mbPos]=name; | ||
1052 | break; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | if (mb != 0) | ||
1057 | { | ||
1058 | // add geometry to the buffer. | ||
1059 | |||
1060 | video::S3DVertex vtx; | ||
1061 | core::vector3df vec; | ||
1062 | vtx.Color=mat->DiffuseColor; | ||
1063 | if (mat->MaterialType==video::EMT_TRANSPARENT_VERTEX_ALPHA) | ||
1064 | { | ||
1065 | vtx.Color.setAlpha((int)(255.0f*mat->MaterialTypeParam)); | ||
1066 | } | ||
1067 | vtx.Normal.set(0,0,0); | ||
1068 | |||
1069 | for (s32 f=0; f<MaterialGroups[i].faceCount; ++f) | ||
1070 | { | ||
1071 | u32 vtxCount = mb->Vertices.size(); | ||
1072 | if (vtxCount>maxPrimitives) | ||
1073 | { | ||
1074 | IMeshBuffer* tmp = mb; | ||
1075 | mb = new SMeshBuffer(); | ||
1076 | Mesh->addMeshBuffer(mb); | ||
1077 | mb->drop(); | ||
1078 | Mesh->MeshBuffers[mbPos] = Mesh->MeshBuffers.getLast(); | ||
1079 | Mesh->MeshBuffers[Mesh->MeshBuffers.size()-1] = tmp; | ||
1080 | mb->getMaterial() = tmp->getMaterial(); | ||
1081 | vtxCount=0; | ||
1082 | } | ||
1083 | |||
1084 | for (s32 v=0; v<3; ++v) | ||
1085 | { | ||
1086 | s32 idx = Indices[MaterialGroups[i].faces[f]*4 +v]; | ||
1087 | |||
1088 | if (CountVertices > idx) | ||
1089 | { | ||
1090 | vtx.Pos.X = Vertices[idx*3 + 0]; | ||
1091 | vtx.Pos.Z = Vertices[idx*3 + 1]; | ||
1092 | vtx.Pos.Y = Vertices[idx*3 + 2]; | ||
1093 | // TransformationMatrix.transformVect(vtx.Pos); | ||
1094 | } | ||
1095 | |||
1096 | if (CountTCoords > idx) | ||
1097 | { | ||
1098 | vtx.TCoords.X = TCoords[idx*2 + 0]; | ||
1099 | vtx.TCoords.Y = 1.0f -TCoords[idx*2 + 1]; | ||
1100 | } | ||
1101 | |||
1102 | mb->Vertices.push_back(vtx); | ||
1103 | } | ||
1104 | |||
1105 | // compute normal | ||
1106 | core::plane3d<f32> pl(mb->Vertices[vtxCount].Pos, mb->Vertices[vtxCount+2].Pos, | ||
1107 | mb->Vertices[vtxCount+1].Pos); | ||
1108 | |||
1109 | mb->Vertices[vtxCount].Normal = pl.Normal; | ||
1110 | mb->Vertices[vtxCount+1].Normal = pl.Normal; | ||
1111 | mb->Vertices[vtxCount+2].Normal = pl.Normal; | ||
1112 | |||
1113 | // add indices | ||
1114 | |||
1115 | mb->Indices.push_back(vtxCount); | ||
1116 | mb->Indices.push_back(vtxCount+2); | ||
1117 | mb->Indices.push_back(vtxCount+1); | ||
1118 | } | ||
1119 | } | ||
1120 | else | ||
1121 | os::Printer::log("Found no matching material for Group in 3ds file.", ELL_WARNING); | ||
1122 | } | ||
1123 | |||
1124 | cleanUp(); | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) | ||
1129 | { | ||
1130 | // create a mesh buffer for every material | ||
1131 | core::stringc modelFilename = file->getFileName(); | ||
1132 | |||
1133 | if (Materials.empty()) | ||
1134 | os::Printer::log("No materials found in 3ds file.", ELL_INFORMATION); | ||
1135 | |||
1136 | MeshBufferNames.reallocate(Materials.size()); | ||
1137 | for (u32 i=0; i<Materials.size(); ++i) | ||
1138 | { | ||
1139 | MeshBufferNames.push_back(""); | ||
1140 | SMeshBuffer* m = new scene::SMeshBuffer(); | ||
1141 | Mesh->addMeshBuffer(m); | ||
1142 | |||
1143 | m->getMaterial() = Materials[i].Material; | ||
1144 | if (Materials[i].Filename[0].size()) | ||
1145 | { | ||
1146 | video::ITexture* texture = 0; | ||
1147 | if (FileSystem->existFile(Materials[i].Filename[0])) | ||
1148 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0]); | ||
1149 | if (!texture) | ||
1150 | { | ||
1151 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[0]); | ||
1152 | if (FileSystem->existFile(fname)) | ||
1153 | texture = SceneManager->getVideoDriver()->getTexture(fname); | ||
1154 | } | ||
1155 | if (!texture) | ||
1156 | os::Printer::log("Could not load a texture for entry in 3ds file", | ||
1157 | Materials[i].Filename[0].c_str(), ELL_WARNING); | ||
1158 | else | ||
1159 | m->getMaterial().setTexture(0, texture); | ||
1160 | } | ||
1161 | |||
1162 | if (Materials[i].Filename[2].size()) | ||
1163 | { | ||
1164 | video::ITexture* texture = 0; | ||
1165 | if (FileSystem->existFile(Materials[i].Filename[2])) | ||
1166 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2]); | ||
1167 | if (!texture) | ||
1168 | { | ||
1169 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[2]); | ||
1170 | if (FileSystem->existFile(fname)) | ||
1171 | texture = SceneManager->getVideoDriver()->getTexture(fname); | ||
1172 | } | ||
1173 | if (!texture) | ||
1174 | { | ||
1175 | os::Printer::log("Could not load a texture for entry in 3ds file", | ||
1176 | Materials[i].Filename[2].c_str(), ELL_WARNING); | ||
1177 | } | ||
1178 | else | ||
1179 | { | ||
1180 | m->getMaterial().setTexture(0, texture); | ||
1181 | m->getMaterial().MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | if (Materials[i].Filename[3].size()) | ||
1186 | { | ||
1187 | video::ITexture* texture = 0; | ||
1188 | if (FileSystem->existFile(Materials[i].Filename[3])) | ||
1189 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3]); | ||
1190 | if (!texture) | ||
1191 | { | ||
1192 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[3]); | ||
1193 | if (FileSystem->existFile(fname)) | ||
1194 | texture = SceneManager->getVideoDriver()->getTexture(fname); | ||
1195 | } | ||
1196 | |||
1197 | if (!texture) | ||
1198 | { | ||
1199 | os::Printer::log("Could not load a texture for entry in 3ds file", | ||
1200 | Materials[i].Filename[3].c_str(), ELL_WARNING); | ||
1201 | } | ||
1202 | else | ||
1203 | { | ||
1204 | m->getMaterial().setTexture(1, m->getMaterial().getTexture(0)); | ||
1205 | m->getMaterial().setTexture(0, texture); | ||
1206 | m->getMaterial().MaterialType = video::EMT_REFLECTION_2_LAYER; | ||
1207 | } | ||
1208 | } | ||
1209 | |||
1210 | if (Materials[i].Filename[4].size()) | ||
1211 | { | ||
1212 | video::ITexture* texture = 0; | ||
1213 | if (FileSystem->existFile(Materials[i].Filename[4])) | ||
1214 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4]); | ||
1215 | if (!texture) | ||
1216 | { | ||
1217 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[4]); | ||
1218 | if (FileSystem->existFile(fname)) | ||
1219 | texture = SceneManager->getVideoDriver()->getTexture(fname); | ||
1220 | } | ||
1221 | if (!texture) | ||
1222 | os::Printer::log("Could not load a texture for entry in 3ds file", | ||
1223 | Materials[i].Filename[4].c_str(), ELL_WARNING); | ||
1224 | else | ||
1225 | { | ||
1226 | m->getMaterial().setTexture(1, texture); | ||
1227 | SceneManager->getVideoDriver()->makeNormalMapTexture(texture, Materials[i].Strength[4]*10.f); | ||
1228 | m->getMaterial().MaterialType=video::EMT_PARALLAX_MAP_SOLID; | ||
1229 | m->getMaterial().MaterialTypeParam=.035f; | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | m->drop(); | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | |||
1238 | void C3DSMeshFileLoader::cleanUp() | ||
1239 | { | ||
1240 | delete [] Vertices; | ||
1241 | CountVertices = 0; | ||
1242 | Vertices = 0; | ||
1243 | delete [] Indices; | ||
1244 | Indices = 0; | ||
1245 | CountFaces = 0; | ||
1246 | delete [] SmoothingGroups; | ||
1247 | SmoothingGroups = 0; | ||
1248 | delete [] TCoords; | ||
1249 | TCoords = 0; | ||
1250 | CountTCoords = 0; | ||
1251 | |||
1252 | MaterialGroups.clear(); | ||
1253 | } | ||
1254 | |||
1255 | |||
1256 | void C3DSMeshFileLoader::readTextureCoords(io::IReadFile* file, ChunkData& data) | ||
1257 | { | ||
1258 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
1259 | os::Printer::log("Load texture coords.", ELL_DEBUG); | ||
1260 | #endif | ||
1261 | file->read(&CountTCoords, sizeof(CountTCoords)); | ||
1262 | #ifdef __BIG_ENDIAN__ | ||
1263 | CountTCoords = os::Byteswap::byteswap(CountTCoords); | ||
1264 | #endif | ||
1265 | data.read += sizeof(CountTCoords); | ||
1266 | |||
1267 | s32 tcoordsBufferByteSize = CountTCoords * sizeof(f32) * 2; | ||
1268 | |||
1269 | if (data.header.length - data.read != tcoordsBufferByteSize) | ||
1270 | { | ||
1271 | os::Printer::log("Invalid size of tcoords found in 3ds file.", ELL_WARNING); | ||
1272 | return; | ||
1273 | } | ||
1274 | |||
1275 | TCoords = new f32[CountTCoords * 3]; | ||
1276 | file->read(TCoords, tcoordsBufferByteSize); | ||
1277 | #ifdef __BIG_ENDIAN__ | ||
1278 | for (int i=0;i<CountTCoords*2;i++) TCoords[i] = os::Byteswap::byteswap(TCoords[i]); | ||
1279 | #endif | ||
1280 | data.read += tcoordsBufferByteSize; | ||
1281 | } | ||
1282 | |||
1283 | |||
1284 | void C3DSMeshFileLoader::readMaterialGroup(io::IReadFile* file, ChunkData& data) | ||
1285 | { | ||
1286 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
1287 | os::Printer::log("Load material group.", ELL_DEBUG); | ||
1288 | #endif | ||
1289 | SMaterialGroup group; | ||
1290 | |||
1291 | readString(file, data, group.MaterialName); | ||
1292 | |||
1293 | file->read(&group.faceCount, sizeof(group.faceCount)); | ||
1294 | #ifdef __BIG_ENDIAN__ | ||
1295 | group.faceCount = os::Byteswap::byteswap(group.faceCount); | ||
1296 | #endif | ||
1297 | data.read += sizeof(group.faceCount); | ||
1298 | |||
1299 | // read faces | ||
1300 | group.faces = new u16[group.faceCount]; | ||
1301 | file->read(group.faces, sizeof(u16) * group.faceCount); | ||
1302 | #ifdef __BIG_ENDIAN__ | ||
1303 | for (u32 i=0;i<group.faceCount;++i) | ||
1304 | group.faces[i] = os::Byteswap::byteswap(group.faces[i]); | ||
1305 | #endif | ||
1306 | data.read += sizeof(u16) * group.faceCount; | ||
1307 | |||
1308 | MaterialGroups.push_back(group); | ||
1309 | } | ||
1310 | |||
1311 | |||
1312 | void C3DSMeshFileLoader::readIndices(io::IReadFile* file, ChunkData& data) | ||
1313 | { | ||
1314 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
1315 | os::Printer::log("Load indices.", ELL_DEBUG); | ||
1316 | #endif | ||
1317 | file->read(&CountFaces, sizeof(CountFaces)); | ||
1318 | #ifdef __BIG_ENDIAN__ | ||
1319 | CountFaces = os::Byteswap::byteswap(CountFaces); | ||
1320 | #endif | ||
1321 | data.read += sizeof(CountFaces); | ||
1322 | |||
1323 | s32 indexBufferByteSize = CountFaces * sizeof(u16) * 4; | ||
1324 | |||
1325 | // Indices are u16s. | ||
1326 | // After every 3 Indices in the array, there follows an edge flag. | ||
1327 | Indices = new u16[CountFaces * 4]; | ||
1328 | file->read(Indices, indexBufferByteSize); | ||
1329 | #ifdef __BIG_ENDIAN__ | ||
1330 | for (int i=0;i<CountFaces*4;++i) | ||
1331 | Indices[i] = os::Byteswap::byteswap(Indices[i]); | ||
1332 | #endif | ||
1333 | data.read += indexBufferByteSize; | ||
1334 | } | ||
1335 | |||
1336 | |||
1337 | void C3DSMeshFileLoader::readVertices(io::IReadFile* file, ChunkData& data) | ||
1338 | { | ||
1339 | #ifdef _IRR_DEBUG_3DS_LOADER_ | ||
1340 | os::Printer::log("Load vertices.", ELL_DEBUG); | ||
1341 | #endif | ||
1342 | file->read(&CountVertices, sizeof(CountVertices)); | ||
1343 | #ifdef __BIG_ENDIAN__ | ||
1344 | CountVertices = os::Byteswap::byteswap(CountVertices); | ||
1345 | #endif | ||
1346 | data.read += sizeof(CountVertices); | ||
1347 | |||
1348 | const s32 vertexBufferByteSize = CountVertices * sizeof(f32) * 3; | ||
1349 | |||
1350 | if (data.header.length - data.read != vertexBufferByteSize) | ||
1351 | { | ||
1352 | os::Printer::log("Invalid size of vertices found in 3ds file", core::stringc(CountVertices), ELL_ERROR); | ||
1353 | return; | ||
1354 | } | ||
1355 | |||
1356 | Vertices = new f32[CountVertices * 3]; | ||
1357 | file->read(Vertices, vertexBufferByteSize); | ||
1358 | #ifdef __BIG_ENDIAN__ | ||
1359 | for (int i=0;i<CountVertices*3;i++) | ||
1360 | Vertices[i] = os::Byteswap::byteswap(Vertices[i]); | ||
1361 | #endif | ||
1362 | data.read += vertexBufferByteSize; | ||
1363 | } | ||
1364 | |||
1365 | |||
1366 | void C3DSMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) | ||
1367 | { | ||
1368 | file->read(&data.header, sizeof(ChunkHeader)); | ||
1369 | #ifdef __BIG_ENDIAN__ | ||
1370 | data.header.id = os::Byteswap::byteswap(data.header.id); | ||
1371 | data.header.length = os::Byteswap::byteswap(data.header.length); | ||
1372 | #endif | ||
1373 | data.read += sizeof(ChunkHeader); | ||
1374 | } | ||
1375 | |||
1376 | |||
1377 | void C3DSMeshFileLoader::readString(io::IReadFile* file, ChunkData& data, core::stringc& out) | ||
1378 | { | ||
1379 | c8 c = 1; | ||
1380 | out = ""; | ||
1381 | |||
1382 | while (c) | ||
1383 | { | ||
1384 | file->read(&c, sizeof(c8)); | ||
1385 | if (c) | ||
1386 | out.append(c); | ||
1387 | } | ||
1388 | data.read+=out.size()+1; | ||
1389 | } | ||
1390 | |||
1391 | |||
1392 | } // end namespace scene | ||
1393 | } // end namespace irr | ||
1394 | |||
1395 | #endif // _IRR_COMPILE_WITH_3DS_LOADER_ | ||
1396 | |||