aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CMS3DMeshFileLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CMS3DMeshFileLoader.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CMS3DMeshFileLoader.cpp818
1 files changed, 818 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CMS3DMeshFileLoader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CMS3DMeshFileLoader.cpp
new file mode 100644
index 0000000..9a88d49
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/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
14namespace irr
15{
16namespace scene
17{
18
19#ifdef _DEBUG
20#define _IRR_DEBUG_MS3D_LOADER_
21#endif
22
23// byte-align structures
24#include "irrpack.h"
25
26namespace {
27// File header
28struct MS3DHeader
29{
30 char ID[10];
31 int Version;
32} PACK_STRUCT;
33
34// Vertex information
35struct MS3DVertex
36{
37 u8 Flags;
38 float Vertex[3];
39 char BoneID;
40 u8 RefCount;
41} PACK_STRUCT;
42
43// Triangle information
44struct 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
55struct 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
70struct 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
82struct MS3DKeyframe
83{
84 float Time;
85 float Parameter[3];
86} PACK_STRUCT;
87
88// vertex weights in 1.8.x
89struct 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
100struct SGroup
101{
102 core::stringc Name;
103 core::array<u16> VertexIds;
104 u16 MaterialIdx;
105};
106
107//! Constructor
108CMS3DMeshFileLoader::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")
119bool 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.
129IAnimatedMesh* 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
151bool 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
793core::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