1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4 
5 Copyright (c) 2006-2019, assimp team
6 
7 
8 All rights reserved.
9 
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the
12 following conditions are met:
13 
14 * Redistributions of source code must retain the above
15   copyright notice, this list of conditions and the
16   following disclaimer.
17 
18 * Redistributions in binary form must reproduce the above
19   copyright notice, this list of conditions and the
20   following disclaimer in the documentation and/or other
21   materials provided with the distribution.
22 
23 * Neither the name of the assimp team, nor the names of its
24   contributors may be used to endorse or promote products
25   derived from this software without specific prior
26   written permission of the assimp team.
27 
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 
40 ----------------------------------------------------------------------
41 */
42 
43 /** @file  FBXDocument.h
44  *  @brief FBX DOM
45  */
46 #ifndef INCLUDED_AI_FBX_DOCUMENT_H
47 #define INCLUDED_AI_FBX_DOCUMENT_H
48 
49 #include <numeric>
50 #include <stdint.h>
51 #include <assimp/mesh.h>
52 #include "FBXProperties.h"
53 #include "FBXParser.h"
54 
55 #define _AI_CONCAT(a,b)  a ## b
56 #define  AI_CONCAT(a,b)  _AI_CONCAT(a,b)
57 
58 namespace Assimp {
59 namespace FBX {
60 
61 class Parser;
62 class Object;
63 struct ImportSettings;
64 
65 class PropertyTable;
66 class Document;
67 class Material;
68 class ShapeGeometry;
69 class LineGeometry;
70 class Geometry;
71 
72 class Video;
73 
74 class AnimationCurve;
75 class AnimationCurveNode;
76 class AnimationLayer;
77 class AnimationStack;
78 
79 class BlendShapeChannel;
80 class BlendShape;
81 class Skin;
82 class Cluster;
83 
84 
85 /** Represents a delay-parsed FBX objects. Many objects in the scene
86  *  are not needed by assimp, so it makes no sense to parse them
87  *  upfront. */
88 class LazyObject {
89 public:
90     LazyObject(uint64_t id, const Element& element, const Document& doc);
91 
92     ~LazyObject();
93 
94     const Object* Get(bool dieOnError = false);
95 
96     template <typename T>
97     const T* Get(bool dieOnError = false) {
98         const Object* const ob = Get(dieOnError);
99         return ob ? dynamic_cast<const T*>(ob) : NULL;
100     }
101 
ID()102     uint64_t ID() const {
103         return id;
104     }
105 
IsBeingConstructed()106     bool IsBeingConstructed() const {
107         return (flags & BEING_CONSTRUCTED) != 0;
108     }
109 
FailedToConstruct()110     bool FailedToConstruct() const {
111         return (flags & FAILED_TO_CONSTRUCT) != 0;
112     }
113 
GetElement()114     const Element& GetElement() const {
115         return element;
116     }
117 
GetDocument()118     const Document& GetDocument() const {
119         return doc;
120     }
121 
122 private:
123     const Document& doc;
124     const Element& element;
125     std::unique_ptr<const Object> object;
126 
127     const uint64_t id;
128 
129     enum Flags {
130         BEING_CONSTRUCTED = 0x1,
131         FAILED_TO_CONSTRUCT = 0x2
132     };
133 
134     unsigned int flags;
135 };
136 
137 /** Base class for in-memory (DOM) representations of FBX objects */
138 class Object {
139 public:
140     Object(uint64_t id, const Element& element, const std::string& name);
141 
142     virtual ~Object();
143 
SourceElement()144     const Element& SourceElement() const {
145         return element;
146     }
147 
Name()148     const std::string& Name() const {
149         return name;
150     }
151 
ID()152     uint64_t ID() const {
153         return id;
154     }
155 
156 protected:
157     const Element& element;
158     const std::string name;
159     const uint64_t id;
160 };
161 
162 /** DOM class for generic FBX NoteAttribute blocks. NoteAttribute's just hold a property table,
163  *  fixed members are added by deriving classes. */
164 class NodeAttribute : public Object {
165 public:
166     NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
167 
168     virtual ~NodeAttribute();
169 
Props()170     const PropertyTable& Props() const {
171         ai_assert(props.get());
172         return *props.get();
173     }
174 
175 private:
176     std::shared_ptr<const PropertyTable> props;
177 };
178 
179 /** DOM base class for FBX camera settings attached to a node */
180 class CameraSwitcher : public NodeAttribute {
181 public:
182     CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
183 
184     virtual ~CameraSwitcher();
185 
CameraID()186     int CameraID() const {
187         return cameraId;
188     }
189 
CameraName()190     const std::string& CameraName() const {
191         return cameraName;
192     }
193 
CameraIndexName()194     const std::string& CameraIndexName() const {
195         return cameraIndexName;
196     }
197 
198 private:
199     int cameraId;
200     std::string cameraName;
201     std::string cameraIndexName;
202 };
203 
204 #define fbx_stringize(a) #a
205 
206 #define fbx_simple_property(name, type, default_value) \
207     type name() const { \
208         return PropertyGet<type>(Props(), fbx_stringize(name), (default_value)); \
209     }
210 
211 // XXX improve logging
212 #define fbx_simple_enum_property(name, type, default_value) \
213     type name() const { \
214         const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
215         if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
216             ai_assert(static_cast<int>(default_value) >= 0 && static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
217             return static_cast<type>(default_value); \
218         } \
219         return static_cast<type>(ival); \
220 }
221 
222 
223 /** DOM base class for FBX cameras attached to a node */
224 class Camera : public NodeAttribute {
225 public:
226     Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
227 
228     virtual  ~Camera();
229 
230     fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
231     fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
232     fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0))
233 
234     fbx_simple_property(AspectWidth, float, 1.0f)
235     fbx_simple_property(AspectHeight, float, 1.0f)
236     fbx_simple_property(FilmWidth, float, 1.0f)
237     fbx_simple_property(FilmHeight, float, 1.0f)
238 
239     fbx_simple_property(NearPlane, float, 0.1f)
240     fbx_simple_property(FarPlane, float, 100.0f)
241 
242     fbx_simple_property(FilmAspectRatio, float, 1.0f)
243     fbx_simple_property(ApertureMode, int, 0)
244 
245     fbx_simple_property(FieldOfView, float, 1.0f)
246     fbx_simple_property(FocalLength, float, 1.0f)
247 };
248 
249 /** DOM base class for FBX null markers attached to a node */
250 class Null : public NodeAttribute {
251 public:
252     Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
253     virtual ~Null();
254 };
255 
256 /** DOM base class for FBX limb node markers attached to a node */
257 class LimbNode : public NodeAttribute {
258 public:
259     LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
260     virtual ~LimbNode();
261 };
262 
263 /** DOM base class for FBX lights attached to a node */
264 class Light : public NodeAttribute {
265 public:
266     Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
267     virtual ~Light();
268 
269     enum Type
270     {
271         Type_Point,
272         Type_Directional,
273         Type_Spot,
274         Type_Area,
275         Type_Volume,
276 
277         Type_MAX // end-of-enum sentinel
278     };
279 
280     enum Decay
281     {
282         Decay_None,
283         Decay_Linear,
284         Decay_Quadratic,
285         Decay_Cubic,
286 
287         Decay_MAX // end-of-enum sentinel
288     };
289 
290     fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1))
291     fbx_simple_enum_property(LightType, Type, 0)
292     fbx_simple_property(CastLightOnObject, bool, false)
293     fbx_simple_property(DrawVolumetricLight, bool, true)
294     fbx_simple_property(DrawGroundProjection, bool, true)
295     fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false)
296     fbx_simple_property(Intensity, float, 100.0f)
297     fbx_simple_property(InnerAngle, float, 0.0f)
298     fbx_simple_property(OuterAngle, float, 45.0f)
299     fbx_simple_property(Fog, int, 50)
300     fbx_simple_enum_property(DecayType, Decay, 2)
301     fbx_simple_property(DecayStart, float, 1.0f)
302     fbx_simple_property(FileName, std::string, "")
303 
304     fbx_simple_property(EnableNearAttenuation, bool, false)
305     fbx_simple_property(NearAttenuationStart, float, 0.0f)
306     fbx_simple_property(NearAttenuationEnd, float, 0.0f)
307     fbx_simple_property(EnableFarAttenuation, bool, false)
308     fbx_simple_property(FarAttenuationStart, float, 0.0f)
309     fbx_simple_property(FarAttenuationEnd, float, 0.0f)
310 
311     fbx_simple_property(CastShadows, bool, true)
312     fbx_simple_property(ShadowColor, aiVector3D, aiVector3D(0,0,0))
313 
314     fbx_simple_property(AreaLightShape, int, 0)
315 
316     fbx_simple_property(LeftBarnDoor, float, 20.0f)
317     fbx_simple_property(RightBarnDoor, float, 20.0f)
318     fbx_simple_property(TopBarnDoor, float, 20.0f)
319     fbx_simple_property(BottomBarnDoor, float, 20.0f)
320     fbx_simple_property(EnableBarnDoor, bool, true)
321 };
322 
323 /** DOM base class for FBX models (even though its semantics are more "node" than "model" */
324 class Model : public Object {
325 public:
326     enum RotOrder {
327         RotOrder_EulerXYZ = 0,
328         RotOrder_EulerXZY,
329         RotOrder_EulerYZX,
330         RotOrder_EulerYXZ,
331         RotOrder_EulerZXY,
332         RotOrder_EulerZYX,
333 
334         RotOrder_SphericXYZ,
335 
336         RotOrder_MAX // end-of-enum sentinel
337     };
338 
339     enum TransformInheritance {
340         TransformInheritance_RrSs = 0,
341         TransformInheritance_RSrs,
342         TransformInheritance_Rrs,
343 
344         TransformInheritance_MAX // end-of-enum sentinel
345     };
346 
347     Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
348 
349     virtual ~Model();
350 
351     fbx_simple_property(QuaternionInterpolate, int, 0)
352 
fbx_simple_property(RotationOffset,aiVector3D,aiVector3D ())353     fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
354     fbx_simple_property(RotationPivot, aiVector3D, aiVector3D())
355     fbx_simple_property(ScalingOffset, aiVector3D, aiVector3D())
356     fbx_simple_property(ScalingPivot, aiVector3D, aiVector3D())
357     fbx_simple_property(TranslationActive, bool, false)
358 
359     fbx_simple_property(TranslationMin, aiVector3D, aiVector3D())
360     fbx_simple_property(TranslationMax, aiVector3D, aiVector3D())
361 
362     fbx_simple_property(TranslationMinX, bool, false)
363     fbx_simple_property(TranslationMaxX, bool, false)
364     fbx_simple_property(TranslationMinY, bool, false)
365     fbx_simple_property(TranslationMaxY, bool, false)
366     fbx_simple_property(TranslationMinZ, bool, false)
367     fbx_simple_property(TranslationMaxZ, bool, false)
368 
369     fbx_simple_enum_property(RotationOrder, RotOrder, 0)
370     fbx_simple_property(RotationSpaceForLimitOnly, bool, false)
371     fbx_simple_property(RotationStiffnessX, float, 0.0f)
372     fbx_simple_property(RotationStiffnessY, float, 0.0f)
373     fbx_simple_property(RotationStiffnessZ, float, 0.0f)
374     fbx_simple_property(AxisLen, float, 0.0f)
375 
376     fbx_simple_property(PreRotation, aiVector3D, aiVector3D())
377     fbx_simple_property(PostRotation, aiVector3D, aiVector3D())
378     fbx_simple_property(RotationActive, bool, false)
379 
380     fbx_simple_property(RotationMin, aiVector3D, aiVector3D())
381     fbx_simple_property(RotationMax, aiVector3D, aiVector3D())
382 
383     fbx_simple_property(RotationMinX, bool, false)
384     fbx_simple_property(RotationMaxX, bool, false)
385     fbx_simple_property(RotationMinY, bool, false)
386     fbx_simple_property(RotationMaxY, bool, false)
387     fbx_simple_property(RotationMinZ, bool, false)
388     fbx_simple_property(RotationMaxZ, bool, false)
389     fbx_simple_enum_property(InheritType, TransformInheritance, 0)
390 
391     fbx_simple_property(ScalingActive, bool, false)
392     fbx_simple_property(ScalingMin, aiVector3D, aiVector3D())
393     fbx_simple_property(ScalingMax, aiVector3D, aiVector3D(1.f,1.f,1.f))
394     fbx_simple_property(ScalingMinX, bool, false)
395     fbx_simple_property(ScalingMaxX, bool, false)
396     fbx_simple_property(ScalingMinY, bool, false)
397     fbx_simple_property(ScalingMaxY, bool, false)
398     fbx_simple_property(ScalingMinZ, bool, false)
399     fbx_simple_property(ScalingMaxZ, bool, false)
400 
401     fbx_simple_property(GeometricTranslation, aiVector3D, aiVector3D())
402     fbx_simple_property(GeometricRotation, aiVector3D, aiVector3D())
403     fbx_simple_property(GeometricScaling, aiVector3D, aiVector3D(1.f, 1.f, 1.f))
404 
405     fbx_simple_property(MinDampRangeX, float, 0.0f)
406     fbx_simple_property(MinDampRangeY, float, 0.0f)
407     fbx_simple_property(MinDampRangeZ, float, 0.0f)
408     fbx_simple_property(MaxDampRangeX, float, 0.0f)
409     fbx_simple_property(MaxDampRangeY, float, 0.0f)
410     fbx_simple_property(MaxDampRangeZ, float, 0.0f)
411 
412     fbx_simple_property(MinDampStrengthX, float, 0.0f)
413     fbx_simple_property(MinDampStrengthY, float, 0.0f)
414     fbx_simple_property(MinDampStrengthZ, float, 0.0f)
415     fbx_simple_property(MaxDampStrengthX, float, 0.0f)
416     fbx_simple_property(MaxDampStrengthY, float, 0.0f)
417     fbx_simple_property(MaxDampStrengthZ, float, 0.0f)
418 
419     fbx_simple_property(PreferredAngleX, float, 0.0f)
420     fbx_simple_property(PreferredAngleY, float, 0.0f)
421     fbx_simple_property(PreferredAngleZ, float, 0.0f)
422 
423     fbx_simple_property(Show, bool, true)
424     fbx_simple_property(LODBox, bool, false)
425     fbx_simple_property(Freeze, bool, false)
426 
427     const std::string& Shading() const {
428         return shading;
429     }
430 
Culling()431     const std::string& Culling() const {
432         return culling;
433     }
434 
Props()435     const PropertyTable& Props() const {
436         ai_assert(props.get());
437         return *props.get();
438     }
439 
440     /** Get material links */
GetMaterials()441     const std::vector<const Material*>& GetMaterials() const {
442         return materials;
443     }
444 
445     /** Get geometry links */
GetGeometry()446     const std::vector<const Geometry*>& GetGeometry() const {
447         return geometry;
448     }
449 
450     /** Get node attachments */
GetAttributes()451     const std::vector<const NodeAttribute*>& GetAttributes() const {
452         return attributes;
453     }
454 
455     /** convenience method to check if the node has a Null node marker */
456     bool IsNull() const;
457 
458 private:
459     void ResolveLinks(const Element& element, const Document& doc);
460 
461 private:
462     std::vector<const Material*> materials;
463     std::vector<const Geometry*> geometry;
464     std::vector<const NodeAttribute*> attributes;
465 
466     std::string shading;
467     std::string culling;
468     std::shared_ptr<const PropertyTable> props;
469 };
470 
471 /** DOM class for generic FBX textures */
472 class Texture : public Object {
473 public:
474     Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
475 
476     virtual ~Texture();
477 
Type()478     const std::string& Type() const {
479         return type;
480     }
481 
FileName()482     const std::string& FileName() const {
483         return fileName;
484     }
485 
RelativeFilename()486     const std::string& RelativeFilename() const {
487         return relativeFileName;
488     }
489 
AlphaSource()490     const std::string& AlphaSource() const {
491         return alphaSource;
492     }
493 
UVTranslation()494     const aiVector2D& UVTranslation() const {
495         return uvTrans;
496     }
497 
UVScaling()498     const aiVector2D& UVScaling() const {
499         return uvScaling;
500     }
501 
Props()502     const PropertyTable& Props() const {
503         ai_assert(props.get());
504         return *props.get();
505     }
506 
507     // return a 4-tuple
Crop()508     const unsigned int* Crop() const {
509         return crop;
510     }
511 
Media()512     const Video* Media() const {
513         return media;
514     }
515 
516 private:
517     aiVector2D uvTrans;
518     aiVector2D uvScaling;
519 
520     std::string type;
521     std::string relativeFileName;
522     std::string fileName;
523     std::string alphaSource;
524     std::shared_ptr<const PropertyTable> props;
525 
526     unsigned int crop[4];
527 
528     const Video* media;
529 };
530 
531 /** DOM class for layered FBX textures */
532 class LayeredTexture : public Object {
533 public:
534     LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
535     virtual ~LayeredTexture();
536 
537     // Can only be called after construction of the layered texture object due to construction flag.
538     void fillTexture(const Document& doc);
539 
540     enum BlendMode {
541         BlendMode_Translucent,
542         BlendMode_Additive,
543         BlendMode_Modulate,
544         BlendMode_Modulate2,
545         BlendMode_Over,
546         BlendMode_Normal,
547         BlendMode_Dissolve,
548         BlendMode_Darken,
549         BlendMode_ColorBurn,
550         BlendMode_LinearBurn,
551         BlendMode_DarkerColor,
552         BlendMode_Lighten,
553         BlendMode_Screen,
554         BlendMode_ColorDodge,
555         BlendMode_LinearDodge,
556         BlendMode_LighterColor,
557         BlendMode_SoftLight,
558         BlendMode_HardLight,
559         BlendMode_VividLight,
560         BlendMode_LinearLight,
561         BlendMode_PinLight,
562         BlendMode_HardMix,
563         BlendMode_Difference,
564         BlendMode_Exclusion,
565         BlendMode_Subtract,
566         BlendMode_Divide,
567         BlendMode_Hue,
568         BlendMode_Saturation,
569         BlendMode_Color,
570         BlendMode_Luminosity,
571         BlendMode_Overlay,
572         BlendMode_BlendModeCount
573     };
574 
575     const Texture* getTexture(int index=0) const
576     {
577 		return textures[index];
578 
579     }
textureCount()580 	int textureCount() const {
581 		return static_cast<int>(textures.size());
582 	}
GetBlendMode()583     BlendMode GetBlendMode() const
584     {
585         return blendMode;
586     }
Alpha()587     float Alpha()
588     {
589         return alpha;
590     }
591 private:
592 	std::vector<const Texture*> textures;
593     BlendMode blendMode;
594     float alpha;
595 };
596 
597 typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
598 typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
599 
600 
601 /** DOM class for generic FBX videos */
602 class Video : public Object {
603 public:
604     Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
605 
606     virtual ~Video();
607 
Type()608     const std::string& Type() const {
609         return type;
610     }
611 
FileName()612     const std::string& FileName() const {
613         return fileName;
614     }
615 
RelativeFilename()616     const std::string& RelativeFilename() const {
617         return relativeFileName;
618     }
619 
Props()620     const PropertyTable& Props() const {
621         ai_assert(props.get());
622         return *props.get();
623     }
624 
Content()625     const uint8_t* Content() const {
626         ai_assert(content);
627         return content;
628     }
629 
ContentLength()630     uint64_t ContentLength() const {
631         return contentLength;
632     }
633 
RelinquishContent()634     uint8_t* RelinquishContent() {
635         uint8_t* ptr = content;
636         content = 0;
637         return ptr;
638     }
639 
640     bool operator==(const Video& other) const
641     {
642         return (
643                type == other.type
644             && relativeFileName == other.relativeFileName
645             && fileName == other.fileName
646         );
647     }
648 
649     bool operator<(const Video& other) const
650     {
651         return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName);
652     }
653 
654 private:
655     std::string type;
656     std::string relativeFileName;
657     std::string fileName;
658     std::shared_ptr<const PropertyTable> props;
659 
660     uint64_t contentLength;
661     uint8_t* content;
662 };
663 
664 /** DOM class for generic FBX materials */
665 class Material : public Object {
666 public:
667     Material(uint64_t id, const Element& element, const Document& doc, const std::string& name);
668 
669     virtual ~Material();
670 
GetShadingModel()671     const std::string& GetShadingModel() const {
672         return shading;
673     }
674 
IsMultilayer()675     bool IsMultilayer() const {
676         return multilayer;
677     }
678 
Props()679     const PropertyTable& Props() const {
680         ai_assert(props.get());
681         return *props.get();
682     }
683 
Textures()684     const TextureMap& Textures() const {
685         return textures;
686     }
687 
LayeredTextures()688     const LayeredTextureMap& LayeredTextures() const {
689         return layeredTextures;
690     }
691 
692 private:
693     std::string shading;
694     bool multilayer;
695     std::shared_ptr<const PropertyTable> props;
696 
697     TextureMap textures;
698     LayeredTextureMap layeredTextures;
699 };
700 
701 typedef std::vector<int64_t> KeyTimeList;
702 typedef std::vector<float> KeyValueList;
703 
704 /** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
705 class AnimationCurve : public Object {
706 public:
707     AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
708     virtual ~AnimationCurve();
709 
710     /** get list of keyframe positions (time).
711      *  Invariant: |GetKeys()| > 0 */
GetKeys()712     const KeyTimeList& GetKeys() const {
713         return keys;
714     }
715 
716     /** get list of keyframe values.
717       * Invariant: |GetKeys()| == |GetValues()| && |GetKeys()| > 0*/
GetValues()718     const KeyValueList& GetValues() const {
719         return values;
720     }
721 
GetAttributes()722     const std::vector<float>& GetAttributes() const {
723         return attributes;
724     }
725 
GetFlags()726     const std::vector<unsigned int>& GetFlags() const {
727         return flags;
728     }
729 
730 private:
731     KeyTimeList keys;
732     KeyValueList values;
733     std::vector<float> attributes;
734     std::vector<unsigned int> flags;
735 };
736 
737 // property-name -> animation curve
738 typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
739 
740 /** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
741 class AnimationCurveNode : public Object {
742 public:
743     /* the optional white list specifies a list of property names for which the caller
744     wants animations for. If the curve node does not match one of these, std::range_error
745     will be thrown. */
746     AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
747         const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0);
748 
749     virtual ~AnimationCurveNode();
750 
Props()751     const PropertyTable& Props() const {
752         ai_assert(props.get());
753         return *props.get();
754     }
755 
756 
757     const AnimationCurveMap& Curves() const;
758 
759     /** Object the curve is assigned to, this can be NULL if the
760      *  target object has no DOM representation or could not
761      *  be read for other reasons.*/
Target()762     const Object* Target() const {
763         return target;
764     }
765 
TargetAsModel()766     const Model* TargetAsModel() const {
767         return dynamic_cast<const Model*>(target);
768     }
769 
TargetAsNodeAttribute()770     const NodeAttribute* TargetAsNodeAttribute() const {
771         return dynamic_cast<const NodeAttribute*>(target);
772     }
773 
774     /** Property of Target() that is being animated*/
TargetProperty()775     const std::string& TargetProperty() const {
776         return prop;
777     }
778 
779 private:
780     const Object* target;
781     std::shared_ptr<const PropertyTable> props;
782     mutable AnimationCurveMap curves;
783 
784     std::string prop;
785     const Document& doc;
786 };
787 
788 typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
789 
790 /** Represents a FBX animation layer (i.e. a list of node animations) */
791 class AnimationLayer : public Object {
792 public:
793     AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
794     virtual ~AnimationLayer();
795 
Props()796     const PropertyTable& Props() const {
797         ai_assert(props.get());
798         return *props.get();
799     }
800 
801     /* the optional white list specifies a list of property names for which the caller
802     wants animations for. Curves not matching this list will not be added to the
803     animation layer. */
804     AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = nullptr, size_t whitelist_size = 0) const;
805 
806 private:
807     std::shared_ptr<const PropertyTable> props;
808     const Document& doc;
809 };
810 
811 typedef std::vector<const AnimationLayer*> AnimationLayerList;
812 
813 /** Represents a FBX animation stack (i.e. a list of animation layers) */
814 class AnimationStack : public Object {
815 public:
816     AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
817     virtual ~AnimationStack();
818 
819     fbx_simple_property(LocalStart, int64_t, 0L)
820     fbx_simple_property(LocalStop, int64_t, 0L)
821     fbx_simple_property(ReferenceStart, int64_t, 0L)
822     fbx_simple_property(ReferenceStop, int64_t, 0L)
823 
Props()824     const PropertyTable& Props() const {
825         ai_assert(props.get());
826         return *props.get();
827     }
828 
Layers()829     const AnimationLayerList& Layers() const {
830         return layers;
831     }
832 
833 private:
834     std::shared_ptr<const PropertyTable> props;
835     AnimationLayerList layers;
836 };
837 
838 
839 /** DOM class for deformers */
840 class Deformer : public Object {
841 public:
842     Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
843     virtual ~Deformer();
844 
Props()845     const PropertyTable& Props() const {
846         ai_assert(props.get());
847         return *props.get();
848     }
849 
850 private:
851     std::shared_ptr<const PropertyTable> props;
852 };
853 
854 typedef std::vector<float> WeightArray;
855 typedef std::vector<unsigned int> WeightIndexArray;
856 
857 
858 /** DOM class for BlendShapeChannel deformers */
859 class BlendShapeChannel : public Deformer {
860 public:
861     BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
862 
863     virtual ~BlendShapeChannel();
864 
DeformPercent()865     float DeformPercent() const {
866         return percent;
867     }
868 
GetFullWeights()869     const WeightArray& GetFullWeights() const {
870         return fullWeights;
871     }
872 
GetShapeGeometries()873     const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
874         return shapeGeometries;
875     }
876 
877 private:
878     float percent;
879     WeightArray fullWeights;
880     std::vector<const ShapeGeometry*> shapeGeometries;
881 };
882 
883 /** DOM class for BlendShape deformers */
884 class BlendShape : public Deformer {
885 public:
886     BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name);
887 
888     virtual ~BlendShape();
889 
BlendShapeChannels()890     const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
891         return blendShapeChannels;
892     }
893 
894 private:
895     std::vector<const BlendShapeChannel*> blendShapeChannels;
896 };
897 
898 /** DOM class for skin deformer clusters (aka sub-deformers) */
899 class Cluster : public Deformer {
900 public:
901     Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
902 
903     virtual ~Cluster();
904 
905     /** get the list of deformer weights associated with this cluster.
906      *  Use #GetIndices() to get the associated vertices. Both arrays
907      *  have the same size (and may also be empty). */
GetWeights()908     const WeightArray& GetWeights() const {
909         return weights;
910     }
911 
912     /** get indices into the vertex data of the geometry associated
913      *  with this cluster. Use #GetWeights() to get the associated weights.
914      *  Both arrays have the same size (and may also be empty). */
GetIndices()915     const WeightIndexArray& GetIndices() const {
916         return indices;
917     }
918 
919     /** */
Transform()920     const aiMatrix4x4& Transform() const {
921         return transform;
922     }
923 
TransformLink()924     const aiMatrix4x4& TransformLink() const {
925         return transformLink;
926     }
927 
TargetNode()928     const Model* TargetNode() const {
929         return node;
930     }
931 
932 private:
933     WeightArray weights;
934     WeightIndexArray indices;
935 
936     aiMatrix4x4 transform;
937     aiMatrix4x4 transformLink;
938 
939     const Model* node;
940 };
941 
942 /** DOM class for skin deformers */
943 class Skin : public Deformer {
944 public:
945     Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
946 
947     virtual ~Skin();
948 
DeformAccuracy()949     float DeformAccuracy() const {
950         return accuracy;
951     }
952 
Clusters()953     const std::vector<const Cluster*>& Clusters() const {
954         return clusters;
955     }
956 
957 private:
958     float accuracy;
959     std::vector<const Cluster*> clusters;
960 };
961 
962 /** Represents a link between two FBX objects. */
963 class Connection {
964 public:
965     Connection(uint64_t insertionOrder,  uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
966 
967     ~Connection();
968 
969     // note: a connection ensures that the source and dest objects exist, but
970     // not that they have DOM representations, so the return value of one of
971     // these functions can still be NULL.
972     const Object* SourceObject() const;
973     const Object* DestinationObject() const;
974 
975     // these, however, are always guaranteed to be valid
976     LazyObject& LazySourceObject() const;
977     LazyObject& LazyDestinationObject() const;
978 
979 
980     /** return the name of the property the connection is attached to.
981       * this is an empty string for object to object (OO) connections. */
PropertyName()982     const std::string& PropertyName() const {
983         return prop;
984     }
985 
InsertionOrder()986     uint64_t InsertionOrder() const {
987         return insertionOrder;
988     }
989 
CompareTo(const Connection * c)990     int CompareTo(const Connection* c) const {
991         ai_assert( nullptr != c );
992 
993         // note: can't subtract because this would overflow uint64_t
994         if(InsertionOrder() > c->InsertionOrder()) {
995             return 1;
996         }
997         else if(InsertionOrder() < c->InsertionOrder()) {
998             return -1;
999         }
1000         return 0;
1001     }
1002 
Compare(const Connection * c)1003     bool Compare(const Connection* c) const {
1004         ai_assert( nullptr != c );
1005 
1006         return InsertionOrder() < c->InsertionOrder();
1007     }
1008 
1009 public:
1010     uint64_t insertionOrder;
1011     const std::string prop;
1012 
1013     uint64_t src, dest;
1014     const Document& doc;
1015 };
1016 
1017 // XXX again, unique_ptr would be useful. shared_ptr is too
1018 // bloated since the objects have a well-defined single owner
1019 // during their entire lifetime (Document). FBX files have
1020 // up to many thousands of objects (most of which we never use),
1021 // so the memory overhead for them should be kept at a minimum.
1022 typedef std::fbx_unordered_map<uint64_t, LazyObject*> ObjectMap;
1023 typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
1024 
1025 typedef std::fbx_unordered_multimap<uint64_t, const Connection*> ConnectionMap;
1026 
1027 /** DOM class for global document settings, a single instance per document can
1028  *  be accessed via Document.Globals(). */
1029 class FileGlobalSettings {
1030 public:
1031     FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
1032 
1033     ~FileGlobalSettings();
1034 
Props()1035     const PropertyTable& Props() const {
1036         ai_assert(props.get());
1037         return *props.get();
1038     }
1039 
GetDocument()1040     const Document& GetDocument() const {
1041         return doc;
1042     }
1043 
1044     fbx_simple_property(UpAxis, int, 1)
1045     fbx_simple_property(UpAxisSign, int, 1)
1046     fbx_simple_property(FrontAxis, int, 2)
1047     fbx_simple_property(FrontAxisSign, int, 1)
1048     fbx_simple_property(CoordAxis, int, 0)
1049     fbx_simple_property(CoordAxisSign, int, 1)
1050     fbx_simple_property(OriginalUpAxis, int, 0)
1051     fbx_simple_property(OriginalUpAxisSign, int, 1)
1052     fbx_simple_property(UnitScaleFactor, float, 1)
1053     fbx_simple_property(OriginalUnitScaleFactor, float, 1)
1054     fbx_simple_property(AmbientColor, aiVector3D, aiVector3D(0,0,0))
1055     fbx_simple_property(DefaultCamera, std::string, "")
1056 
1057 
1058     enum FrameRate {
1059         FrameRate_DEFAULT = 0,
1060         FrameRate_120 = 1,
1061         FrameRate_100 = 2,
1062         FrameRate_60 = 3,
1063         FrameRate_50 = 4,
1064         FrameRate_48 = 5,
1065         FrameRate_30 = 6,
1066         FrameRate_30_DROP = 7,
1067         FrameRate_NTSC_DROP_FRAME = 8,
1068         FrameRate_NTSC_FULL_FRAME = 9,
1069         FrameRate_PAL = 10,
1070         FrameRate_CINEMA = 11,
1071         FrameRate_1000 = 12,
1072         FrameRate_CINEMA_ND = 13,
1073         FrameRate_CUSTOM = 14,
1074 
1075         FrameRate_MAX// end-of-enum sentinel
1076     };
1077 
1078     fbx_simple_enum_property(TimeMode, FrameRate, FrameRate_DEFAULT)
1079     fbx_simple_property(TimeSpanStart, uint64_t, 0L)
1080     fbx_simple_property(TimeSpanStop, uint64_t, 0L)
1081     fbx_simple_property(CustomFrameRate, float, -1.0f)
1082 
1083 private:
1084     std::shared_ptr<const PropertyTable> props;
1085     const Document& doc;
1086 };
1087 
1088 /** DOM root for a FBX file */
1089 class Document {
1090 public:
1091     Document(const Parser& parser, const ImportSettings& settings);
1092 
1093     ~Document();
1094 
1095     LazyObject* GetObject(uint64_t id) const;
1096 
IsBinary()1097     bool IsBinary() const {
1098         return parser.IsBinary();
1099     }
1100 
FBXVersion()1101     unsigned int FBXVersion() const {
1102         return fbxVersion;
1103     }
1104 
Creator()1105     const std::string& Creator() const {
1106         return creator;
1107     }
1108 
1109     // elements (in this order): Year, Month, Day, Hour, Second, Millisecond
CreationTimeStamp()1110     const unsigned int* CreationTimeStamp() const {
1111         return creationTimeStamp;
1112     }
1113 
GlobalSettings()1114     const FileGlobalSettings& GlobalSettings() const {
1115         ai_assert(globals.get());
1116         return *globals.get();
1117     }
1118 
Templates()1119     const PropertyTemplateMap& Templates() const {
1120         return templates;
1121     }
1122 
Objects()1123     const ObjectMap& Objects() const {
1124         return objects;
1125     }
1126 
Settings()1127     const ImportSettings& Settings() const {
1128         return settings;
1129     }
1130 
ConnectionsBySource()1131     const ConnectionMap& ConnectionsBySource() const {
1132         return src_connections;
1133     }
1134 
ConnectionsByDestination()1135     const ConnectionMap& ConnectionsByDestination() const {
1136         return dest_connections;
1137     }
1138 
1139     // note: the implicit rule in all DOM classes is to always resolve
1140     // from destination to source (since the FBX object hierarchy is,
1141     // with very few exceptions, a DAG, this avoids cycles). In all
1142     // cases that may involve back-facing edges in the object graph,
1143     // use LazyObject::IsBeingConstructed() to check.
1144 
1145     std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source) const;
1146     std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest) const;
1147 
1148     std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source, const char* classname) const;
1149     std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest, const char* classname) const;
1150 
1151     std::vector<const Connection*> GetConnectionsBySourceSequenced(uint64_t source,
1152         const char* const* classnames, size_t count) const;
1153     std::vector<const Connection*> GetConnectionsByDestinationSequenced(uint64_t dest,
1154         const char* const* classnames,
1155         size_t count) const;
1156 
1157     const std::vector<const AnimationStack*>& AnimationStacks() const;
1158 
1159 private:
1160     std::vector<const Connection*> GetConnectionsSequenced(uint64_t id, const ConnectionMap&) const;
1161     std::vector<const Connection*> GetConnectionsSequenced(uint64_t id, bool is_src,
1162         const ConnectionMap&,
1163         const char* const* classnames,
1164         size_t count) const;
1165     void ReadHeader();
1166     void ReadObjects();
1167     void ReadPropertyTemplates();
1168     void ReadConnections();
1169     void ReadGlobalSettings();
1170 
1171 private:
1172     const ImportSettings& settings;
1173 
1174     ObjectMap objects;
1175     const Parser& parser;
1176 
1177     PropertyTemplateMap templates;
1178     ConnectionMap src_connections;
1179     ConnectionMap dest_connections;
1180 
1181     unsigned int fbxVersion;
1182     std::string creator;
1183     unsigned int creationTimeStamp[7];
1184 
1185     std::vector<uint64_t> animationStacks;
1186     mutable std::vector<const AnimationStack*> animationStacksResolved;
1187 
1188     std::unique_ptr<FileGlobalSettings> globals;
1189 };
1190 
1191 } // Namespace FBX
1192 } // Namespace Assimp
1193 
1194 namespace std
1195 {
1196     template <>
1197     struct hash<const Assimp::FBX::Video>
1198     {
1199         std::size_t operator()(const Assimp::FBX::Video& video) const
1200         {
1201             using std::size_t;
1202             using std::hash;
1203             using std::string;
1204 
1205             size_t res = 17;
1206             res = res * 31 + hash<string>()(video.Name());
1207             res = res * 31 + hash<string>()(video.RelativeFilename());
1208             res = res * 31 + hash<string>()(video.Type());
1209 
1210             return res;
1211         }
1212     };
1213 }
1214 
1215 #endif // INCLUDED_AI_FBX_DOCUMENT_H
1216