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