1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2017, assimp team
6
7All rights reserved.
8
9Redistribution and use of this software in source and binary forms,
10with or without modification, are permitted provided that the
11following 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
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37OF 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
57namespace Assimp {
58namespace FBX {
59
60class Parser;
61class Object;
62struct ImportSettings;
63
64class PropertyTable;
65class Document;
66class Material;
67class Geometry;
68
69class Video;
70
71class AnimationCurve;
72class AnimationCurveNode;
73class AnimationLayer;
74class AnimationStack;
75
76class Skin;
77class 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. */
83class LazyObject
84{
85public:
86 LazyObject(uint64_t id, const Element& element, const Document& doc);
87 ~LazyObject();
88
89public:
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
99 uint64_t ID() const {
100 return id;
101 }
102
103 bool IsBeingConstructed() const {
104 return (flags & BEING_CONSTRUCTED) != 0;
105 }
106
107 bool FailedToConstruct() const {
108 return (flags & FAILED_TO_CONSTRUCT) != 0;
109 }
110
111 const Element& GetElement() const {
112 return element;
113 }
114
115 const Document& GetDocument() const {
116 return doc;
117 }
118
119private:
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 */
137class Object
138{
139public:
140 Object(uint64_t id, const Element& element, const std::string& name);
141
142 virtual ~Object();
143
144 const Element& SourceElement() const {
145 return element;
146 }
147
148 const std::string& Name() const {
149 return name;
150 }
151
152 uint64_t ID() const {
153 return id;
154 }
155
156protected:
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. */
166class NodeAttribute : public Object
167{
168public:
169 NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
170 virtual ~NodeAttribute();
171
172 const PropertyTable& Props() const {
173 ai_assert(props.get());
174 return *props.get();
175 }
176
177private:
178 std::shared_ptr<const PropertyTable> props;
179};
180
181
182/** DOM base class for FBX camera settings attached to a node */
183class CameraSwitcher : public NodeAttribute
184{
185public:
186 CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
187 virtual ~CameraSwitcher();
188
189 int CameraID() const {
190 return cameraId;
191 }
192
193 const std::string& CameraName() const {
194 return cameraName;
195 }
196
197 const std::string& CameraIndexName() const {
198 return cameraIndexName;
199 }
200
201private:
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 */
228class Camera : public NodeAttribute
229{
230public:
231 Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
232 virtual ~Camera();
233
234public:
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 */
256class Null : public NodeAttribute
257{
258public:
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 */
265class LimbNode : public NodeAttribute
266{
267public:
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 */
274class Light : public NodeAttribute
275{
276public:
277 Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
278 virtual ~Light();
279
280public:
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
302public:
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" */
338class Model : public Object
339{
340public:
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
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
447 const std::string& Culling() const {
448 return culling;
449 }
450
451 const PropertyTable& Props() const {
452 ai_assert(props.get());
453 return *props.get();
454 }
455
456 /** Get material links */
457 const std::vector<const Material*>& GetMaterials() const {
458 return materials;
459 }
460
461 /** Get geometry links */
462 const std::vector<const Geometry*>& GetGeometry() const {
463 return geometry;
464 }
465
466 /** Get node attachments */
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
474private:
475 void ResolveLinks(const Element& element, const Document& doc);
476
477private:
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 */
488class Texture : public Object
489{
490public:
491 Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
492 virtual ~Texture();
493
494public:
495 const std::string& Type() const {
496 return type;
497 }
498
499 const std::string& FileName() const {
500 return fileName;
501 }
502
503 const std::string& RelativeFilename() const {
504 return relativeFileName;
505 }
506
507 const std::string& AlphaSource() const {
508 return alphaSource;
509 }
510
511 const aiVector2D& UVTranslation() const {
512 return uvTrans;
513 }
514
515 const aiVector2D& UVScaling() const {
516 return uvScaling;
517 }
518
519 const PropertyTable& Props() const {
520 ai_assert(props.get());
521 return *props.get();
522 }
523
524 // return a 4-tuple
525 const unsigned int* Crop() const {
526 return crop;
527 }
528
529 const Video* Media() const {
530 return media;
531 }
532
533private:
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 */
549class LayeredTexture : public Object
550{
551public:
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 }
599 int textureCount() const {
600 return static_cast<int>(textures.size());
601 }
602 BlendMode GetBlendMode() const
603 {
604 return blendMode;
605 }
606 float Alpha()
607 {
608 return alpha;
609 }
610private:
611 std::vector<const Texture*> textures;
612 BlendMode blendMode;
613 float alpha;
614};
615
616typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
617typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
618
619
620/** DOM class for generic FBX videos */
621class Video : public Object
622{
623public:
624 Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
625 virtual ~Video();
626
627public:
628 const std::string& Type() const {
629 return type;
630 }
631
632 const std::string& FileName() const {
633 return fileName;
634 }
635
636 const std::string& RelativeFilename() const {
637 return relativeFileName;
638 }
639
640 const PropertyTable& Props() const {
641 ai_assert(props.get());
642 return *props.get();
643 }
644
645 const uint8_t* Content() const {
646 ai_assert(content);
647 return content;
648 }
649
650 uint32_t ContentLength() const {
651 return contentLength;
652 }
653
654 uint8_t* RelinquishContent() {
655 uint8_t* ptr = content;
656 content = 0;
657 return ptr;
658 }
659
660private:
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 */
671class Material : public Object
672{
673public:
674 Material(uint64_t id, const Element& element, const Document& doc, const std::string& name);
675 virtual ~Material();
676
677 const std::string& GetShadingModel() const {
678 return shading;
679 }
680
681 bool IsMultilayer() const {
682 return multilayer;
683 }
684
685 const PropertyTable& Props() const {
686 ai_assert(props.get());
687 return *props.get();
688 }
689
690 const TextureMap& Textures() const {
691 return textures;
692 }
693
694 const LayeredTextureMap& LayeredTextures() const {
695 return layeredTextures;
696 }
697
698private:
699 std::string shading;
700 bool multilayer;
701 std::shared_ptr<const PropertyTable> props;
702
703 TextureMap textures;
704 LayeredTextureMap layeredTextures;
705};
706
707typedef std::vector<int64_t> KeyTimeList;
708typedef std::vector<float> KeyValueList;
709
710/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
711class AnimationCurve : public Object
712{
713public:
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 */
719 const KeyTimeList& GetKeys() const {
720 return keys;
721 }
722
723
724 /** get list of keyframe values.
725 * Invariant: |GetKeys()| == |GetValues()| && |GetKeys()| > 0*/
726 const KeyValueList& GetValues() const {
727 return values;
728 }
729
730
731 const std::vector<float>& GetAttributes() const {
732 return attributes;
733 }
734
735 const std::vector<unsigned int>& GetFlags() const {
736 return flags;
737 }
738
739private:
740 KeyTimeList keys;
741 KeyValueList values;
742 std::vector<float> attributes;
743 std::vector<unsigned int> flags;
744};
745
746// property-name -> animation curve
747typedef 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) */
751class AnimationCurveNode : public Object
752{
753public:
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
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.*/
773 const Object* Target() const {
774 return target;
775 }
776
777 const Model* TargetAsModel() const {
778 return dynamic_cast<const Model*>(target);
779 }
780
781 const NodeAttribute* TargetAsNodeAttribute() const {
782 return dynamic_cast<const NodeAttribute*>(target);
783 }
784
785 /** Property of Target() that is being animated*/
786 const std::string& TargetProperty() const {
787 return prop;
788 }
789
790private:
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
799typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
800
801/** Represents a FBX animation layer (i.e. a list of node animations) */
802class AnimationLayer : public Object
803{
804public:
805 AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
806 virtual ~AnimationLayer();
807
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
818private:
819 std::shared_ptr<const PropertyTable> props;
820 const Document& doc;
821};
822
823typedef std::vector<const AnimationLayer*> AnimationLayerList;
824
825/** Represents a FBX animation stack (i.e. a list of animation layers) */
826class AnimationStack : public Object
827{
828public:
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
837 const PropertyTable& Props() const {
838 ai_assert(props.get());
839 return *props.get();
840 }
841
842 const AnimationLayerList& Layers() const {
843 return layers;
844 }
845
846private:
847 std::shared_ptr<const PropertyTable> props;
848 AnimationLayerList layers;
849};
850
851
852/** DOM class for deformers */
853class Deformer : public Object
854{
855public:
856 Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
857 virtual ~Deformer();
858
859 const PropertyTable& Props() const {
860 ai_assert(props.get());
861 return *props.get();
862 }
863
864private:
865 std::shared_ptr<const PropertyTable> props;
866};
867
868typedef std::vector<float> WeightArray;
869typedef std::vector<unsigned int> WeightIndexArray;
870
871/** DOM class for skin deformer clusters (aka subdeformers) */
872class Cluster : public Deformer
873{
874public:
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). */
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). */
888 const WeightIndexArray& GetIndices() const {
889 return indices;
890 }
891
892 /** */
893 const aiMatrix4x4& Transform() const {
894 return transform;
895 }
896
897 const aiMatrix4x4& TransformLink() const {
898 return transformLink;
899 }
900
901 const Model* TargetNode() const {
902 return node;
903 }
904
905private:
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 */
916class Skin : public Deformer
917{
918public:
919 Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
920 virtual ~Skin();
921
922 float DeformAccuracy() const {
923 return accuracy;
924 }
925
926 const std::vector<const Cluster*>& Clusters() const {
927 return clusters;
928 }
929
930private:
931 float accuracy;
932 std::vector<const Cluster*> clusters;
933};
934
935/** Represents a link between two FBX objects. */
936class Connection
937{
938public:
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. */
955 const std::string& PropertyName() const {
956 return prop;
957 }
958
959 uint64_t InsertionOrder() const {
960 return insertionOrder;
961 }
962
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
976 bool Compare(const Connection* c) const {
977 ai_assert( NULL != c );
978
979 return InsertionOrder() < c->InsertionOrder();
980 }
981
982public:
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.
995typedef std::map<uint64_t, LazyObject*> ObjectMap;
996typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
997
998typedef 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(). */
1002class FileGlobalSettings
1003{
1004public:
1005 FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
1006 ~FileGlobalSettings();
1007
1008 const PropertyTable& Props() const {
1009 ai_assert(props.get());
1010 return *props.get();
1011 }
1012
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
1056private:
1057 std::shared_ptr<const PropertyTable> props;
1058 const Document& doc;
1059};
1060
1061/** DOM root for a FBX file */
1062class Document
1063{
1064public:
1065 Document(const Parser& parser, const ImportSettings& settings);
1066 ~Document();
1067
1068 LazyObject* GetObject(uint64_t id) const;
1069
1070 bool IsBinary() const {
1071 return parser.IsBinary();
1072 }
1073
1074 unsigned int FBXVersion() const {
1075 return fbxVersion;
1076 }
1077
1078 const std::string& Creator() const {
1079 return creator;
1080 }
1081
1082 // elements (in this order): Year, Month, Day, Hour, Second, Millisecond
1083 const unsigned int* CreationTimeStamp() const {
1084 return creationTimeStamp;
1085 }
1086
1087 const FileGlobalSettings& GlobalSettings() const {
1088 ai_assert(globals.get());
1089 return *globals.get();
1090 }
1091
1092 const PropertyTemplateMap& Templates() const {
1093 return templates;
1094 }
1095
1096 const ObjectMap& Objects() const {
1097 return objects;
1098 }
1099
1100 const ImportSettings& Settings() const {
1101 return settings;
1102 }
1103
1104 const ConnectionMap& ConnectionsBySource() const {
1105 return src_connections;
1106 }
1107
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
1132private:
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
1144private:
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