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