1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4 
5 Copyright (c) 2006-2015, assimp team
6 All rights reserved.
7 
8 Redistribution and use of this software in source and binary forms,
9 with or without modification, are permitted provided that the
10 following conditions are met:
11 
12 * Redistributions of source code must retain the above
13   copyright notice, this list of conditions and the
14   following disclaimer.
15 
16 * Redistributions in binary form must reproduce the above
17   copyright notice, this list of conditions and the
18   following disclaimer in the documentation and/or other
19   materials provided with the distribution.
20 
21 * Neither the name of the assimp team, nor the names of its
22   contributors may be used to endorse or promote products
23   derived from this software without specific prior
24   written permission of the assimp team.
25 
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 
38 ----------------------------------------------------------------------
39 */
40 
41 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
42 
43 #include "OgreStructs.h"
44 #include "TinyFormatter.h"
45 #include "../include/assimp/scene.h"
46 #include "../include/assimp/DefaultLogger.hpp"
47 #include "Exceptional.h"
48 
49 
50 namespace Assimp
51 {
52 namespace Ogre
53 {
54 
55 // VertexElement
56 
VertexElement()57 VertexElement::VertexElement() :
58     index(0),
59     source(0),
60     offset(0),
61     type(VET_FLOAT1),
62     semantic(VES_POSITION)
63 {
64 }
65 
Size() const66 size_t VertexElement::Size() const
67 {
68     return TypeSize(type);
69 }
70 
ComponentCount() const71 size_t VertexElement::ComponentCount() const
72 {
73     return ComponentCount(type);
74 }
75 
ComponentCount(Type type)76 size_t VertexElement::ComponentCount(Type type)
77 {
78     switch(type)
79     {
80         case VET_COLOUR:
81         case VET_COLOUR_ABGR:
82         case VET_COLOUR_ARGB:
83         case VET_FLOAT1:
84         case VET_DOUBLE1:
85         case VET_SHORT1:
86         case VET_USHORT1:
87         case VET_INT1:
88         case VET_UINT1:
89             return 1;
90         case VET_FLOAT2:
91         case VET_DOUBLE2:
92         case VET_SHORT2:
93         case VET_USHORT2:
94         case VET_INT2:
95         case VET_UINT2:
96             return 2;
97         case VET_FLOAT3:
98         case VET_DOUBLE3:
99         case VET_SHORT3:
100         case VET_USHORT3:
101         case VET_INT3:
102         case VET_UINT3:
103             return 3;
104         case VET_FLOAT4:
105         case VET_DOUBLE4:
106         case VET_SHORT4:
107         case VET_USHORT4:
108         case VET_INT4:
109         case VET_UINT4:
110         case VET_UBYTE4:
111             return 4;
112     }
113     return 0;
114 }
115 
TypeSize(Type type)116 size_t VertexElement::TypeSize(Type type)
117 {
118     switch(type)
119     {
120         case VET_COLOUR:
121         case VET_COLOUR_ABGR:
122         case VET_COLOUR_ARGB:
123             return sizeof(unsigned int);
124         case VET_FLOAT1:
125             return sizeof(float);
126         case VET_FLOAT2:
127             return sizeof(float)*2;
128         case VET_FLOAT3:
129             return sizeof(float)*3;
130         case VET_FLOAT4:
131             return sizeof(float)*4;
132         case VET_DOUBLE1:
133             return sizeof(double);
134         case VET_DOUBLE2:
135             return sizeof(double)*2;
136         case VET_DOUBLE3:
137             return sizeof(double)*3;
138         case VET_DOUBLE4:
139             return sizeof(double)*4;
140         case VET_SHORT1:
141             return sizeof(short);
142         case VET_SHORT2:
143             return sizeof(short)*2;
144         case VET_SHORT3:
145             return sizeof(short)*3;
146         case VET_SHORT4:
147             return sizeof(short)*4;
148         case VET_USHORT1:
149             return sizeof(unsigned short);
150         case VET_USHORT2:
151             return sizeof(unsigned short)*2;
152         case VET_USHORT3:
153             return sizeof(unsigned short)*3;
154         case VET_USHORT4:
155             return sizeof(unsigned short)*4;
156         case VET_INT1:
157             return sizeof(int);
158         case VET_INT2:
159             return sizeof(int)*2;
160         case VET_INT3:
161             return sizeof(int)*3;
162         case VET_INT4:
163             return sizeof(int)*4;
164         case VET_UINT1:
165             return sizeof(unsigned int);
166         case VET_UINT2:
167             return sizeof(unsigned int)*2;
168         case VET_UINT3:
169             return sizeof(unsigned int)*3;
170         case VET_UINT4:
171             return sizeof(unsigned int)*4;
172         case VET_UBYTE4:
173             return sizeof(unsigned char)*4;
174     }
175     return 0;
176 }
177 
TypeToString()178 std::string VertexElement::TypeToString()
179 {
180     return TypeToString(type);
181 }
182 
TypeToString(Type type)183 std::string VertexElement::TypeToString(Type type)
184 {
185     switch(type)
186     {
187         case VET_COLOUR:        return "COLOUR";
188         case VET_COLOUR_ABGR:   return "COLOUR_ABGR";
189         case VET_COLOUR_ARGB:   return "COLOUR_ARGB";
190         case VET_FLOAT1:        return "FLOAT1";
191         case VET_FLOAT2:        return "FLOAT2";
192         case VET_FLOAT3:        return "FLOAT3";
193         case VET_FLOAT4:        return "FLOAT4";
194         case VET_DOUBLE1:       return "DOUBLE1";
195         case VET_DOUBLE2:       return "DOUBLE2";
196         case VET_DOUBLE3:       return "DOUBLE3";
197         case VET_DOUBLE4:       return "DOUBLE4";
198         case VET_SHORT1:        return "SHORT1";
199         case VET_SHORT2:        return "SHORT2";
200         case VET_SHORT3:        return "SHORT3";
201         case VET_SHORT4:        return "SHORT4";
202         case VET_USHORT1:       return "USHORT1";
203         case VET_USHORT2:       return "USHORT2";
204         case VET_USHORT3:       return "USHORT3";
205         case VET_USHORT4:       return "USHORT4";
206         case VET_INT1:          return "INT1";
207         case VET_INT2:          return "INT2";
208         case VET_INT3:          return "INT3";
209         case VET_INT4:          return "INT4";
210         case VET_UINT1:         return "UINT1";
211         case VET_UINT2:         return "UINT2";
212         case VET_UINT3:         return "UINT3";
213         case VET_UINT4:         return "UINT4";
214         case VET_UBYTE4:        return "UBYTE4";
215     }
216     return "Uknown_VertexElement::Type";
217 }
218 
SemanticToString()219 std::string VertexElement::SemanticToString()
220 {
221     return SemanticToString(semantic);
222 }
223 
SemanticToString(Semantic semantic)224 std::string VertexElement::SemanticToString(Semantic semantic)
225 {
226     switch(semantic)
227     {
228         case VES_POSITION:              return "POSITION";
229         case VES_BLEND_WEIGHTS:         return "BLEND_WEIGHTS";
230         case VES_BLEND_INDICES:         return "BLEND_INDICES";
231         case VES_NORMAL:                return "NORMAL";
232         case VES_DIFFUSE:               return "DIFFUSE";
233         case VES_SPECULAR:              return "SPECULAR";
234         case VES_TEXTURE_COORDINATES:   return "TEXTURE_COORDINATES";
235         case VES_BINORMAL:              return "BINORMAL";
236         case VES_TANGENT:               return "TANGENT";
237     }
238     return "Uknown_VertexElement::Semantic";
239 }
240 
241 // IVertexData
242 
IVertexData()243 IVertexData::IVertexData() :
244     count(0)
245 {
246 }
247 
HasBoneAssignments() const248 bool IVertexData::HasBoneAssignments() const
249 {
250     return !boneAssignments.empty();
251 }
252 
AddVertexMapping(uint32_t oldIndex,uint32_t newIndex)253 void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex)
254 {
255     BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]);
256     vertexIndexMapping[oldIndex].push_back(newIndex);
257 }
258 
BoneAssignmentsForVertex(uint32_t currentIndex,uint32_t newIndex,VertexBoneAssignmentList & dest) const259 void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const
260 {
261     for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end();
262         iter!=end; ++iter)
263     {
264         if (iter->vertexIndex == currentIndex)
265         {
266             VertexBoneAssignment a = (*iter);
267             a.vertexIndex = newIndex;
268             dest.push_back(a);
269         }
270     }
271 }
272 
AssimpBoneWeights(size_t vertices)273 AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices)
274 {
275     AssimpVertexBoneWeightList weights;
276     for(size_t vi=0; vi<vertices; ++vi)
277     {
278         VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi];
279         for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end();
280             iter!=end; ++iter)
281         {
282             std::vector<aiVertexWeight> &boneWeights = weights[iter->boneIndex];
283             boneWeights.push_back(aiVertexWeight(vi, iter->weight));
284         }
285     }
286     return weights;
287 }
288 
ReferencedBonesByWeights() const289 std::set<uint16_t> IVertexData::ReferencedBonesByWeights() const
290 {
291     std::set<uint16_t> referenced;
292     for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end();
293         iter!=end; ++iter)
294     {
295         referenced.insert(iter->boneIndex);
296     }
297     return referenced;
298 }
299 
300 // VertexData
301 
VertexData()302 VertexData::VertexData()
303 {
304 }
305 
~VertexData()306 VertexData::~VertexData()
307 {
308     Reset();
309 }
310 
Reset()311 void VertexData::Reset()
312 {
313     // Releases shared ptr memory streams.
314     vertexBindings.clear();
315     vertexElements.clear();
316 }
317 
VertexSize(uint16_t source) const318 uint32_t VertexData::VertexSize(uint16_t source) const
319 {
320     uint32_t size = 0;
321     for(VertexElementList::const_iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
322     {
323         if (iter->source == source)
324             size += iter->Size();
325     }
326     return size;
327 }
328 
VertexBuffer(uint16_t source)329 MemoryStream *VertexData::VertexBuffer(uint16_t source)
330 {
331     if (vertexBindings.find(source) != vertexBindings.end())
332         return vertexBindings[source].get();
333     return 0;
334 }
335 
GetVertexElement(VertexElement::Semantic semantic,uint16_t index)336 VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index)
337 {
338     for(VertexElementList::iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
339     {
340         VertexElement &element = (*iter);
341         if (element.semantic == semantic && element.index == index)
342             return &element;
343     }
344     return 0;
345 }
346 
347 // VertexDataXml
348 
VertexDataXml()349 VertexDataXml::VertexDataXml()
350 {
351 }
352 
HasPositions() const353 bool VertexDataXml::HasPositions() const
354 {
355     return !positions.empty();
356 }
357 
HasNormals() const358 bool VertexDataXml::HasNormals() const
359 {
360     return !normals.empty();
361 }
362 
HasTangents() const363 bool VertexDataXml::HasTangents() const
364 {
365     return !tangents.empty();
366 }
367 
HasUvs() const368 bool VertexDataXml::HasUvs() const
369 {
370     return !uvs.empty();
371 }
372 
NumUvs() const373 size_t VertexDataXml::NumUvs() const
374 {
375     return uvs.size();
376 }
377 
378 // IndexData
379 
IndexData()380 IndexData::IndexData() :
381     count(0),
382     faceCount(0),
383     is32bit(false)
384 {
385 }
386 
~IndexData()387 IndexData::~IndexData()
388 {
389     Reset();
390 }
391 
Reset()392 void IndexData::Reset()
393 {
394     // Release shared ptr memory stream.
395     buffer.reset();
396 }
397 
IndexSize() const398 size_t IndexData::IndexSize() const
399 {
400     return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
401 }
402 
FaceSize() const403 size_t IndexData::FaceSize() const
404 {
405     return IndexSize() * 3;
406 }
407 
408 // Mesh
409 
Mesh()410 Mesh::Mesh() :
411     hasSkeletalAnimations(false),
412     skeleton(NULL),
413     sharedVertexData(NULL)
414 {
415 }
416 
~Mesh()417 Mesh::~Mesh()
418 {
419     Reset();
420 }
421 
Reset()422 void Mesh::Reset()
423 {
424     OGRE_SAFE_DELETE(skeleton)
425     OGRE_SAFE_DELETE(sharedVertexData)
426 
427     for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
428         OGRE_SAFE_DELETE(subMeshes[i])
429     }
430     subMeshes.clear();
431     for(size_t i=0, len=animations.size(); i<len; ++i) {
432         OGRE_SAFE_DELETE(animations[i])
433     }
434     animations.clear();
435     for(size_t i=0, len=poses.size(); i<len; ++i) {
436         OGRE_SAFE_DELETE(poses[i])
437     }
438     poses.clear();
439 }
440 
NumSubMeshes() const441 size_t Mesh::NumSubMeshes() const
442 {
443     return subMeshes.size();
444 }
445 
GetSubMesh(uint16_t index) const446 SubMesh *Mesh::GetSubMesh(uint16_t index) const
447 {
448     for(size_t i=0; i<subMeshes.size(); ++i)
449         if (subMeshes[i]->index == index)
450             return subMeshes[i];
451     return 0;
452 }
453 
ConvertToAssimpScene(aiScene * dest)454 void Mesh::ConvertToAssimpScene(aiScene* dest)
455 {
456     // Setup
457     dest->mNumMeshes = NumSubMeshes();
458     dest->mMeshes = new aiMesh*[dest->mNumMeshes];
459 
460     // Create root node
461     dest->mRootNode = new aiNode();
462     dest->mRootNode->mNumMeshes = dest->mNumMeshes;
463     dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
464 
465     // Export meshes
466     for(size_t i=0; i<dest->mNumMeshes; ++i)
467     {
468         dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
469         dest->mRootNode->mMeshes[i] = i;
470     }
471 
472     // Export skeleton
473     if (skeleton)
474     {
475         // Bones
476         if (!skeleton->bones.empty())
477         {
478             BoneList rootBones = skeleton->RootBones();
479             dest->mRootNode->mNumChildren = rootBones.size();
480             dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
481 
482             for(size_t i=0, len=rootBones.size(); i<len; ++i)
483             {
484                 dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
485             }
486         }
487 
488         // Animations
489         if (!skeleton->animations.empty())
490         {
491             dest->mNumAnimations = skeleton->animations.size();
492             dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
493 
494             for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
495             {
496                 dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
497             }
498         }
499     }
500 }
501 
502 // ISubMesh
503 
ISubMesh()504 ISubMesh::ISubMesh() :
505     index(0),
506     materialIndex(-1),
507     usesSharedVertexData(false),
508     operationType(OT_POINT_LIST)
509 {
510 }
511 
512 // SubMesh
513 
SubMesh()514 SubMesh::SubMesh() :
515     vertexData(0),
516     indexData(new IndexData())
517 {
518 }
519 
~SubMesh()520 SubMesh::~SubMesh()
521 {
522     Reset();
523 }
524 
Reset()525 void SubMesh::Reset()
526 {
527     OGRE_SAFE_DELETE(vertexData)
528     OGRE_SAFE_DELETE(indexData)
529 }
530 
ConvertToAssimpMesh(Mesh * parent)531 aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
532 {
533     if (operationType != OT_TRIANGLE_LIST) {
534         throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType);
535     }
536 
537     aiMesh *dest = new aiMesh();
538     dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
539 
540     if (!name.empty())
541         dest->mName = name;
542 
543     // Material index
544     if (materialIndex != -1)
545         dest->mMaterialIndex = materialIndex;
546 
547     // Pick source vertex data from shader geometry or from internal geometry.
548     VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
549 
550     VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION);
551     VertexElement *normalsElement   = src->GetVertexElement(VertexElement::VES_NORMAL);
552     VertexElement *uv1Element       = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0);
553     VertexElement *uv2Element       = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1);
554 
555     // Sanity checks
556     if (!positionsElement) {
557         throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!");
558     } else if (positionsElement->type != VertexElement::VET_FLOAT3) {
559         throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
560     } else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) {
561         throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
562     }
563 
564     // Faces
565     dest->mNumFaces = indexData->faceCount;
566     dest->mFaces = new aiFace[dest->mNumFaces];
567 
568     // Assimp required unique vertices, we need to convert from Ogres shared indexing.
569     size_t uniqueVertexCount = dest->mNumFaces * 3;
570     dest->mNumVertices = uniqueVertexCount;
571     dest->mVertices = new aiVector3D[dest->mNumVertices];
572 
573     // Source streams
574     MemoryStream *positions      = src->VertexBuffer(positionsElement->source);
575     MemoryStream *normals        = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0);
576     MemoryStream *uv1            = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0);
577     MemoryStream *uv2            = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0);
578 
579     // Element size
580     const size_t sizePosition    = positionsElement->Size();
581     const size_t sizeNormal      = (normalsElement ? normalsElement->Size() : 0);
582     const size_t sizeUv1         = (uv1Element ? uv1Element->Size() : 0);
583     const size_t sizeUv2         = (uv2Element ? uv2Element->Size() : 0);
584 
585     // Vertex width
586     const size_t vWidthPosition  = src->VertexSize(positionsElement->source);
587     const size_t vWidthNormal    = (normalsElement ? src->VertexSize(normalsElement->source) : 0);
588     const size_t vWidthUv1       = (uv1Element ? src->VertexSize(uv1Element->source) : 0);
589     const size_t vWidthUv2       = (uv2Element ? src->VertexSize(uv2Element->source) : 0);
590 
591     bool boneAssignments = src->HasBoneAssignments();
592 
593     // Prepare normals
594     if (normals)
595         dest->mNormals = new aiVector3D[dest->mNumVertices];
596 
597     // Prepare UVs, ignoring incompatible UVs.
598     if (uv1)
599     {
600         if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3)
601         {
602             dest->mNumUVComponents[0] = uv1Element->ComponentCount();
603             dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices];
604         }
605         else
606         {
607             DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
608             uv1 = 0;
609         }
610     }
611     if (uv2)
612     {
613         if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3)
614         {
615             dest->mNumUVComponents[1] = uv2Element->ComponentCount();
616             dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices];
617         }
618         else
619         {
620             DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
621             uv2 = 0;
622         }
623     }
624 
625     aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0);
626     aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0);
627 
628     MemoryStream *faces = indexData->buffer.get();
629     for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize();
630          fi<dest->mNumFaces; ++fi)
631     {
632         // Source Ogre face
633         aiFace ogreFace;
634         ogreFace.mNumIndices = 3;
635         ogreFace.mIndices = new unsigned int[3];
636 
637         faces->Seek(fi * fsize, aiOrigin_SET);
638         if (indexData->is32bit)
639         {
640             faces->Read(&ogreFace.mIndices[0], isize, 3);
641         }
642         else
643         {
644             uint16_t iout = 0;
645             for (size_t ii=0; ii<3; ++ii)
646             {
647                 faces->Read(&iout, isize, 1);
648                 ogreFace.mIndices[ii] = static_cast<unsigned int>(iout);
649             }
650         }
651 
652         // Destination Assimp face
653         aiFace &face = dest->mFaces[fi];
654         face.mNumIndices = 3;
655         face.mIndices = new unsigned int[3];
656 
657         const size_t pos = fi * 3;
658         for (size_t v=0; v<3; ++v)
659         {
660             const size_t newIndex = pos + v;
661 
662             // Write face index
663             face.mIndices[v] = newIndex;
664 
665             // Ogres vertex index to ref into the source buffers.
666             const size_t ogreVertexIndex = ogreFace.mIndices[v];
667             src->AddVertexMapping(ogreVertexIndex, newIndex);
668 
669             // Position
670             positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET);
671             positions->Read(&dest->mVertices[newIndex], sizePosition, 1);
672 
673             // Normal
674             if (normals)
675             {
676                 normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET);
677                 normals->Read(&dest->mNormals[newIndex], sizeNormal, 1);
678             }
679             // UV0
680             if (uv1 && uv1Dest)
681             {
682                 uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET);
683                 uv1->Read(&uv1Dest[newIndex], sizeUv1, 1);
684                 uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
685             }
686             // UV1
687             if (uv2 && uv2Dest)
688             {
689                 uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET);
690                 uv2->Read(&uv2Dest[newIndex], sizeUv2, 1);
691                 uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
692             }
693         }
694     }
695 
696     // Bones and bone weights
697     if (parent->skeleton && boneAssignments)
698     {
699         AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
700         std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
701 
702         dest->mNumBones = referencedBones.size();
703         dest->mBones = new aiBone*[dest->mNumBones];
704 
705         size_t assimpBoneIndex = 0;
706         for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
707         {
708             Bone *bone = parent->skeleton->BoneById((*rbIter));
709             dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
710         }
711     }
712 
713     return dest;
714 }
715 
716 // MeshXml
717 
MeshXml()718 MeshXml::MeshXml() :
719     skeleton(0),
720     sharedVertexData(0)
721 {
722 }
723 
~MeshXml()724 MeshXml::~MeshXml()
725 {
726     Reset();
727 }
728 
Reset()729 void MeshXml::Reset()
730 {
731     OGRE_SAFE_DELETE(skeleton)
732     OGRE_SAFE_DELETE(sharedVertexData)
733 
734     for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
735         OGRE_SAFE_DELETE(subMeshes[i])
736     }
737     subMeshes.clear();
738 }
739 
NumSubMeshes() const740 size_t MeshXml::NumSubMeshes() const
741 {
742     return subMeshes.size();
743 }
744 
GetSubMesh(uint16_t index) const745 SubMeshXml *MeshXml::GetSubMesh(uint16_t index) const
746 {
747     for(size_t i=0; i<subMeshes.size(); ++i)
748         if (subMeshes[i]->index == index)
749             return subMeshes[i];
750     return 0;
751 }
752 
ConvertToAssimpScene(aiScene * dest)753 void MeshXml::ConvertToAssimpScene(aiScene* dest)
754 {
755     // Setup
756     dest->mNumMeshes = NumSubMeshes();
757     dest->mMeshes = new aiMesh*[dest->mNumMeshes];
758 
759     // Create root node
760     dest->mRootNode = new aiNode();
761     dest->mRootNode->mNumMeshes = dest->mNumMeshes;
762     dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
763 
764     // Export meshes
765     for(size_t i=0; i<dest->mNumMeshes; ++i)
766     {
767         dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
768         dest->mRootNode->mMeshes[i] = i;
769     }
770 
771     // Export skeleton
772     if (skeleton)
773     {
774         // Bones
775         if (!skeleton->bones.empty())
776         {
777             BoneList rootBones = skeleton->RootBones();
778             dest->mRootNode->mNumChildren = rootBones.size();
779             dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
780 
781             for(size_t i=0, len=rootBones.size(); i<len; ++i)
782             {
783                 dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
784             }
785         }
786 
787         // Animations
788         if (!skeleton->animations.empty())
789         {
790             dest->mNumAnimations = skeleton->animations.size();
791             dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
792 
793             for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
794             {
795                 dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
796             }
797         }
798     }
799 }
800 
801 // SubMeshXml
802 
SubMeshXml()803 SubMeshXml::SubMeshXml() :
804     indexData(new IndexDataXml()),
805     vertexData(0)
806 {
807 }
808 
~SubMeshXml()809 SubMeshXml::~SubMeshXml()
810 {
811     Reset();
812 }
813 
Reset()814 void SubMeshXml::Reset()
815 {
816     OGRE_SAFE_DELETE(indexData)
817     OGRE_SAFE_DELETE(vertexData)
818 }
819 
ConvertToAssimpMesh(MeshXml * parent)820 aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
821 {
822     aiMesh *dest = new aiMesh();
823     dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
824 
825     if (!name.empty())
826         dest->mName = name;
827 
828     // Material index
829     if (materialIndex != -1)
830         dest->mMaterialIndex = materialIndex;
831 
832     // Faces
833     dest->mNumFaces = indexData->faceCount;
834     dest->mFaces = new aiFace[dest->mNumFaces];
835 
836     // Assimp required unique vertices, we need to convert from Ogres shared indexing.
837     size_t uniqueVertexCount = dest->mNumFaces * 3;
838     dest->mNumVertices = uniqueVertexCount;
839     dest->mVertices = new aiVector3D[dest->mNumVertices];
840 
841     VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
842     bool boneAssignments = src->HasBoneAssignments();
843     bool normals = src->HasNormals();
844     size_t uvs = src->NumUvs();
845 
846     // Prepare normals
847     if (normals)
848         dest->mNormals = new aiVector3D[dest->mNumVertices];
849 
850     // Prepare UVs
851     for(size_t uvi=0; uvi<uvs; ++uvi)
852     {
853         dest->mNumUVComponents[uvi] = 2;
854         dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices];
855     }
856 
857     for (size_t fi=0; fi<dest->mNumFaces; ++fi)
858     {
859         // Source Ogre face
860         aiFace &ogreFace = indexData->faces[fi];
861 
862         // Destination Assimp face
863         aiFace &face = dest->mFaces[fi];
864         face.mNumIndices = 3;
865         face.mIndices = new unsigned int[3];
866 
867         const size_t pos = fi * 3;
868         for (size_t v=0; v<3; ++v)
869         {
870             const size_t newIndex = pos + v;
871 
872             // Write face index
873             face.mIndices[v] = newIndex;
874 
875             // Ogres vertex index to ref into the source buffers.
876             const size_t ogreVertexIndex = ogreFace.mIndices[v];
877             src->AddVertexMapping(ogreVertexIndex, newIndex);
878 
879             // Position
880             dest->mVertices[newIndex] = src->positions[ogreVertexIndex];
881 
882             // Normal
883             if (normals)
884                 dest->mNormals[newIndex] = src->normals[ogreVertexIndex];
885 
886             // UVs
887             for(size_t uvi=0; uvi<uvs; ++uvi)
888             {
889                 aiVector3D *uvDest = dest->mTextureCoords[uvi];
890                 std::vector<aiVector3D> &uvSrc = src->uvs[uvi];
891                 uvDest[newIndex] = uvSrc[ogreVertexIndex];
892             }
893         }
894     }
895 
896     // Bones and bone weights
897     if (parent->skeleton && boneAssignments)
898     {
899         AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
900         std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
901 
902         dest->mNumBones = referencedBones.size();
903         dest->mBones = new aiBone*[dest->mNumBones];
904 
905         size_t assimpBoneIndex = 0;
906         for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
907         {
908             Bone *bone = parent->skeleton->BoneById((*rbIter));
909             dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
910         }
911     }
912 
913     return dest;
914 }
915 
916 // Animation
917 
Animation(Skeleton * parent)918 Animation::Animation(Skeleton *parent) :
919     parentMesh(NULL),
920     parentSkeleton(parent),
921     length(0.0f),
922     baseTime(-1.0f)
923 {
924 }
925 
Animation(Mesh * parent)926 Animation::Animation(Mesh *parent) :
927     parentMesh(parent),
928     parentSkeleton(0),
929     length(0.0f),
930     baseTime(-1.0f)
931 {
932 }
933 
AssociatedVertexData(VertexAnimationTrack * track) const934 VertexData *Animation::AssociatedVertexData(VertexAnimationTrack *track) const
935 {
936     if (!parentMesh)
937         return 0;
938 
939     bool sharedGeom = (track->target == 0);
940     if (sharedGeom)
941         return parentMesh->sharedVertexData;
942     else
943         return parentMesh->GetSubMesh(track->target-1)->vertexData;
944 }
945 
ConvertToAssimpAnimation()946 aiAnimation *Animation::ConvertToAssimpAnimation()
947 {
948     aiAnimation *anim = new aiAnimation();
949     anim->mName = name;
950     anim->mDuration = static_cast<double>(length);
951     anim->mTicksPerSecond = 1.0;
952 
953     // Tracks
954     if (!tracks.empty())
955     {
956         anim->mNumChannels = tracks.size();
957         anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
958 
959         for(size_t i=0, len=tracks.size(); i<len; ++i)
960         {
961             anim->mChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton);
962         }
963     }
964     return anim;
965 }
966 
967 // Skeleton
968 
Skeleton()969 Skeleton::Skeleton() :
970     bones(),
971     animations(),
972     blendMode(ANIMBLEND_AVERAGE)
973 {
974 }
975 
~Skeleton()976 Skeleton::~Skeleton()
977 {
978     Reset();
979 }
980 
Reset()981 void Skeleton::Reset()
982 {
983     for(size_t i=0, len=bones.size(); i<len; ++i) {
984         OGRE_SAFE_DELETE(bones[i])
985     }
986     bones.clear();
987     for(size_t i=0, len=animations.size(); i<len; ++i) {
988         OGRE_SAFE_DELETE(animations[i])
989     }
990     animations.clear();
991 }
992 
RootBones() const993 BoneList Skeleton::RootBones() const
994 {
995     BoneList rootBones;
996     for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
997     {
998         if (!(*iter)->IsParented())
999             rootBones.push_back((*iter));
1000     }
1001     return rootBones;
1002 }
1003 
NumRootBones() const1004 size_t Skeleton::NumRootBones() const
1005 {
1006     size_t num = 0;
1007     for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
1008     {
1009         if (!(*iter)->IsParented())
1010             num++;
1011     }
1012     return num;
1013 }
1014 
BoneByName(const std::string & name) const1015 Bone *Skeleton::BoneByName(const std::string &name) const
1016 {
1017     for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
1018     {
1019         if ((*iter)->name == name)
1020             return (*iter);
1021     }
1022     return 0;
1023 }
1024 
BoneById(uint16_t id) const1025 Bone *Skeleton::BoneById(uint16_t id) const
1026 {
1027     for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
1028     {
1029         if ((*iter)->id == id)
1030             return (*iter);
1031     }
1032     return 0;
1033 }
1034 
1035 // Bone
1036 
Bone()1037 Bone::Bone() :
1038     id(0),
1039     parent(0),
1040     parentId(-1),
1041     scale(1.0f, 1.0f, 1.0f)
1042 {
1043 }
1044 
IsParented() const1045 bool Bone::IsParented() const
1046 {
1047     return (parentId != -1 && parent != 0);
1048 }
1049 
ParentId() const1050 uint16_t Bone::ParentId() const
1051 {
1052     return static_cast<uint16_t>(parentId);
1053 }
1054 
AddChild(Bone * bone)1055 void Bone::AddChild(Bone *bone)
1056 {
1057     if (!bone)
1058         return;
1059     if (bone->IsParented())
1060         throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name);
1061 
1062     bone->parent = this;
1063     bone->parentId = id;
1064     children.push_back(bone->id);
1065 }
1066 
CalculateWorldMatrixAndDefaultPose(Skeleton * skeleton)1067 void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton)
1068 {
1069     if (!IsParented())
1070         worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse();
1071     else
1072         worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix;
1073 
1074     defaultPose = aiMatrix4x4(scale, rotation, position);
1075 
1076     // Recursively for all children now that the parent matrix has been calculated.
1077     for (size_t i=0, len=children.size(); i<len; ++i)
1078     {
1079         Bone *child = skeleton->BoneById(children[i]);
1080         if (!child) {
1081             throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
1082         }
1083         child->CalculateWorldMatrixAndDefaultPose(skeleton);
1084     }
1085 }
1086 
ConvertToAssimpNode(Skeleton * skeleton,aiNode * parentNode)1087 aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
1088 {
1089     // Bone node
1090     aiNode* node = new aiNode(name);
1091     node->mParent = parentNode;
1092     node->mTransformation = defaultPose;
1093 
1094     // Children
1095     if (!children.empty())
1096     {
1097         node->mNumChildren = children.size();
1098         node->mChildren = new aiNode*[node->mNumChildren];
1099 
1100         for(size_t i=0, len=children.size(); i<len; ++i)
1101         {
1102             Bone *child = skeleton->BoneById(children[i]);
1103             if (!child) {
1104                 throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
1105             }
1106             node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node);
1107         }
1108     }
1109     return node;
1110 }
1111 
ConvertToAssimpBone(Skeleton *,const std::vector<aiVertexWeight> & boneWeights)1112 aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights)
1113 {
1114     aiBone *bone = new aiBone();
1115     bone->mName = name;
1116     bone->mOffsetMatrix = worldMatrix;
1117 
1118     if (!boneWeights.empty())
1119     {
1120         bone->mNumWeights = boneWeights.size();
1121         bone->mWeights = new aiVertexWeight[boneWeights.size()];
1122         memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
1123     }
1124 
1125     return bone;
1126 }
1127 
1128 // VertexAnimationTrack
1129 
VertexAnimationTrack()1130 VertexAnimationTrack::VertexAnimationTrack() :
1131     type(VAT_NONE),
1132     target(0)
1133 {
1134 }
1135 
ConvertToAssimpAnimationNode(Skeleton * skeleton)1136 aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleton)
1137 {
1138     if (boneName.empty() || type != VAT_TRANSFORM) {
1139         throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM");
1140     }
1141 
1142     aiNodeAnim *nodeAnim = new aiNodeAnim();
1143     nodeAnim->mNodeName = boneName;
1144 
1145     Bone *bone = skeleton->BoneByName(boneName);
1146     if (!bone) {
1147         throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton");
1148     }
1149 
1150     // Keyframes
1151     size_t numKeyframes = transformKeyFrames.size();
1152 
1153     nodeAnim->mPositionKeys = new aiVectorKey[numKeyframes];
1154     nodeAnim->mRotationKeys = new aiQuatKey[numKeyframes];
1155     nodeAnim->mScalingKeys = new aiVectorKey[numKeyframes];
1156     nodeAnim->mNumPositionKeys = numKeyframes;
1157     nodeAnim->mNumRotationKeys = numKeyframes;
1158     nodeAnim->mNumScalingKeys  = numKeyframes;
1159 
1160     for(size_t kfi=0; kfi<numKeyframes; ++kfi)
1161     {
1162         TransformKeyFrame &kfSource = transformKeyFrames[kfi];
1163 
1164         // Calculate the complete transformation from world space to bone space
1165         aiVector3D pos; aiQuaternion rot; aiVector3D scale;
1166 
1167         aiMatrix4x4 finalTransform = bone->defaultPose * kfSource.Transform();
1168         finalTransform.Decompose(scale, rot, pos);
1169 
1170         double t = static_cast<double>(kfSource.timePos);
1171         nodeAnim->mPositionKeys[kfi].mTime = t;
1172         nodeAnim->mRotationKeys[kfi].mTime = t;
1173         nodeAnim->mScalingKeys[kfi].mTime = t;
1174 
1175         nodeAnim->mPositionKeys[kfi].mValue = pos;
1176         nodeAnim->mRotationKeys[kfi].mValue = rot;
1177         nodeAnim->mScalingKeys[kfi].mValue = scale;
1178     }
1179 
1180     return nodeAnim;
1181 }
1182 
1183 // TransformKeyFrame
1184 
TransformKeyFrame()1185 TransformKeyFrame::TransformKeyFrame() :
1186     timePos(0.0f),
1187     scale(1.0f, 1.0f, 1.0f)
1188 {
1189 }
1190 
Transform()1191 aiMatrix4x4 TransformKeyFrame::Transform()
1192 {
1193     return aiMatrix4x4(scale, rotation, position);
1194 }
1195 
1196 } // Ogre
1197 } // Assimp
1198 
1199 #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
1200