diff options
author | David Walter Seikel | 2013-01-13 17:24:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 17:24:39 +1000 |
commit | 393b5cd1dc438872af89d334ef6e5fcc59f27d47 (patch) | |
tree | 6a14521219942a08a1b95cb2f5a923a9edd60f63 /libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp | |
parent | Add a note about rasters suggested start up code. (diff) | |
download | SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.zip SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.tar.gz SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.tar.bz2 SledjHamr-393b5cd1dc438872af89d334ef6e5fcc59f27d47.tar.xz |
Added Irrlicht 1.8, but without all the Windows binaries.
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp | 818 |
1 files changed, 818 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp new file mode 100644 index 0000000..9a88d49 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp | |||
@@ -0,0 +1,818 @@ | |||
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_MS3D_LOADER_ | ||
7 | |||
8 | #include "IReadFile.h" | ||
9 | #include "os.h" | ||
10 | #include "CMS3DMeshFileLoader.h" | ||
11 | #include "CSkinnedMesh.h" | ||
12 | |||
13 | |||
14 | namespace irr | ||
15 | { | ||
16 | namespace scene | ||
17 | { | ||
18 | |||
19 | #ifdef _DEBUG | ||
20 | #define _IRR_DEBUG_MS3D_LOADER_ | ||
21 | #endif | ||
22 | |||
23 | // byte-align structures | ||
24 | #include "irrpack.h" | ||
25 | |||
26 | namespace { | ||
27 | // File header | ||
28 | struct MS3DHeader | ||
29 | { | ||
30 | char ID[10]; | ||
31 | int Version; | ||
32 | } PACK_STRUCT; | ||
33 | |||
34 | // Vertex information | ||
35 | struct MS3DVertex | ||
36 | { | ||
37 | u8 Flags; | ||
38 | float Vertex[3]; | ||
39 | char BoneID; | ||
40 | u8 RefCount; | ||
41 | } PACK_STRUCT; | ||
42 | |||
43 | // Triangle information | ||
44 | struct MS3DTriangle | ||
45 | { | ||
46 | u16 Flags; | ||
47 | u16 VertexIndices[3]; | ||
48 | float VertexNormals[3][3]; | ||
49 | float S[3], T[3]; | ||
50 | u8 SmoothingGroup; | ||
51 | u8 GroupIndex; | ||
52 | } PACK_STRUCT; | ||
53 | |||
54 | // Material information | ||
55 | struct MS3DMaterial | ||
56 | { | ||
57 | char Name[32]; | ||
58 | float Ambient[4]; | ||
59 | float Diffuse[4]; | ||
60 | float Specular[4]; | ||
61 | float Emissive[4]; | ||
62 | float Shininess; // 0.0f - 128.0f | ||
63 | float Transparency; // 0.0f - 1.0f | ||
64 | u8 Mode; // 0, 1, 2 is unused now | ||
65 | char Texture[128]; | ||
66 | char Alphamap[128]; | ||
67 | } PACK_STRUCT; | ||
68 | |||
69 | // Joint information | ||
70 | struct MS3DJoint | ||
71 | { | ||
72 | u8 Flags; | ||
73 | char Name[32]; | ||
74 | char ParentName[32]; | ||
75 | float Rotation[3]; | ||
76 | float Translation[3]; | ||
77 | u16 NumRotationKeyframes; | ||
78 | u16 NumTranslationKeyframes; | ||
79 | } PACK_STRUCT; | ||
80 | |||
81 | // Keyframe data | ||
82 | struct MS3DKeyframe | ||
83 | { | ||
84 | float Time; | ||
85 | float Parameter[3]; | ||
86 | } PACK_STRUCT; | ||
87 | |||
88 | // vertex weights in 1.8.x | ||
89 | struct MS3DVertexWeights | ||
90 | { | ||
91 | char boneIds[3]; | ||
92 | u8 weights[3]; | ||
93 | } PACK_STRUCT; | ||
94 | |||
95 | } // end namespace | ||
96 | |||
97 | // Default alignment | ||
98 | #include "irrunpack.h" | ||
99 | |||
100 | struct SGroup | ||
101 | { | ||
102 | core::stringc Name; | ||
103 | core::array<u16> VertexIds; | ||
104 | u16 MaterialIdx; | ||
105 | }; | ||
106 | |||
107 | //! Constructor | ||
108 | CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) | ||
109 | : Driver(driver), AnimatedMesh(0) | ||
110 | { | ||
111 | #ifdef _DEBUG | ||
112 | setDebugName("CMS3DMeshFileLoader"); | ||
113 | #endif | ||
114 | } | ||
115 | |||
116 | |||
117 | //! returns true if the file maybe is able to be loaded by this class | ||
118 | //! based on the file extension (e.g. ".bsp") | ||
119 | bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | ||
120 | { | ||
121 | return core::hasFileExtension ( filename, "ms3d" ); | ||
122 | } | ||
123 | |||
124 | |||
125 | //! creates/loads an animated mesh from the file. | ||
126 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | ||
127 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | ||
128 | //! See IReferenceCounted::drop() for more information. | ||
129 | IAnimatedMesh* CMS3DMeshFileLoader::createMesh(io::IReadFile* file) | ||
130 | { | ||
131 | if (!file) | ||
132 | return 0; | ||
133 | |||
134 | AnimatedMesh = new CSkinnedMesh(); | ||
135 | |||
136 | if ( load(file) ) | ||
137 | { | ||
138 | AnimatedMesh->finalize(); | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | AnimatedMesh->drop(); | ||
143 | AnimatedMesh = 0; | ||
144 | } | ||
145 | |||
146 | return AnimatedMesh; | ||
147 | } | ||
148 | |||
149 | |||
150 | //! loads a milkshape file | ||
151 | bool CMS3DMeshFileLoader::load(io::IReadFile* file) | ||
152 | { | ||
153 | if (!file) | ||
154 | return false; | ||
155 | |||
156 | // find file size | ||
157 | const long fileSize = file->getSize(); | ||
158 | |||
159 | // read whole file | ||
160 | |||
161 | u8* buffer = new u8[fileSize]; | ||
162 | s32 read = file->read(buffer, fileSize); | ||
163 | if (read != fileSize) | ||
164 | { | ||
165 | delete [] buffer; | ||
166 | os::Printer::log("Could not read full file. Loading failed", file->getFileName(), ELL_ERROR); | ||
167 | return false; | ||
168 | } | ||
169 | |||
170 | // read header | ||
171 | |||
172 | const u8 *pPtr = (u8*)((void*)buffer); | ||
173 | MS3DHeader *pHeader = (MS3DHeader*)pPtr; | ||
174 | pPtr += sizeof(MS3DHeader); | ||
175 | |||
176 | if ( strncmp( pHeader->ID, "MS3D000000", 10 ) != 0 ) | ||
177 | { | ||
178 | delete [] buffer; | ||
179 | os::Printer::log("Not a valid Milkshape3D Model File. Loading failed", file->getFileName(), ELL_ERROR); | ||
180 | return false; | ||
181 | } | ||
182 | |||
183 | #ifdef __BIG_ENDIAN__ | ||
184 | pHeader->Version = os::Byteswap::byteswap(pHeader->Version); | ||
185 | #endif | ||
186 | if ( pHeader->Version < 3 || pHeader->Version > 4 ) | ||
187 | { | ||
188 | delete [] buffer; | ||
189 | os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR); | ||
190 | return false; | ||
191 | } | ||
192 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
193 | os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str()); | ||
194 | #endif | ||
195 | |||
196 | // get pointers to data | ||
197 | |||
198 | // vertices | ||
199 | u16 numVertices = *(u16*)pPtr; | ||
200 | #ifdef __BIG_ENDIAN__ | ||
201 | numVertices = os::Byteswap::byteswap(numVertices); | ||
202 | #endif | ||
203 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
204 | os::Printer::log("Load vertices", core::stringc(numVertices).c_str()); | ||
205 | #endif | ||
206 | pPtr += sizeof(u16); | ||
207 | MS3DVertex *vertices = (MS3DVertex*)pPtr; | ||
208 | pPtr += sizeof(MS3DVertex) * numVertices; | ||
209 | if (pPtr > buffer+fileSize) | ||
210 | { | ||
211 | delete [] buffer; | ||
212 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
213 | return false; | ||
214 | } | ||
215 | for (u16 tmp=0; tmp<numVertices; ++tmp) | ||
216 | { | ||
217 | #ifdef __BIG_ENDIAN__ | ||
218 | vertices[tmp].Vertex[0] = os::Byteswap::byteswap(vertices[tmp].Vertex[0]); | ||
219 | vertices[tmp].Vertex[1] = os::Byteswap::byteswap(vertices[tmp].Vertex[1]); | ||
220 | vertices[tmp].Vertex[2] = -os::Byteswap::byteswap(vertices[tmp].Vertex[2]); | ||
221 | #else | ||
222 | vertices[tmp].Vertex[2] = -vertices[tmp].Vertex[2]; | ||
223 | #endif | ||
224 | } | ||
225 | |||
226 | // triangles | ||
227 | u16 numTriangles = *(u16*)pPtr; | ||
228 | #ifdef __BIG_ENDIAN__ | ||
229 | numTriangles = os::Byteswap::byteswap(numTriangles); | ||
230 | #endif | ||
231 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
232 | os::Printer::log("Load Triangles", core::stringc(numTriangles).c_str()); | ||
233 | #endif | ||
234 | pPtr += sizeof(u16); | ||
235 | MS3DTriangle *triangles = (MS3DTriangle*)pPtr; | ||
236 | pPtr += sizeof(MS3DTriangle) * numTriangles; | ||
237 | if (pPtr > buffer+fileSize) | ||
238 | { | ||
239 | delete [] buffer; | ||
240 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
241 | return false; | ||
242 | } | ||
243 | for (u16 tmp=0; tmp<numTriangles; ++tmp) | ||
244 | { | ||
245 | #ifdef __BIG_ENDIAN__ | ||
246 | triangles[tmp].Flags = os::Byteswap::byteswap(triangles[tmp].Flags); | ||
247 | for (u16 j=0; j<3; ++j) | ||
248 | { | ||
249 | triangles[tmp].VertexIndices[j] = os::Byteswap::byteswap(triangles[tmp].VertexIndices[j]); | ||
250 | triangles[tmp].VertexNormals[j][0] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][0]); | ||
251 | triangles[tmp].VertexNormals[j][1] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][1]); | ||
252 | triangles[tmp].VertexNormals[j][2] = -os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][2]); | ||
253 | triangles[tmp].S[j] = os::Byteswap::byteswap(triangles[tmp].S[j]); | ||
254 | triangles[tmp].T[j] = os::Byteswap::byteswap(triangles[tmp].T[j]); | ||
255 | } | ||
256 | #else | ||
257 | triangles[tmp].VertexNormals[0][2] = -triangles[tmp].VertexNormals[0][2]; | ||
258 | triangles[tmp].VertexNormals[1][2] = -triangles[tmp].VertexNormals[1][2]; | ||
259 | triangles[tmp].VertexNormals[2][2] = -triangles[tmp].VertexNormals[2][2]; | ||
260 | #endif | ||
261 | } | ||
262 | |||
263 | // groups | ||
264 | u16 numGroups = *(u16*)pPtr; | ||
265 | #ifdef __BIG_ENDIAN__ | ||
266 | numGroups = os::Byteswap::byteswap(numGroups); | ||
267 | #endif | ||
268 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
269 | os::Printer::log("Load Groups", core::stringc(numGroups).c_str()); | ||
270 | #endif | ||
271 | pPtr += sizeof(u16); | ||
272 | |||
273 | core::array<SGroup> groups; | ||
274 | groups.reallocate(numGroups); | ||
275 | |||
276 | //store groups | ||
277 | u32 i; | ||
278 | for (i=0; i<numGroups; ++i) | ||
279 | { | ||
280 | groups.push_back(SGroup()); | ||
281 | SGroup& grp = groups.getLast(); | ||
282 | |||
283 | // The byte flag is before the name, so add 1 | ||
284 | grp.Name = ((const c8*) pPtr) + 1; | ||
285 | |||
286 | pPtr += 33; // name and 1 byte flags | ||
287 | u16 triangleCount = *(u16*)pPtr; | ||
288 | #ifdef __BIG_ENDIAN__ | ||
289 | triangleCount = os::Byteswap::byteswap(triangleCount); | ||
290 | #endif | ||
291 | pPtr += sizeof(u16); | ||
292 | grp.VertexIds.reallocate(triangleCount); | ||
293 | |||
294 | //pPtr += sizeof(u16) * triangleCount; // triangle indices | ||
295 | for (u16 j=0; j<triangleCount; ++j) | ||
296 | { | ||
297 | #ifdef __BIG_ENDIAN__ | ||
298 | grp.VertexIds.push_back(os::Byteswap::byteswap(*(u16*)pPtr)); | ||
299 | #else | ||
300 | grp.VertexIds.push_back(*(u16*)pPtr); | ||
301 | #endif | ||
302 | pPtr += sizeof (u16); | ||
303 | } | ||
304 | |||
305 | grp.MaterialIdx = *(u8*)pPtr; | ||
306 | if (grp.MaterialIdx == 255) | ||
307 | grp.MaterialIdx = 0; | ||
308 | |||
309 | pPtr += sizeof(c8); // material index | ||
310 | if (pPtr > buffer+fileSize) | ||
311 | { | ||
312 | delete [] buffer; | ||
313 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
314 | return false; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | // load materials | ||
319 | u16 numMaterials = *(u16*)pPtr; | ||
320 | #ifdef __BIG_ENDIAN__ | ||
321 | numMaterials = os::Byteswap::byteswap(numMaterials); | ||
322 | #endif | ||
323 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
324 | os::Printer::log("Load Materials", core::stringc(numMaterials).c_str()); | ||
325 | #endif | ||
326 | pPtr += sizeof(u16); | ||
327 | |||
328 | if(numMaterials == 0) | ||
329 | { | ||
330 | // if there are no materials, add at least one buffer | ||
331 | AnimatedMesh->addMeshBuffer(); | ||
332 | } | ||
333 | |||
334 | for (i=0; i<numMaterials; ++i) | ||
335 | { | ||
336 | MS3DMaterial *material = (MS3DMaterial*)pPtr; | ||
337 | #ifdef __BIG_ENDIAN__ | ||
338 | for (u16 j=0; j<4; ++j) | ||
339 | material->Ambient[j] = os::Byteswap::byteswap(material->Ambient[j]); | ||
340 | for (u16 j=0; j<4; ++j) | ||
341 | material->Diffuse[j] = os::Byteswap::byteswap(material->Diffuse[j]); | ||
342 | for (u16 j=0; j<4; ++j) | ||
343 | material->Specular[j] = os::Byteswap::byteswap(material->Specular[j]); | ||
344 | for (u16 j=0; j<4; ++j) | ||
345 | material->Emissive[j] = os::Byteswap::byteswap(material->Emissive[j]); | ||
346 | material->Shininess = os::Byteswap::byteswap(material->Shininess); | ||
347 | material->Transparency = os::Byteswap::byteswap(material->Transparency); | ||
348 | #endif | ||
349 | pPtr += sizeof(MS3DMaterial); | ||
350 | if (pPtr > buffer+fileSize) | ||
351 | { | ||
352 | delete [] buffer; | ||
353 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
354 | return false; | ||
355 | } | ||
356 | |||
357 | scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer(); | ||
358 | |||
359 | tmpBuffer->Material.MaterialType = video::EMT_SOLID; | ||
360 | |||
361 | tmpBuffer->Material.AmbientColor = video::SColorf(material->Ambient[0], material->Ambient[1], material->Ambient[2], material->Ambient[3]).toSColor (); | ||
362 | tmpBuffer->Material.DiffuseColor = video::SColorf(material->Diffuse[0], material->Diffuse[1], material->Diffuse[2], material->Diffuse[3]).toSColor (); | ||
363 | tmpBuffer->Material.EmissiveColor = video::SColorf(material->Emissive[0], material->Emissive[1], material->Emissive[2], material->Emissive[3]).toSColor (); | ||
364 | tmpBuffer->Material.SpecularColor = video::SColorf(material->Specular[0], material->Specular[1], material->Specular[2], material->Specular[3]).toSColor (); | ||
365 | tmpBuffer->Material.Shininess = material->Shininess; | ||
366 | |||
367 | core::stringc TexturePath(material->Texture); | ||
368 | if (TexturePath.trim()!="") | ||
369 | { | ||
370 | TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); | ||
371 | tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath)); | ||
372 | } | ||
373 | |||
374 | core::stringc AlphamapPath=(const c8*)material->Alphamap; | ||
375 | if (AlphamapPath.trim()!="") | ||
376 | { | ||
377 | AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); | ||
378 | tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath)); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | // animation time | ||
383 | f32 framesPerSecond = *(float*)pPtr; | ||
384 | #ifdef __BIG_ENDIAN__ | ||
385 | framesPerSecond = os::Byteswap::byteswap(framesPerSecond); | ||
386 | #endif | ||
387 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
388 | os::Printer::log("FPS", core::stringc(framesPerSecond).c_str()); | ||
389 | #endif | ||
390 | pPtr += sizeof(float) * 2; // fps and current time | ||
391 | |||
392 | if (framesPerSecond<1.f) | ||
393 | framesPerSecond=1.f; | ||
394 | AnimatedMesh->setAnimationSpeed(framesPerSecond); | ||
395 | |||
396 | // ignore, calculated inside SkinnedMesh | ||
397 | // s32 frameCount = *(int*)pPtr; | ||
398 | #ifdef __BIG_ENDIAN__ | ||
399 | // frameCount = os::Byteswap::byteswap(frameCount); | ||
400 | #endif | ||
401 | pPtr += sizeof(int); | ||
402 | |||
403 | u16 jointCount = *(u16*)pPtr; | ||
404 | #ifdef __BIG_ENDIAN__ | ||
405 | jointCount = os::Byteswap::byteswap(jointCount); | ||
406 | #endif | ||
407 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
408 | os::Printer::log("Joints", core::stringc(jointCount).c_str()); | ||
409 | #endif | ||
410 | pPtr += sizeof(u16); | ||
411 | if (pPtr > buffer+fileSize) | ||
412 | { | ||
413 | delete [] buffer; | ||
414 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
415 | return false; | ||
416 | } | ||
417 | |||
418 | core::array<core::stringc> parentNames; | ||
419 | parentNames.reallocate(jointCount); | ||
420 | |||
421 | // load joints | ||
422 | for (i=0; i<jointCount; ++i) | ||
423 | { | ||
424 | u32 j; | ||
425 | MS3DJoint *pJoint = (MS3DJoint*)pPtr; | ||
426 | #ifdef __BIG_ENDIAN__ | ||
427 | for (j=0; j<3; ++j) | ||
428 | pJoint->Rotation[j] = os::Byteswap::byteswap(pJoint->Rotation[j]); | ||
429 | for (j=0; j<3; ++j) | ||
430 | pJoint->Translation[j] = os::Byteswap::byteswap(pJoint->Translation[j]); | ||
431 | pJoint->NumRotationKeyframes= os::Byteswap::byteswap(pJoint->NumRotationKeyframes); | ||
432 | pJoint->NumTranslationKeyframes = os::Byteswap::byteswap(pJoint->NumTranslationKeyframes); | ||
433 | #endif | ||
434 | pPtr += sizeof(MS3DJoint); | ||
435 | if (pPtr > buffer+fileSize) | ||
436 | { | ||
437 | delete [] buffer; | ||
438 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
439 | return false; | ||
440 | } | ||
441 | |||
442 | ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint(); | ||
443 | |||
444 | jnt->Name = pJoint->Name; | ||
445 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
446 | os::Printer::log("Joint", jnt->Name.c_str()); | ||
447 | os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str()); | ||
448 | os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str()); | ||
449 | #endif | ||
450 | jnt->LocalMatrix.makeIdentity(); | ||
451 | jnt->LocalMatrix.setRotationRadians( | ||
452 | core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) ); | ||
453 | // convert right-handed to left-handed | ||
454 | jnt->LocalMatrix[2]=-jnt->LocalMatrix[2]; | ||
455 | jnt->LocalMatrix[6]=-jnt->LocalMatrix[6]; | ||
456 | jnt->LocalMatrix[8]=-jnt->LocalMatrix[8]; | ||
457 | jnt->LocalMatrix[9]=-jnt->LocalMatrix[9]; | ||
458 | |||
459 | jnt->LocalMatrix.setTranslation( | ||
460 | core::vector3df(pJoint->Translation[0], pJoint->Translation[1], -pJoint->Translation[2]) ); | ||
461 | jnt->Animatedposition.set(jnt->LocalMatrix.getTranslation()); | ||
462 | jnt->Animatedrotation.set(jnt->LocalMatrix.getRotationDegrees()); | ||
463 | |||
464 | parentNames.push_back( (c8*)pJoint->ParentName ); | ||
465 | |||
466 | /*if (pJoint->NumRotationKeyframes || | ||
467 | pJoint->NumTranslationKeyframes) | ||
468 | HasAnimation = true; | ||
469 | */ | ||
470 | |||
471 | // get rotation keyframes | ||
472 | const u16 numRotationKeyframes = pJoint->NumRotationKeyframes; | ||
473 | for (j=0; j < numRotationKeyframes; ++j) | ||
474 | { | ||
475 | MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; | ||
476 | #ifdef __BIG_ENDIAN__ | ||
477 | kf->Time = os::Byteswap::byteswap(kf->Time); | ||
478 | for (u32 l=0; l<3; ++l) | ||
479 | kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); | ||
480 | #endif | ||
481 | pPtr += sizeof(MS3DKeyframe); | ||
482 | if (pPtr > buffer+fileSize) | ||
483 | { | ||
484 | delete [] buffer; | ||
485 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
486 | return false; | ||
487 | } | ||
488 | |||
489 | ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt); | ||
490 | k->frame = kf->Time * framesPerSecond-1; | ||
491 | |||
492 | core::matrix4 tmpMatrix; | ||
493 | |||
494 | tmpMatrix.setRotationRadians( | ||
495 | core::vector3df(kf->Parameter[0], kf->Parameter[1], kf->Parameter[2]) ); | ||
496 | // convert right-handed to left-handed | ||
497 | tmpMatrix[2]=-tmpMatrix[2]; | ||
498 | tmpMatrix[6]=-tmpMatrix[6]; | ||
499 | tmpMatrix[8]=-tmpMatrix[8]; | ||
500 | tmpMatrix[9]=-tmpMatrix[9]; | ||
501 | |||
502 | tmpMatrix=jnt->LocalMatrix*tmpMatrix; | ||
503 | |||
504 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from tmpMatrix to tmpMatrix.getTransposed() for downward compatibility. | ||
505 | // Not tested so far if this was correct or wrong before quaternion fix! | ||
506 | k->rotation = core::quaternion(tmpMatrix.getTransposed()); | ||
507 | } | ||
508 | |||
509 | // get translation keyframes | ||
510 | const u16 numTranslationKeyframes = pJoint->NumTranslationKeyframes; | ||
511 | for (j=0; j<numTranslationKeyframes; ++j) | ||
512 | { | ||
513 | MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; | ||
514 | #ifdef __BIG_ENDIAN__ | ||
515 | kf->Time = os::Byteswap::byteswap(kf->Time); | ||
516 | for (u32 l=0; l<3; ++l) | ||
517 | kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); | ||
518 | #endif | ||
519 | pPtr += sizeof(MS3DKeyframe); | ||
520 | if (pPtr > buffer+fileSize) | ||
521 | { | ||
522 | delete [] buffer; | ||
523 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
524 | return false; | ||
525 | } | ||
526 | |||
527 | ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt); | ||
528 | k->frame = kf->Time * framesPerSecond-1; | ||
529 | |||
530 | k->position = core::vector3df | ||
531 | (kf->Parameter[0]+pJoint->Translation[0], | ||
532 | kf->Parameter[1]+pJoint->Translation[1], | ||
533 | -kf->Parameter[2]-pJoint->Translation[2]); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | core::array<MS3DVertexWeights> vertexWeights; | ||
538 | f32 weightFactor=0; | ||
539 | |||
540 | if (jointCount && (pHeader->Version == 4) && (pPtr < buffer+fileSize)) | ||
541 | { | ||
542 | s32 subVersion = *(s32*)pPtr; // comment subVersion, always 1 | ||
543 | #ifdef __BIG_ENDIAN__ | ||
544 | subVersion = os::Byteswap::byteswap(subVersion); | ||
545 | #endif | ||
546 | pPtr += sizeof(s32); | ||
547 | |||
548 | for (u32 j=0; j<4; ++j) // four comment groups | ||
549 | { | ||
550 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
551 | os::Printer::log("Skipping comment group", core::stringc(j+1).c_str()); | ||
552 | #endif | ||
553 | u32 numComments = *(u32*)pPtr; | ||
554 | #ifdef __BIG_ENDIAN__ | ||
555 | numComments = os::Byteswap::byteswap(numComments); | ||
556 | #endif | ||
557 | pPtr += sizeof(u32); | ||
558 | for (i=0; i<numComments; ++i) | ||
559 | { | ||
560 | // according to scorpiomidget this field does | ||
561 | // not exist for model comments. So avoid to | ||
562 | // read it | ||
563 | if (j!=3) | ||
564 | pPtr += sizeof(s32); // index | ||
565 | s32 commentLength = *(s32*)pPtr; | ||
566 | #ifdef __BIG_ENDIAN__ | ||
567 | commentLength = os::Byteswap::byteswap(commentLength); | ||
568 | #endif | ||
569 | pPtr += sizeof(s32); | ||
570 | pPtr += commentLength; | ||
571 | } | ||
572 | |||
573 | if (pPtr > buffer+fileSize) | ||
574 | { | ||
575 | delete [] buffer; | ||
576 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
577 | return false; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | if (pPtr < buffer+fileSize) | ||
582 | { | ||
583 | subVersion = *(s32*)pPtr; // vertex subVersion, 1 or 2 | ||
584 | #ifdef __BIG_ENDIAN__ | ||
585 | subVersion = os::Byteswap::byteswap(subVersion); | ||
586 | #endif | ||
587 | if (subVersion==1) | ||
588 | weightFactor=1.f/255.f; | ||
589 | else | ||
590 | weightFactor=1.f/100.f; | ||
591 | pPtr += sizeof(s32); | ||
592 | |||
593 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
594 | os::Printer::log("Reading vertex weights"); | ||
595 | #endif | ||
596 | // read vertex weights, ignoring data 'extra' from 1.8.2 | ||
597 | vertexWeights.reallocate(numVertices); | ||
598 | const char offset = (subVersion==1)?6:10; | ||
599 | for (i=0; i<numVertices; ++i) | ||
600 | { | ||
601 | vertexWeights.push_back(*(MS3DVertexWeights*)pPtr); | ||
602 | pPtr += offset; | ||
603 | } | ||
604 | |||
605 | if (pPtr > buffer+fileSize) | ||
606 | { | ||
607 | delete [] buffer; | ||
608 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | ||
609 | return false; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | if (pPtr < buffer+fileSize) | ||
614 | { | ||
615 | subVersion = *(s32*)pPtr; // joint subVersion, 1 or 2 | ||
616 | #ifdef __BIG_ENDIAN__ | ||
617 | subVersion = os::Byteswap::byteswap(subVersion); | ||
618 | #endif | ||
619 | pPtr += sizeof(s32); | ||
620 | // skip joint colors | ||
621 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
622 | os::Printer::log("Skip joint color"); | ||
623 | #endif | ||
624 | pPtr += 3*sizeof(float)*jointCount; | ||
625 | |||
626 | if (pPtr > buffer+fileSize) | ||
627 | { | ||
628 | delete [] buffer; | ||
629 | os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); | ||
630 | return false; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | if (pPtr < buffer+fileSize) | ||
635 | { | ||
636 | subVersion = *(s32*)pPtr; // model subVersion, 1 or 2 | ||
637 | #ifdef __BIG_ENDIAN__ | ||
638 | subVersion = os::Byteswap::byteswap(subVersion); | ||
639 | #endif | ||
640 | pPtr += sizeof(s32); | ||
641 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | ||
642 | os::Printer::log("Skip model extra information"); | ||
643 | #endif | ||
644 | // now the model extra information would follow | ||
645 | // we also skip this for now | ||
646 | } | ||
647 | } | ||
648 | |||
649 | //find parent of every joint | ||
650 | for (u32 jointnum=0; jointnum<AnimatedMesh->getAllJoints().size(); ++jointnum) | ||
651 | { | ||
652 | for (u32 j2=0; j2<AnimatedMesh->getAllJoints().size(); ++j2) | ||
653 | { | ||
654 | if (jointnum != j2 && parentNames[jointnum] == AnimatedMesh->getAllJoints()[j2]->Name ) | ||
655 | { | ||
656 | AnimatedMesh->getAllJoints()[j2]->Children.push_back(AnimatedMesh->getAllJoints()[jointnum]); | ||
657 | break; | ||
658 | } | ||
659 | } | ||
660 | } | ||
661 | |||
662 | // create vertices and indices, attach them to the joints. | ||
663 | video::S3DVertex v; | ||
664 | core::array<video::S3DVertex> *Vertices; | ||
665 | core::array<u16> Indices; | ||
666 | |||
667 | for (i=0; i<numTriangles; ++i) | ||
668 | { | ||
669 | u32 tmp = groups[triangles[i].GroupIndex].MaterialIdx; | ||
670 | Vertices = &AnimatedMesh->getMeshBuffers()[tmp]->Vertices_Standard; | ||
671 | |||
672 | for (s32 j = 2; j!=-1; --j) | ||
673 | { | ||
674 | const u32 vertidx = triangles[i].VertexIndices[j]; | ||
675 | |||
676 | v.TCoords.X = triangles[i].S[j]; | ||
677 | v.TCoords.Y = triangles[i].T[j]; | ||
678 | |||
679 | v.Normal.X = triangles[i].VertexNormals[j][0]; | ||
680 | v.Normal.Y = triangles[i].VertexNormals[j][1]; | ||
681 | v.Normal.Z = triangles[i].VertexNormals[j][2]; | ||
682 | |||
683 | if(triangles[i].GroupIndex < groups.size() && | ||
684 | groups[triangles[i].GroupIndex].MaterialIdx < AnimatedMesh->getMeshBuffers().size()) | ||
685 | v.Color = AnimatedMesh->getMeshBuffers()[groups[triangles[i].GroupIndex].MaterialIdx]->Material.DiffuseColor; | ||
686 | else | ||
687 | v.Color.set(255,255,255,255); | ||
688 | |||
689 | v.Pos.X = vertices[vertidx].Vertex[0]; | ||
690 | v.Pos.Y = vertices[vertidx].Vertex[1]; | ||
691 | v.Pos.Z = vertices[vertidx].Vertex[2]; | ||
692 | |||
693 | // check if we already have this vertex in our vertex array | ||
694 | s32 index = -1; | ||
695 | for (u32 iV = 0; iV < Vertices->size(); ++iV) | ||
696 | { | ||
697 | if (v == (*Vertices)[iV]) | ||
698 | { | ||
699 | index = (s32)iV; | ||
700 | break; | ||
701 | } | ||
702 | } | ||
703 | |||
704 | if (index == -1) | ||
705 | { | ||
706 | index = Vertices->size(); | ||
707 | const u32 matidx = groups[triangles[i].GroupIndex].MaterialIdx; | ||
708 | if (vertexWeights.size()==0) | ||
709 | { | ||
710 | const s32 boneid = vertices[vertidx].BoneID; | ||
711 | if ((u32)boneid < AnimatedMesh->getAllJoints().size()) | ||
712 | { | ||
713 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | ||
714 | w->buffer_id = matidx; | ||
715 | w->strength = 1.0f; | ||
716 | w->vertex_id = index; | ||
717 | } | ||
718 | } | ||
719 | else if (jointCount) // new weights from 1.8.x | ||
720 | { | ||
721 | f32 sum = 1.0f; | ||
722 | s32 boneid = vertices[vertidx].BoneID; | ||
723 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0)) | ||
724 | { | ||
725 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | ||
726 | w->buffer_id = matidx; | ||
727 | sum -= (w->strength = vertexWeights[vertidx].weights[0]*weightFactor); | ||
728 | w->vertex_id = index; | ||
729 | } | ||
730 | boneid = vertexWeights[vertidx].boneIds[0]; | ||
731 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0)) | ||
732 | { | ||
733 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | ||
734 | w->buffer_id = matidx; | ||
735 | sum -= (w->strength = vertexWeights[vertidx].weights[1]*weightFactor); | ||
736 | w->vertex_id = index; | ||
737 | } | ||
738 | boneid = vertexWeights[vertidx].boneIds[1]; | ||
739 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0)) | ||
740 | { | ||
741 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | ||
742 | w->buffer_id = matidx; | ||
743 | sum -= (w->strength = vertexWeights[vertidx].weights[2]*weightFactor); | ||
744 | w->vertex_id = index; | ||
745 | } | ||
746 | boneid = vertexWeights[vertidx].boneIds[2]; | ||
747 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f)) | ||
748 | { | ||
749 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | ||
750 | w->buffer_id = matidx; | ||
751 | w->strength = sum; | ||
752 | w->vertex_id = index; | ||
753 | } | ||
754 | // fallback, if no bone chosen. Seems to be an error in the specs | ||
755 | boneid = vertices[vertidx].BoneID; | ||
756 | if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size())) | ||
757 | { | ||
758 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | ||
759 | w->buffer_id = matidx; | ||
760 | w->strength = 1.f; | ||
761 | w->vertex_id = index; | ||
762 | } | ||
763 | } | ||
764 | |||
765 | Vertices->push_back(v); | ||
766 | } | ||
767 | Indices.push_back(index); | ||
768 | } | ||
769 | } | ||
770 | |||
771 | //create groups | ||
772 | s32 iIndex = -1; | ||
773 | for (i=0; i<groups.size(); ++i) | ||
774 | { | ||
775 | SGroup& grp = groups[i]; | ||
776 | |||
777 | if (grp.MaterialIdx >= AnimatedMesh->getMeshBuffers().size()) | ||
778 | grp.MaterialIdx = 0; | ||
779 | |||
780 | core::array<u16>& indices = AnimatedMesh->getMeshBuffers()[grp.MaterialIdx]->Indices; | ||
781 | |||
782 | for (u32 k=0; k < grp.VertexIds.size(); ++k) | ||
783 | for (u32 l=0; l<3; ++l) | ||
784 | indices.push_back(Indices[++iIndex]); | ||
785 | } | ||
786 | |||
787 | delete [] buffer; | ||
788 | |||
789 | return true; | ||
790 | } | ||
791 | |||
792 | |||
793 | core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const | ||
794 | { | ||
795 | s32 slashIndex=inString.findLast('/'); // forward slash | ||
796 | s32 backSlash=inString.findLast('\\'); // back slash | ||
797 | |||
798 | if (backSlash>slashIndex) slashIndex=backSlash; | ||
799 | |||
800 | if (slashIndex==-1)//no slashes found | ||
801 | { | ||
802 | if (returnPath) | ||
803 | return core::stringc(); //no path to return | ||
804 | else | ||
805 | return inString; | ||
806 | } | ||
807 | |||
808 | if (returnPath) | ||
809 | return inString.subString(0, slashIndex + 1); | ||
810 | else | ||
811 | return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); | ||
812 | } | ||
813 | |||
814 | |||
815 | } // end namespace scene | ||
816 | } // end namespace irr | ||
817 | |||
818 | #endif | ||