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