1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | |
39 | ---------------------------------------------------------------------- |
40 | */ |
41 | |
42 | #ifndef AI_OGRESTRUCTS_H_INC |
43 | #define AI_OGRESTRUCTS_H_INC |
44 | |
45 | #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER |
46 | |
47 | #include "MemoryIOWrapper.h" |
48 | #include <memory> |
49 | #include <assimp/mesh.h> |
50 | #include <map> |
51 | #include <vector> |
52 | #include <set> |
53 | |
54 | struct aiNodeAnim; |
55 | struct aiAnimation; |
56 | struct aiNode; |
57 | struct aiMaterial; |
58 | struct aiScene; |
59 | |
60 | /** @note Parts of this implementation, for example enums, deserialization constants and logic |
61 | has been copied directly with minor modifications from the MIT licensed Ogre3D code base. |
62 | See more from https://bitbucket.org/sinbad/ogre. */ |
63 | |
64 | namespace Assimp |
65 | { |
66 | namespace Ogre |
67 | { |
68 | |
69 | // Forward decl |
70 | class Mesh; |
71 | class MeshXml; |
72 | class SubMesh; |
73 | class SubMeshXml; |
74 | class Skeleton; |
75 | |
76 | #define OGRE_SAFE_DELETE(p) delete p; p=0; |
77 | |
78 | // Typedefs |
79 | typedef Assimp::MemoryIOStream MemoryStream; |
80 | typedef std::shared_ptr<MemoryStream> MemoryStreamPtr; |
81 | typedef std::map<uint16_t, MemoryStreamPtr> VertexBufferBindings; |
82 | |
83 | // Ogre Vertex Element |
84 | class VertexElement |
85 | { |
86 | public: |
87 | /// Vertex element semantics, used to identify the meaning of vertex buffer contents |
88 | enum Semantic { |
89 | /// Position, 3 reals per vertex |
90 | VES_POSITION = 1, |
91 | /// Blending weights |
92 | VES_BLEND_WEIGHTS = 2, |
93 | /// Blending indices |
94 | VES_BLEND_INDICES = 3, |
95 | /// Normal, 3 reals per vertex |
96 | VES_NORMAL = 4, |
97 | /// Diffuse colours |
98 | VES_DIFFUSE = 5, |
99 | /// Specular colours |
100 | VES_SPECULAR = 6, |
101 | /// Texture coordinates |
102 | VES_TEXTURE_COORDINATES = 7, |
103 | /// Binormal (Y axis if normal is Z) |
104 | VES_BINORMAL = 8, |
105 | /// Tangent (X axis if normal is Z) |
106 | VES_TANGENT = 9, |
107 | /// The number of VertexElementSemantic elements (note - the first value VES_POSITION is 1) |
108 | VES_COUNT = 9 |
109 | }; |
110 | |
111 | /// Vertex element type, used to identify the base types of the vertex contents |
112 | enum Type |
113 | { |
114 | VET_FLOAT1 = 0, |
115 | VET_FLOAT2 = 1, |
116 | VET_FLOAT3 = 2, |
117 | VET_FLOAT4 = 3, |
118 | /// alias to more specific colour type - use the current rendersystem's colour packing |
119 | VET_COLOUR = 4, |
120 | VET_SHORT1 = 5, |
121 | VET_SHORT2 = 6, |
122 | VET_SHORT3 = 7, |
123 | VET_SHORT4 = 8, |
124 | VET_UBYTE4 = 9, |
125 | /// D3D style compact colour |
126 | VET_COLOUR_ARGB = 10, |
127 | /// GL style compact colour |
128 | VET_COLOUR_ABGR = 11, |
129 | VET_DOUBLE1 = 12, |
130 | VET_DOUBLE2 = 13, |
131 | VET_DOUBLE3 = 14, |
132 | VET_DOUBLE4 = 15, |
133 | VET_USHORT1 = 16, |
134 | VET_USHORT2 = 17, |
135 | VET_USHORT3 = 18, |
136 | VET_USHORT4 = 19, |
137 | VET_INT1 = 20, |
138 | VET_INT2 = 21, |
139 | VET_INT3 = 22, |
140 | VET_INT4 = 23, |
141 | VET_UINT1 = 24, |
142 | VET_UINT2 = 25, |
143 | VET_UINT3 = 26, |
144 | VET_UINT4 = 27 |
145 | }; |
146 | |
147 | VertexElement(); |
148 | |
149 | /// Size of the vertex element in bytes. |
150 | size_t Size() const; |
151 | |
152 | /// Count of components in this element, eg. VET_FLOAT3 return 3. |
153 | size_t ComponentCount() const; |
154 | |
155 | /// Type as string. |
156 | std::string TypeToString(); |
157 | |
158 | /// Semantic as string. |
159 | std::string SemanticToString(); |
160 | |
161 | static size_t TypeSize(Type type); |
162 | static size_t ComponentCount(Type type); |
163 | static std::string TypeToString(Type type); |
164 | static std::string SemanticToString(Semantic semantic); |
165 | |
166 | uint16_t index; |
167 | uint16_t source; |
168 | uint16_t offset; |
169 | Type type; |
170 | Semantic semantic; |
171 | }; |
172 | typedef std::vector<VertexElement> VertexElementList; |
173 | |
174 | /// Ogre Vertex Bone Assignment |
175 | struct VertexBoneAssignment |
176 | { |
177 | uint32_t vertexIndex; |
178 | uint16_t boneIndex; |
179 | float weight; |
180 | }; |
181 | typedef std::vector<VertexBoneAssignment> VertexBoneAssignmentList; |
182 | typedef std::map<uint32_t, VertexBoneAssignmentList > VertexBoneAssignmentsMap; |
183 | typedef std::map<uint16_t, std::vector<aiVertexWeight> > AssimpVertexBoneWeightList; |
184 | |
185 | // Ogre Vertex Data interface, inherited by the binary and XML implementations. |
186 | class IVertexData |
187 | { |
188 | public: |
189 | IVertexData(); |
190 | |
191 | /// Returns if bone assignments are available. |
192 | bool HasBoneAssignments() const; |
193 | |
194 | /// Add vertex mapping from old to new index. |
195 | void AddVertexMapping(uint32_t oldIndex, uint32_t newIndex); |
196 | |
197 | /// Returns re-mapped bone assignments. |
198 | /** @note Uses mappings added via AddVertexMapping. */ |
199 | AssimpVertexBoneWeightList AssimpBoneWeights(size_t vertices); |
200 | |
201 | /// Returns a set of bone indexes that are referenced by bone assignments (weights). |
202 | std::set<uint16_t> ReferencedBonesByWeights() const; |
203 | |
204 | /// Vertex count. |
205 | uint32_t count; |
206 | |
207 | /// Bone assignments. |
208 | VertexBoneAssignmentList boneAssignments; |
209 | |
210 | private: |
211 | void BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const; |
212 | |
213 | std::map<uint32_t, std::vector<uint32_t> > vertexIndexMapping; |
214 | VertexBoneAssignmentsMap boneAssignmentsMap; |
215 | }; |
216 | |
217 | // Ogre Vertex Data |
218 | class VertexData : public IVertexData |
219 | { |
220 | public: |
221 | VertexData(); |
222 | ~VertexData(); |
223 | |
224 | /// Releases all memory that this data structure owns. |
225 | void Reset(); |
226 | |
227 | /// Get vertex size for @c source. |
228 | uint32_t VertexSize(uint16_t source) const; |
229 | |
230 | /// Get vertex buffer for @c source. |
231 | MemoryStream *VertexBuffer(uint16_t source); |
232 | |
233 | /// Get vertex element for @c semantic for @c index. |
234 | VertexElement *GetVertexElement(VertexElement::Semantic semantic, uint16_t index = 0); |
235 | |
236 | /// Vertex elements. |
237 | VertexElementList vertexElements; |
238 | |
239 | /// Vertex buffers mapped to bind index. |
240 | VertexBufferBindings vertexBindings; |
241 | }; |
242 | |
243 | // Ogre Index Data |
244 | class IndexData |
245 | { |
246 | public: |
247 | IndexData(); |
248 | ~IndexData(); |
249 | |
250 | /// Releases all memory that this data structure owns. |
251 | void Reset(); |
252 | |
253 | /// Index size in bytes. |
254 | size_t IndexSize() const; |
255 | |
256 | /// Face size in bytes. |
257 | size_t FaceSize() const; |
258 | |
259 | /// Index count. |
260 | uint32_t count; |
261 | |
262 | /// Face count. |
263 | uint32_t faceCount; |
264 | |
265 | /// If has 32-bit indexes. |
266 | bool is32bit; |
267 | |
268 | /// Index buffer. |
269 | MemoryStreamPtr buffer; |
270 | }; |
271 | |
272 | /// Ogre Pose |
273 | class Pose |
274 | { |
275 | public: |
276 | struct Vertex |
277 | { |
278 | uint32_t index; |
279 | aiVector3D offset; |
280 | aiVector3D normal; |
281 | }; |
282 | typedef std::map<uint32_t, Vertex> PoseVertexMap; |
283 | |
284 | Pose() : target(0), hasNormals(false) {} |
285 | |
286 | /// Name. |
287 | std::string name; |
288 | |
289 | /// Target. |
290 | uint16_t target; |
291 | |
292 | /// Does vertices map have normals. |
293 | bool hasNormals; |
294 | |
295 | /// Vertex offset and normals. |
296 | PoseVertexMap vertices; |
297 | }; |
298 | typedef std::vector<Pose*> PoseList; |
299 | |
300 | /// Ogre Pose Key Frame Ref |
301 | struct PoseRef |
302 | { |
303 | uint16_t index; |
304 | float influence; |
305 | }; |
306 | typedef std::vector<PoseRef> PoseRefList; |
307 | |
308 | /// Ogre Pose Key Frame |
309 | struct PoseKeyFrame |
310 | { |
311 | /// Time position in the animation. |
312 | float timePos; |
313 | |
314 | PoseRefList references; |
315 | }; |
316 | typedef std::vector<PoseKeyFrame> PoseKeyFrameList; |
317 | |
318 | /// Ogre Morph Key Frame |
319 | struct MorphKeyFrame |
320 | { |
321 | /// Time position in the animation. |
322 | float timePos; |
323 | |
324 | MemoryStreamPtr buffer; |
325 | }; |
326 | typedef std::vector<MorphKeyFrame> MorphKeyFrameList; |
327 | |
328 | /// Ogre animation key frame |
329 | struct TransformKeyFrame |
330 | { |
331 | TransformKeyFrame(); |
332 | |
333 | aiMatrix4x4 Transform(); |
334 | |
335 | float timePos; |
336 | |
337 | aiQuaternion rotation; |
338 | aiVector3D position; |
339 | aiVector3D scale; |
340 | }; |
341 | typedef std::vector<TransformKeyFrame> TransformKeyFrameList; |
342 | |
343 | /// Ogre Animation Track |
344 | struct VertexAnimationTrack |
345 | { |
346 | enum Type |
347 | { |
348 | /// No animation |
349 | VAT_NONE = 0, |
350 | /// Morph animation is made up of many interpolated snapshot keyframes |
351 | VAT_MORPH = 1, |
352 | /// Pose animation is made up of a single delta pose keyframe |
353 | VAT_POSE = 2, |
354 | /// Keyframe that has its on pos, rot and scale for a time position |
355 | VAT_TRANSFORM = 3 |
356 | }; |
357 | |
358 | VertexAnimationTrack(); |
359 | |
360 | /// Convert to Assimp node animation. |
361 | aiNodeAnim *ConvertToAssimpAnimationNode(Skeleton *skeleton); |
362 | |
363 | // Animation type. |
364 | Type type; |
365 | |
366 | /// Vertex data target. |
367 | /** 0 == shared geometry |
368 | >0 == submesh index + 1 */ |
369 | uint16_t target; |
370 | |
371 | /// Only valid for VAT_TRANSFORM. |
372 | std::string boneName; |
373 | |
374 | /// Only one of these will contain key frames, depending on the type enum. |
375 | PoseKeyFrameList poseKeyFrames; |
376 | MorphKeyFrameList morphKeyFrames; |
377 | TransformKeyFrameList transformKeyFrames; |
378 | }; |
379 | typedef std::vector<VertexAnimationTrack> VertexAnimationTrackList; |
380 | |
381 | /// Ogre Animation |
382 | class Animation |
383 | { |
384 | public: |
385 | explicit Animation(Skeleton *parent); |
386 | explicit Animation(Mesh *parent); |
387 | |
388 | /// Returns the associated vertex data for a track in this animation. |
389 | /** @note Only valid to call when parent Mesh is set. */ |
390 | VertexData *AssociatedVertexData(VertexAnimationTrack *track) const; |
391 | |
392 | /// Convert to Assimp animation. |
393 | aiAnimation *ConvertToAssimpAnimation(); |
394 | |
395 | /// Parent mesh. |
396 | /** @note Set only when animation is read from a mesh. */ |
397 | Mesh *parentMesh; |
398 | |
399 | /// Parent skeleton. |
400 | /** @note Set only when animation is read from a skeleton. */ |
401 | Skeleton *parentSkeleton; |
402 | |
403 | /// Animation name. |
404 | std::string name; |
405 | |
406 | /// Base animation name. |
407 | std::string baseName; |
408 | |
409 | /// Length in seconds. |
410 | float length; |
411 | |
412 | /// Base animation key time. |
413 | float baseTime; |
414 | |
415 | /// Animation tracks. |
416 | VertexAnimationTrackList tracks; |
417 | }; |
418 | typedef std::vector<Animation*> AnimationList; |
419 | |
420 | /// Ogre Bone |
421 | class Bone |
422 | { |
423 | public: |
424 | Bone(); |
425 | |
426 | /// Returns if this bone is parented. |
427 | bool IsParented() const; |
428 | |
429 | /// Parent index as uint16_t. Internally int32_t as -1 means unparented. |
430 | uint16_t ParentId() const; |
431 | |
432 | /// Add child bone. |
433 | void AddChild(Bone *bone); |
434 | |
435 | /// Calculates the world matrix for bone and its children. |
436 | void CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton); |
437 | |
438 | /// Convert to Assimp node (animation nodes). |
439 | aiNode *ConvertToAssimpNode(Skeleton *parent, aiNode *parentNode = 0); |
440 | |
441 | /// Convert to Assimp bone (mesh bones). |
442 | aiBone *ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights); |
443 | |
444 | uint16_t id; |
445 | std::string name; |
446 | |
447 | Bone *parent; |
448 | int32_t parentId; |
449 | std::vector<uint16_t> children; |
450 | |
451 | aiVector3D position; |
452 | aiQuaternion rotation; |
453 | aiVector3D scale; |
454 | |
455 | aiMatrix4x4 worldMatrix; |
456 | aiMatrix4x4 defaultPose; |
457 | }; |
458 | typedef std::vector<Bone*> BoneList; |
459 | |
460 | /// Ogre Skeleton |
461 | class Skeleton |
462 | { |
463 | public: |
464 | enum BlendMode |
465 | { |
466 | /// Animations are applied by calculating a weighted average of all animations |
467 | ANIMBLEND_AVERAGE = 0, |
468 | /// Animations are applied by calculating a weighted cumulative total |
469 | ANIMBLEND_CUMULATIVE = 1 |
470 | }; |
471 | |
472 | Skeleton(); |
473 | ~Skeleton(); |
474 | |
475 | /// Releases all memory that this data structure owns. |
476 | void Reset(); |
477 | |
478 | /// Returns unparented root bones. |
479 | BoneList RootBones() const; |
480 | |
481 | /// Returns number of unparented root bones. |
482 | size_t NumRootBones() const; |
483 | |
484 | /// Get bone by name. |
485 | Bone *BoneByName(const std::string &name) const; |
486 | |
487 | /// Get bone by id. |
488 | Bone *BoneById(uint16_t id) const; |
489 | |
490 | BoneList bones; |
491 | AnimationList animations; |
492 | |
493 | /// @todo Take blend mode into account, but where? |
494 | BlendMode blendMode; |
495 | }; |
496 | |
497 | /// Ogre Sub Mesh interface, inherited by the binary and XML implementations. |
498 | class ISubMesh |
499 | { |
500 | public: |
501 | /// @note Full list of Ogre types, not all of them are supported and exposed to Assimp. |
502 | enum OperationType |
503 | { |
504 | /// A list of points, 1 vertex per point |
505 | OT_POINT_LIST = 1, |
506 | /// A list of lines, 2 vertices per line |
507 | OT_LINE_LIST = 2, |
508 | /// A strip of connected lines, 1 vertex per line plus 1 start vertex |
509 | OT_LINE_STRIP = 3, |
510 | /// A list of triangles, 3 vertices per triangle |
511 | OT_TRIANGLE_LIST = 4, |
512 | /// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that |
513 | OT_TRIANGLE_STRIP = 5, |
514 | /// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that |
515 | OT_TRIANGLE_FAN = 6 |
516 | }; |
517 | |
518 | ISubMesh(); |
519 | |
520 | /// SubMesh index. |
521 | unsigned int index; |
522 | |
523 | /// SubMesh name. |
524 | std::string name; |
525 | |
526 | /// Material used by this submesh. |
527 | std::string materialRef; |
528 | |
529 | /// Texture alias information. |
530 | std::string textureAliasName; |
531 | std::string textureAliasRef; |
532 | |
533 | /// Assimp scene material index used by this submesh. |
534 | /** -1 if no material or material could not be imported. */ |
535 | int materialIndex; |
536 | |
537 | /// If submesh uses shared geometry from parent mesh. |
538 | bool usesSharedVertexData; |
539 | |
540 | /// Operation type. |
541 | OperationType operationType; |
542 | }; |
543 | |
544 | /// Ogre SubMesh |
545 | class SubMesh : public ISubMesh |
546 | { |
547 | public: |
548 | SubMesh(); |
549 | ~SubMesh(); |
550 | |
551 | /// Releases all memory that this data structure owns. |
552 | /** @note Vertex and index data contains shared ptrs |
553 | that are freed automatically. In practice the ref count |
554 | should be 0 after this reset. */ |
555 | void Reset(); |
556 | |
557 | /// Covert to Assimp mesh. |
558 | aiMesh *ConvertToAssimpMesh(Mesh *parent); |
559 | |
560 | /// Vertex data. |
561 | VertexData *vertexData; |
562 | |
563 | /// Index data. |
564 | IndexData *indexData; |
565 | }; |
566 | typedef std::vector<SubMesh*> SubMeshList; |
567 | |
568 | /// Ogre Mesh |
569 | class Mesh |
570 | { |
571 | public: |
572 | /// Constructor. |
573 | Mesh(); |
574 | |
575 | /// Destructor. |
576 | ~Mesh(); |
577 | |
578 | /// Releases all memory that this data structure owns. |
579 | void Reset(); |
580 | |
581 | /// Returns number of subMeshes. |
582 | size_t NumSubMeshes() const; |
583 | |
584 | /// Returns submesh for @c index. |
585 | SubMesh *GetSubMesh( size_t index) const; |
586 | |
587 | /// Convert mesh to Assimp scene. |
588 | void ConvertToAssimpScene(aiScene* dest); |
589 | |
590 | /// Mesh has skeletal animations. |
591 | bool hasSkeletalAnimations; |
592 | |
593 | /// Skeleton reference. |
594 | std::string skeletonRef; |
595 | |
596 | /// Skeleton. |
597 | Skeleton *skeleton; |
598 | |
599 | /// Vertex data |
600 | VertexData *sharedVertexData; |
601 | |
602 | /// Sub meshes. |
603 | SubMeshList subMeshes; |
604 | |
605 | /// Animations |
606 | AnimationList animations; |
607 | |
608 | /// Poses |
609 | PoseList poses; |
610 | }; |
611 | |
612 | /// Ogre XML Vertex Data |
613 | class VertexDataXml : public IVertexData |
614 | { |
615 | public: |
616 | VertexDataXml(); |
617 | |
618 | bool HasPositions() const; |
619 | bool HasNormals() const; |
620 | bool HasTangents() const; |
621 | bool HasUvs() const; |
622 | size_t NumUvs() const; |
623 | |
624 | std::vector<aiVector3D> positions; |
625 | std::vector<aiVector3D> normals; |
626 | std::vector<aiVector3D> tangents; |
627 | std::vector<std::vector<aiVector3D> > uvs; |
628 | }; |
629 | |
630 | /// Ogre XML Index Data |
631 | class IndexDataXml |
632 | { |
633 | public: |
634 | IndexDataXml() : faceCount(0) {} |
635 | |
636 | /// Face count. |
637 | uint32_t faceCount; |
638 | |
639 | std::vector<aiFace> faces; |
640 | }; |
641 | |
642 | /// Ogre XML SubMesh |
643 | class SubMeshXml : public ISubMesh |
644 | { |
645 | public: |
646 | SubMeshXml(); |
647 | ~SubMeshXml(); |
648 | |
649 | /// Releases all memory that this data structure owns. |
650 | void Reset(); |
651 | |
652 | aiMesh *ConvertToAssimpMesh(MeshXml *parent); |
653 | |
654 | IndexDataXml *indexData; |
655 | VertexDataXml *vertexData; |
656 | }; |
657 | typedef std::vector<SubMeshXml*> SubMeshXmlList; |
658 | |
659 | /// Ogre XML Mesh |
660 | class MeshXml |
661 | { |
662 | public: |
663 | MeshXml(); |
664 | ~MeshXml(); |
665 | |
666 | /// Releases all memory that this data structure owns. |
667 | void Reset(); |
668 | |
669 | /// Returns number of subMeshes. |
670 | size_t NumSubMeshes() const; |
671 | |
672 | /// Returns submesh for @c index. |
673 | SubMeshXml *GetSubMesh(uint16_t index) const; |
674 | |
675 | /// Convert mesh to Assimp scene. |
676 | void ConvertToAssimpScene(aiScene* dest); |
677 | |
678 | /// Skeleton reference. |
679 | std::string skeletonRef; |
680 | |
681 | /// Skeleton. |
682 | Skeleton *skeleton; |
683 | |
684 | /// Vertex data |
685 | VertexDataXml *sharedVertexData; |
686 | |
687 | /// Sub meshes. |
688 | SubMeshXmlList subMeshes; |
689 | }; |
690 | |
691 | } // Ogre |
692 | } // Assimp |
693 | |
694 | #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER |
695 | #endif // AI_OGRESTRUCTS_H_INC |
696 | |