summaryrefslogtreecommitdiff
path: root/modules/fbx/fbx_parser/FBXDocument.h
diff options
context:
space:
mode:
Diffstat (limited to 'modules/fbx/fbx_parser/FBXDocument.h')
-rw-r--r--modules/fbx/fbx_parser/FBXDocument.h1319
1 files changed, 1319 insertions, 0 deletions
diff --git a/modules/fbx/fbx_parser/FBXDocument.h b/modules/fbx/fbx_parser/FBXDocument.h
new file mode 100644
index 0000000000..7c08f3de65
--- /dev/null
+++ b/modules/fbx/fbx_parser/FBXDocument.h
@@ -0,0 +1,1319 @@
+/*************************************************************************/
+/* FBXDocument.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+/** @file FBXDocument.h
+ * @brief FBX DOM
+ */
+#ifndef FBX_DOCUMENT_H
+#define FBX_DOCUMENT_H
+
+#include "FBXCommon.h"
+#include "FBXParser.h"
+#include "FBXProperties.h"
+#include "core/math/transform.h"
+#include "core/math/vector2.h"
+#include "core/math/vector3.h"
+#include "core/string/print_string.h"
+#include <stdint.h>
+#include <numeric>
+
+#define _AI_CONCAT(a, b) a##b
+#define AI_CONCAT(a, b) _AI_CONCAT(a, b)
+
+namespace FBXDocParser {
+
+class Parser;
+class Object;
+struct ImportSettings;
+class Connection;
+
+class PropertyTable;
+class Document;
+class Material;
+class ShapeGeometry;
+class LineGeometry;
+class Geometry;
+
+class Video;
+
+class AnimationCurve;
+class AnimationCurveNode;
+class AnimationLayer;
+class AnimationStack;
+
+class BlendShapeChannel;
+class BlendShape;
+class Skin;
+class Cluster;
+
+typedef Object *ObjectPtr;
+#define new_Object new Object
+
+/** Represents a delay-parsed FBX objects. Many objects in the scene
+ * are not needed by assimp, so it makes no sense to parse them
+ * upfront. */
+class LazyObject {
+public:
+ LazyObject(uint64_t id, const ElementPtr element, const Document &doc);
+ ~LazyObject();
+
+ ObjectPtr LoadObject();
+
+ /* Casting weak pointers to their templated type safely and preserving ref counting and safety
+ * with lock() keyword to prevent leaking memory
+ */
+ template <typename T>
+ const T *Get() {
+ ObjectPtr ob = LoadObject();
+ return dynamic_cast<const T *>(ob);
+ }
+
+ uint64_t ID() const {
+ return id;
+ }
+
+ bool IsBeingConstructed() const {
+ return (flags & BEING_CONSTRUCTED) != 0;
+ }
+
+ bool FailedToConstruct() const {
+ return (flags & FAILED_TO_CONSTRUCT) != 0;
+ }
+
+ ElementPtr GetElement() const {
+ return element;
+ }
+
+ const Document &GetDocument() const {
+ return doc;
+ }
+
+private:
+ const Document &doc;
+ ElementPtr element = nullptr;
+ std::shared_ptr<Object> object = nullptr;
+ const uint64_t id = 0;
+
+ enum Flags {
+ BEING_CONSTRUCTED = 0x1,
+ FAILED_TO_CONSTRUCT = 0x2
+ };
+
+ unsigned int flags = 0;
+};
+
+/** Base class for in-memory (DOM) representations of FBX objects */
+class Object {
+public:
+ Object(uint64_t id, const ElementPtr element, const std::string &name);
+
+ virtual ~Object();
+
+ ElementPtr SourceElement() const {
+ return element;
+ }
+
+ const std::string &Name() const {
+ return name;
+ }
+
+ uint64_t ID() const {
+ return id;
+ }
+
+protected:
+ const ElementPtr element;
+ const std::string name;
+ const uint64_t id = 0;
+};
+
+/** DOM class for generic FBX NoteAttribute blocks. NoteAttribute's just hold a property table,
+ * fixed members are added by deriving classes. */
+class NodeAttribute : public Object {
+public:
+ NodeAttribute(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~NodeAttribute();
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+private:
+ const PropertyTable *props;
+};
+
+/** DOM base class for FBX camera settings attached to a node */
+class CameraSwitcher : public NodeAttribute {
+public:
+ CameraSwitcher(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~CameraSwitcher();
+
+ int CameraID() const {
+ return cameraId;
+ }
+
+ const std::string &CameraName() const {
+ return cameraName;
+ }
+
+ const std::string &CameraIndexName() const {
+ return cameraIndexName;
+ }
+
+private:
+ int cameraId;
+ std::string cameraName;
+ std::string cameraIndexName;
+};
+
+#define fbx_stringize(a) #a
+
+#define fbx_simple_property(name, type, default_value) \
+ type name() const { \
+ return PropertyGet<type>(Props(), fbx_stringize(name), (default_value)); \
+ }
+
+// XXX improve logging
+#define fbx_simple_enum_property(name, type, default_value) \
+ type name() const { \
+ const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
+ if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
+ return static_cast<type>(default_value); \
+ } \
+ return static_cast<type>(ival); \
+ }
+
+class FbxPoseNode;
+class FbxPose : public Object {
+public:
+ FbxPose(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ const std::vector<FbxPoseNode *> &GetBindPoses() const {
+ return pose_nodes;
+ }
+
+ virtual ~FbxPose();
+
+private:
+ std::vector<FbxPoseNode *> pose_nodes;
+};
+
+class FbxPoseNode {
+public:
+ FbxPoseNode(const ElementPtr element, const Document &doc, const std::string &name) {
+ const ScopePtr sc = GetRequiredScope(element);
+
+ // get pose node transform
+ const ElementPtr Transform = GetRequiredElement(sc, "Matrix", element);
+ transform = ReadMatrix(Transform);
+
+ // get node id this pose node is for
+ const ElementPtr NodeId = sc->GetElement("Node3D");
+ if (NodeId) {
+ target_id = ParseTokenAsInt64(GetRequiredToken(NodeId, 0));
+ }
+
+ print_verbose("added posenode " + itos(target_id) + " transform: " + transform);
+ }
+ virtual ~FbxPoseNode() {
+ }
+
+ uint64_t GetNodeID() const {
+ return target_id;
+ }
+
+ Transform GetBindPose() const {
+ return transform;
+ }
+
+private:
+ uint64_t target_id;
+ Transform transform;
+};
+
+/** DOM base class for FBX cameras attached to a node */
+class Camera : public NodeAttribute {
+public:
+ Camera(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Camera();
+
+ fbx_simple_property(Position, Vector3, Vector3(0, 0, 0));
+ fbx_simple_property(UpVector, Vector3, Vector3(0, 1, 0));
+ fbx_simple_property(InterestPosition, Vector3, Vector3(0, 0, 0));
+
+ fbx_simple_property(AspectWidth, float, 1.0f);
+ fbx_simple_property(AspectHeight, float, 1.0f);
+ fbx_simple_property(FilmWidth, float, 1.0f);
+ fbx_simple_property(FilmHeight, float, 1.0f);
+
+ fbx_simple_property(NearPlane, float, 0.1f);
+ fbx_simple_property(FarPlane, float, 100.0f);
+
+ fbx_simple_property(FilmAspectRatio, float, 1.0f);
+ fbx_simple_property(ApertureMode, int, 0);
+
+ fbx_simple_property(FieldOfView, float, 1.0f);
+ fbx_simple_property(FocalLength, float, 1.0f);
+};
+
+/** DOM base class for FBX null markers attached to a node */
+class Null : public NodeAttribute {
+public:
+ Null(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+ virtual ~Null();
+};
+
+/** DOM base class for FBX limb node markers attached to a node */
+class LimbNode : public NodeAttribute {
+public:
+ LimbNode(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+ virtual ~LimbNode();
+};
+
+/** DOM base class for FBX lights attached to a node */
+class Light : public NodeAttribute {
+public:
+ Light(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+ virtual ~Light();
+
+ enum Type {
+ Type_Point,
+ Type_Directional,
+ Type_Spot,
+ Type_Area,
+ Type_Volume,
+
+ Type_MAX // end-of-enum sentinel
+ };
+
+ enum Decay {
+ Decay_None,
+ Decay_Linear,
+ Decay_Quadratic,
+ Decay_Cubic,
+
+ Decay_MAX // end-of-enum sentinel
+ };
+
+ fbx_simple_property(Color, Vector3, Vector3(1, 1, 1));
+ fbx_simple_enum_property(LightType, Type, 0);
+ fbx_simple_property(CastLightOnObject, bool, false);
+ fbx_simple_property(DrawVolumetricLight, bool, true);
+ fbx_simple_property(DrawGroundProjection, bool, true);
+ fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false);
+ fbx_simple_property(Intensity, float, 100.0f);
+ fbx_simple_property(InnerAngle, float, 0.0f);
+ fbx_simple_property(OuterAngle, float, 45.0f);
+ fbx_simple_property(Fog, int, 50);
+ fbx_simple_enum_property(DecayType, Decay, 2);
+ fbx_simple_property(DecayStart, float, 1.0f);
+ fbx_simple_property(FileName, std::string, "");
+
+ fbx_simple_property(EnableNearAttenuation, bool, false);
+ fbx_simple_property(NearAttenuationStart, float, 0.0f);
+ fbx_simple_property(NearAttenuationEnd, float, 0.0f);
+ fbx_simple_property(EnableFarAttenuation, bool, false);
+ fbx_simple_property(FarAttenuationStart, float, 0.0f);
+ fbx_simple_property(FarAttenuationEnd, float, 0.0f);
+
+ fbx_simple_property(CastShadows, bool, true);
+ fbx_simple_property(ShadowColor, Vector3, Vector3(0, 0, 0));
+
+ fbx_simple_property(AreaLightShape, int, 0);
+
+ fbx_simple_property(LeftBarnDoor, float, 20.0f);
+ fbx_simple_property(RightBarnDoor, float, 20.0f);
+ fbx_simple_property(TopBarnDoor, float, 20.0f);
+ fbx_simple_property(BottomBarnDoor, float, 20.0f);
+ fbx_simple_property(EnableBarnDoor, bool, true);
+};
+
+class Model;
+
+typedef Model *ModelPtr;
+#define new_Model new Model
+
+/** DOM base class for FBX models (even though its semantics are more "node" than "model" */
+class Model : public Object {
+public:
+ enum RotOrder {
+ RotOrder_EulerXYZ = 0,
+ RotOrder_EulerXZY,
+ RotOrder_EulerYZX,
+ RotOrder_EulerYXZ,
+ RotOrder_EulerZXY,
+ RotOrder_EulerZYX,
+
+ RotOrder_SphericXYZ,
+
+ RotOrder_MAX // end-of-enum sentinel
+ };
+
+ Model(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Model();
+
+ fbx_simple_property(QuaternionInterpolate, int, 0);
+
+ fbx_simple_property(RotationOffset, Vector3, Vector3());
+ fbx_simple_property(RotationPivot, Vector3, Vector3());
+ fbx_simple_property(ScalingOffset, Vector3, Vector3());
+ fbx_simple_property(ScalingPivot, Vector3, Vector3());
+ fbx_simple_property(TranslationActive, bool, false);
+ fbx_simple_property(TranslationMin, Vector3, Vector3());
+ fbx_simple_property(TranslationMax, Vector3, Vector3());
+
+ fbx_simple_property(TranslationMinX, bool, false);
+ fbx_simple_property(TranslationMaxX, bool, false);
+ fbx_simple_property(TranslationMinY, bool, false);
+ fbx_simple_property(TranslationMaxY, bool, false);
+ fbx_simple_property(TranslationMinZ, bool, false);
+ fbx_simple_property(TranslationMaxZ, bool, false);
+
+ fbx_simple_enum_property(RotationOrder, RotOrder, 0);
+ fbx_simple_property(RotationSpaceForLimitOnly, bool, false);
+ fbx_simple_property(RotationStiffnessX, float, 0.0f);
+ fbx_simple_property(RotationStiffnessY, float, 0.0f);
+ fbx_simple_property(RotationStiffnessZ, float, 0.0f);
+ fbx_simple_property(AxisLen, float, 0.0f);
+
+ fbx_simple_property(PreRotation, Vector3, Vector3());
+ fbx_simple_property(PostRotation, Vector3, Vector3());
+ fbx_simple_property(RotationActive, bool, false);
+
+ fbx_simple_property(RotationMin, Vector3, Vector3());
+ fbx_simple_property(RotationMax, Vector3, Vector3());
+
+ fbx_simple_property(RotationMinX, bool, false);
+ fbx_simple_property(RotationMaxX, bool, false);
+ fbx_simple_property(RotationMinY, bool, false);
+ fbx_simple_property(RotationMaxY, bool, false);
+ fbx_simple_property(RotationMinZ, bool, false);
+ fbx_simple_property(RotationMaxZ, bool, false);
+ fbx_simple_enum_property(InheritType, TransformInheritance, 0);
+
+ fbx_simple_property(ScalingActive, bool, false);
+ fbx_simple_property(ScalingMin, Vector3, Vector3());
+ fbx_simple_property(ScalingMax, Vector3, Vector3(1, 1, 1));
+ fbx_simple_property(ScalingMinX, bool, false);
+ fbx_simple_property(ScalingMaxX, bool, false);
+ fbx_simple_property(ScalingMinY, bool, false);
+ fbx_simple_property(ScalingMaxY, bool, false);
+ fbx_simple_property(ScalingMinZ, bool, false);
+ fbx_simple_property(ScalingMaxZ, bool, false);
+
+ fbx_simple_property(GeometricTranslation, Vector3, Vector3());
+ fbx_simple_property(GeometricRotation, Vector3, Vector3());
+ fbx_simple_property(GeometricScaling, Vector3, Vector3(1, 1, 1));
+
+ fbx_simple_property(MinDampRangeX, float, 0.0f);
+ fbx_simple_property(MinDampRangeY, float, 0.0f);
+ fbx_simple_property(MinDampRangeZ, float, 0.0f);
+ fbx_simple_property(MaxDampRangeX, float, 0.0f);
+ fbx_simple_property(MaxDampRangeY, float, 0.0f);
+ fbx_simple_property(MaxDampRangeZ, float, 0.0f);
+
+ fbx_simple_property(MinDampStrengthX, float, 0.0f);
+ fbx_simple_property(MinDampStrengthY, float, 0.0f);
+ fbx_simple_property(MinDampStrengthZ, float, 0.0f);
+ fbx_simple_property(MaxDampStrengthX, float, 0.0f);
+ fbx_simple_property(MaxDampStrengthY, float, 0.0f);
+ fbx_simple_property(MaxDampStrengthZ, float, 0.0f);
+
+ fbx_simple_property(PreferredAngleX, float, 0.0f);
+ fbx_simple_property(PreferredAngleY, float, 0.0f);
+ fbx_simple_property(PreferredAngleZ, float, 0.0f);
+
+ fbx_simple_property(Show, bool, true);
+ fbx_simple_property(LODBox, bool, false);
+ fbx_simple_property(Freeze, bool, false);
+
+ const std::string &Shading() const {
+ return shading;
+ }
+
+ const std::string &Culling() const {
+ return culling;
+ }
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ /** Get material links */
+ const std::vector<const Material *> &GetMaterials() const {
+ return materials;
+ }
+
+ /** Get geometry links */
+ const std::vector<const Geometry *> &GetGeometry() const {
+ return geometry;
+ }
+
+ /** Get node attachments */
+ const std::vector<const NodeAttribute *> &GetAttributes() const {
+ return attributes;
+ }
+
+ /** convenience method to check if the node has a Null node marker */
+ bool IsNull() const;
+
+private:
+ void ResolveLinks(const ElementPtr element, const Document &doc);
+
+private:
+ std::vector<const Material *> materials;
+ std::vector<const Geometry *> geometry;
+ std::vector<const NodeAttribute *> attributes;
+
+ std::string shading;
+ std::string culling;
+ const PropertyTable *props = nullptr;
+};
+
+class ModelLimbNode : public Model {
+public:
+ ModelLimbNode(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~ModelLimbNode();
+};
+
+/** DOM class for generic FBX textures */
+class Texture : public Object {
+public:
+ Texture(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Texture();
+
+ const std::string &Type() const {
+ return type;
+ }
+
+ const std::string &FileName() const {
+ return fileName;
+ }
+
+ const std::string &RelativeFilename() const {
+ return relativeFileName;
+ }
+
+ const std::string &AlphaSource() const {
+ return alphaSource;
+ }
+
+ const Vector2 &UVTranslation() const {
+ return uvTrans;
+ }
+
+ const Vector2 &UVScaling() const {
+ return uvScaling;
+ }
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ // return a 4-tuple
+ const unsigned int *Crop() const {
+ return crop;
+ }
+
+ const Video *Media() const {
+ return media;
+ }
+
+private:
+ Vector2 uvTrans;
+ Vector2 uvScaling;
+
+ std::string type;
+ std::string relativeFileName;
+ std::string fileName;
+ std::string alphaSource;
+ const PropertyTable *props = nullptr;
+
+ unsigned int crop[4] = { 0 };
+
+ const Video *media = nullptr;
+};
+
+/** DOM class for layered FBX textures */
+class LayeredTexture : public Object {
+public:
+ LayeredTexture(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+ virtual ~LayeredTexture();
+
+ // Can only be called after construction of the layered texture object due to construction flag.
+ void fillTexture(const Document &doc);
+
+ enum BlendMode {
+ BlendMode_Translucent,
+ BlendMode_Additive,
+ BlendMode_Modulate,
+ BlendMode_Modulate2,
+ BlendMode_Over,
+ BlendMode_Normal,
+ BlendMode_Dissolve,
+ BlendMode_Darken,
+ BlendMode_ColorBurn,
+ BlendMode_LinearBurn,
+ BlendMode_DarkerColor,
+ BlendMode_Lighten,
+ BlendMode_Screen,
+ BlendMode_ColorDodge,
+ BlendMode_LinearDodge,
+ BlendMode_LighterColor,
+ BlendMode_SoftLight,
+ BlendMode_HardLight,
+ BlendMode_VividLight,
+ BlendMode_LinearLight,
+ BlendMode_PinLight,
+ BlendMode_HardMix,
+ BlendMode_Difference,
+ BlendMode_Exclusion,
+ BlendMode_Subtract,
+ BlendMode_Divide,
+ BlendMode_Hue,
+ BlendMode_Saturation,
+ BlendMode_Color,
+ BlendMode_Luminosity,
+ BlendMode_Overlay,
+ BlendMode_BlendModeCount
+ };
+
+ const Texture *getTexture(int index = 0) const {
+ return textures[index];
+ }
+ int textureCount() const {
+ return static_cast<int>(textures.size());
+ }
+ BlendMode GetBlendMode() const {
+ return blendMode;
+ }
+ float Alpha() {
+ return alpha;
+ }
+
+private:
+ std::vector<const Texture *> textures;
+ BlendMode blendMode;
+ float alpha;
+};
+
+typedef std::map<std::string, const Texture *> TextureMap;
+typedef std::map<std::string, const LayeredTexture *> LayeredTextureMap;
+
+/** DOM class for generic FBX videos */
+class Video : public Object {
+public:
+ Video(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Video();
+
+ const std::string &Type() const {
+ return type;
+ }
+
+ bool IsEmbedded() const {
+ return contentLength > 0;
+ }
+
+ const std::string &FileName() const {
+ return fileName;
+ }
+
+ const std::string &RelativeFilename() const {
+ return relativeFileName;
+ }
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ const uint8_t *Content() const {
+ return content;
+ }
+
+ uint64_t ContentLength() const {
+ return contentLength;
+ }
+
+ uint8_t *RelinquishContent() {
+ uint8_t *ptr = content;
+ content = 0;
+ return ptr;
+ }
+
+ bool operator==(const Video &other) const {
+ return (
+ type == other.type && relativeFileName == other.relativeFileName && fileName == other.fileName);
+ }
+
+ bool operator<(const Video &other) const {
+ return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName);
+ }
+
+private:
+ std::string type;
+ std::string relativeFileName;
+ std::string fileName;
+ const PropertyTable *props = nullptr;
+
+ uint64_t contentLength = 0;
+ uint8_t *content = nullptr;
+};
+
+/** DOM class for generic FBX materials */
+class Material : public Object {
+public:
+ Material(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Material();
+
+ const std::string &GetShadingModel() const {
+ return shading;
+ }
+
+ bool IsMultilayer() const {
+ return multilayer;
+ }
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ const TextureMap &Textures() const {
+ return textures;
+ }
+
+ const LayeredTextureMap &LayeredTextures() const {
+ return layeredTextures;
+ }
+
+private:
+ std::string shading;
+ bool multilayer;
+ const PropertyTable *props;
+
+ TextureMap textures;
+ LayeredTextureMap layeredTextures;
+};
+
+// signed int keys (this can happen!)
+typedef std::vector<int64_t> KeyTimeList;
+typedef std::vector<float> KeyValueList;
+
+/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
+class AnimationCurve : public Object {
+public:
+ AnimationCurve(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc);
+ virtual ~AnimationCurve();
+
+ /** get list of keyframe positions (time).
+ * Invariant: |GetKeys()| > 0 */
+ const KeyTimeList &GetKeys() const {
+ return keys;
+ }
+
+ /** get list of keyframe values.
+ * Invariant: |GetKeys()| == |GetValues()| && |GetKeys()| > 0*/
+ const KeyValueList &GetValues() const {
+ return values;
+ }
+
+ const std::map<int64_t, float> &GetValueTimeTrack() const {
+ return keyvalues;
+ }
+
+ const std::vector<float> &GetAttributes() const {
+ return attributes;
+ }
+
+ const std::vector<unsigned int> &GetFlags() const {
+ return flags;
+ }
+
+private:
+ KeyTimeList keys;
+ KeyValueList values;
+ std::vector<float> attributes;
+ std::map<int64_t, float> keyvalues;
+ std::vector<unsigned int> flags;
+};
+
+/* Typedef for pointers for the animation handler */
+typedef std::shared_ptr<AnimationCurve> AnimationCurvePtr;
+typedef std::weak_ptr<AnimationCurve> AnimationCurveWeakPtr;
+typedef std::map<std::string, const AnimationCurve *> AnimationMap;
+
+/* Animation Curve node ptr */
+typedef std::shared_ptr<AnimationCurveNode> AnimationCurveNodePtr;
+typedef std::weak_ptr<AnimationCurveNode> AnimationCurveNodeWeakPtr;
+
+/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
+class AnimationCurveNode : public Object {
+public:
+ /* the optional white list specifies a list of property names for which the caller
+ wants animations for. If the curve node does not match one of these, std::range_error
+ will be thrown. */
+ AnimationCurveNode(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc,
+ const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
+
+ virtual ~AnimationCurveNode();
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ const AnimationMap &Curves() const;
+
+ /** Object the curve is assigned to, this can be NULL if the
+ * target object has no DOM representation or could not
+ * be read for other reasons.*/
+ Object *Target() const {
+ return target;
+ }
+
+ Model *TargetAsModel() const {
+ return dynamic_cast<Model *>(target);
+ }
+
+ NodeAttribute *TargetAsNodeAttribute() const {
+ return dynamic_cast<NodeAttribute *>(target);
+ }
+
+ /** Property of Target() that is being animated*/
+ const std::string &TargetProperty() const {
+ return prop;
+ }
+
+private:
+ Object *target = nullptr;
+ const PropertyTable *props;
+ mutable AnimationMap curves;
+ std::string prop;
+ const Document &doc;
+};
+
+typedef std::vector<const AnimationCurveNode *> AnimationCurveNodeList;
+
+typedef std::shared_ptr<AnimationLayer> AnimationLayerPtr;
+typedef std::weak_ptr<AnimationLayer> AnimationLayerWeakPtr;
+typedef std::vector<const AnimationLayer *> AnimationLayerList;
+
+/** Represents a FBX animation layer (i.e. a list of node animations) */
+class AnimationLayer : public Object {
+public:
+ AnimationLayer(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc);
+ virtual ~AnimationLayer();
+
+ const PropertyTable *Props() const {
+ //ai_assert(props.get());
+ return props;
+ }
+
+ /* the optional white list specifies a list of property names for which the caller
+ wants animations for. Curves not matching this list will not be added to the
+ animation layer. */
+ const AnimationCurveNodeList Nodes(const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0) const;
+
+private:
+ const PropertyTable *props;
+ const Document &doc;
+};
+
+/** Represents a FBX animation stack (i.e. a list of animation layers) */
+class AnimationStack : public Object {
+public:
+ AnimationStack(uint64_t id, const ElementPtr element, const std::string &name, const Document &doc);
+ virtual ~AnimationStack();
+
+ fbx_simple_property(LocalStart, int64_t, 0L);
+ fbx_simple_property(LocalStop, int64_t, 0L);
+ fbx_simple_property(ReferenceStart, int64_t, 0L);
+ fbx_simple_property(ReferenceStop, int64_t, 0L);
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ const AnimationLayerList &Layers() const {
+ return layers;
+ }
+
+private:
+ const PropertyTable *props = nullptr;
+ AnimationLayerList layers;
+};
+
+/** DOM class for deformers */
+class Deformer : public Object {
+public:
+ Deformer(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+ virtual ~Deformer();
+
+ const PropertyTable *Props() const {
+ //ai_assert(props.get());
+ return props;
+ }
+
+private:
+ const PropertyTable *props;
+};
+
+/** Constraints are from Maya they can help us with BoneAttachments :) **/
+class Constraint : public Object {
+public:
+ Constraint(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+ virtual ~Constraint();
+
+private:
+ const PropertyTable *props;
+};
+
+typedef std::vector<float> WeightArray;
+typedef std::vector<unsigned int> WeightIndexArray;
+
+/** DOM class for BlendShapeChannel deformers */
+class BlendShapeChannel : public Deformer {
+public:
+ BlendShapeChannel(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~BlendShapeChannel();
+
+ float DeformPercent() const {
+ return percent;
+ }
+
+ const WeightArray &GetFullWeights() const {
+ return fullWeights;
+ }
+
+ const std::vector<const ShapeGeometry *> &GetShapeGeometries() const {
+ return shapeGeometries;
+ }
+
+private:
+ float percent;
+ WeightArray fullWeights;
+ std::vector<const ShapeGeometry *> shapeGeometries;
+};
+
+/** DOM class for BlendShape deformers */
+class BlendShape : public Deformer {
+public:
+ BlendShape(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~BlendShape();
+
+ const std::vector<const BlendShapeChannel *> &BlendShapeChannels() const {
+ return blendShapeChannels;
+ }
+
+private:
+ std::vector<const BlendShapeChannel *> blendShapeChannels;
+};
+
+/** DOM class for skin deformer clusters (aka sub-deformers) */
+class Cluster : public Deformer {
+public:
+ Cluster(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Cluster();
+
+ /** get the list of deformer weights associated with this cluster.
+ * Use #GetIndices() to get the associated vertices. Both arrays
+ * have the same size (and may also be empty). */
+ const std::vector<float> &GetWeights() const {
+ return weights;
+ }
+
+ /** get indices into the vertex data of the geometry associated
+ * with this cluster. Use #GetWeights() to get the associated weights.
+ * Both arrays have the same size (and may also be empty). */
+ const std::vector<unsigned int> &GetIndices() const {
+ return indices;
+ }
+
+ /** */
+ const Transform &GetTransform() const {
+ return transform;
+ }
+
+ const Transform &TransformLink() const {
+ return transformLink;
+ }
+
+ const Model *TargetNode() const {
+ return node;
+ }
+
+ const Transform &TransformAssociateModel() const {
+ return transformAssociateModel;
+ }
+
+ bool TransformAssociateModelValid() const {
+ return valid_transformAssociateModel;
+ }
+
+ // property is not in the fbx file
+ // if the cluster has an associate model
+ // we then have an additive type
+ enum SkinLinkMode {
+ SkinLinkMode_Normalized = 0,
+ SkinLinkMode_Additive = 1
+ };
+
+ SkinLinkMode GetLinkMode() {
+ return link_mode;
+ }
+
+private:
+ std::vector<float> weights;
+ std::vector<unsigned int> indices;
+
+ Transform transform;
+ Transform transformLink;
+ Transform transformAssociateModel;
+ SkinLinkMode link_mode;
+ bool valid_transformAssociateModel;
+ const Model *node = nullptr;
+};
+
+/** DOM class for skin deformers */
+class Skin : public Deformer {
+public:
+ Skin(uint64_t id, const ElementPtr element, const Document &doc, const std::string &name);
+
+ virtual ~Skin();
+
+ float DeformAccuracy() const {
+ return accuracy;
+ }
+
+ const std::vector<const Cluster *> &Clusters() const {
+ return clusters;
+ }
+
+ enum SkinType {
+ Skin_Rigid = 0,
+ Skin_Linear,
+ Skin_DualQuaternion,
+ Skin_Blend
+ };
+
+ const SkinType &GetSkinType() const {
+ return skinType;
+ }
+
+private:
+ float accuracy;
+ SkinType skinType;
+ std::vector<const Cluster *> clusters;
+};
+
+/** Represents a link between two FBX objects. */
+class Connection {
+public:
+ Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string &prop, const Document &doc);
+ ~Connection();
+
+ // note: a connection ensures that the source and dest objects exist, but
+ // not that they have DOM representations, so the return value of one of
+ // these functions can still be NULL.
+ Object *SourceObject() const;
+ Object *DestinationObject() const;
+
+ // these, however, are always guaranteed to be valid
+ LazyObject *LazySourceObject() const;
+ LazyObject *LazyDestinationObject() const;
+
+ /** return the name of the property the connection is attached to.
+ * this is an empty string for object to object (OO) connections. */
+ const std::string &PropertyName() const {
+ return prop;
+ }
+
+ uint64_t InsertionOrder() const {
+ return insertionOrder;
+ }
+
+ int CompareTo(const Connection *c) const {
+ //ai_assert(nullptr != c);
+
+ // note: can't subtract because this would overflow uint64_t
+ if (InsertionOrder() > c->InsertionOrder()) {
+ return 1;
+ } else if (InsertionOrder() < c->InsertionOrder()) {
+ return -1;
+ }
+ return 0;
+ }
+
+ bool Compare(const Connection *c) const {
+ //ai_assert(nullptr != c);
+
+ return InsertionOrder() < c->InsertionOrder();
+ }
+
+public:
+ uint64_t insertionOrder;
+ const std::string prop;
+
+ uint64_t src, dest;
+ const Document &doc;
+};
+
+// XXX again, unique_ptr would be useful. shared_ptr is too
+// bloated since the objects have a well-defined single owner
+// during their entire lifetime (Document). FBX files have
+// up to many thousands of objects (most of which we never use),
+// so the memory overhead for them should be kept at a minimum.
+typedef std::map<uint64_t, LazyObject *> ObjectMap;
+typedef std::map<std::string, const PropertyTable *> PropertyTemplateMap;
+typedef std::multimap<uint64_t, const Connection *> ConnectionMap;
+
+/** DOM class for global document settings, a single instance per document can
+ * be accessed via Document.Globals(). */
+class FileGlobalSettings {
+public:
+ FileGlobalSettings(const Document &doc, const PropertyTable *props);
+
+ ~FileGlobalSettings();
+
+ const PropertyTable *Props() const {
+ return props;
+ }
+
+ const Document &GetDocument() const {
+ return doc;
+ }
+
+ fbx_simple_property(UpAxis, int, 1);
+ fbx_simple_property(UpAxisSign, int, 1);
+ fbx_simple_property(FrontAxis, int, 2);
+ fbx_simple_property(FrontAxisSign, int, 1);
+ fbx_simple_property(CoordAxis, int, 0);
+ fbx_simple_property(CoordAxisSign, int, 1);
+ fbx_simple_property(OriginalUpAxis, int, 0);
+ fbx_simple_property(OriginalUpAxisSign, int, 1);
+ fbx_simple_property(UnitScaleFactor, float, 1);
+ fbx_simple_property(OriginalUnitScaleFactor, float, 1);
+ fbx_simple_property(AmbientColor, Vector3, Vector3(0, 0, 0));
+ fbx_simple_property(DefaultCamera, std::string, "");
+
+ enum FrameRate {
+ FrameRate_DEFAULT = 0,
+ FrameRate_120 = 1,
+ FrameRate_100 = 2,
+ FrameRate_60 = 3,
+ FrameRate_50 = 4,
+ FrameRate_48 = 5,
+ FrameRate_30 = 6,
+ FrameRate_30_DROP = 7,
+ FrameRate_NTSC_DROP_FRAME = 8,
+ FrameRate_NTSC_FULL_FRAME = 9,
+ FrameRate_PAL = 10,
+ FrameRate_CINEMA = 11,
+ FrameRate_1000 = 12,
+ FrameRate_CINEMA_ND = 13,
+ FrameRate_CUSTOM = 14,
+
+ FrameRate_MAX // end-of-enum sentinel
+ };
+
+ fbx_simple_enum_property(TimeMode, FrameRate, FrameRate_DEFAULT);
+ fbx_simple_property(TimeSpanStart, uint64_t, 0L);
+ fbx_simple_property(TimeSpanStop, uint64_t, 0L);
+ fbx_simple_property(CustomFrameRate, float, -1.0f);
+
+private:
+ const PropertyTable *props = nullptr;
+ const Document &doc;
+};
+
+/** DOM root for a FBX file */
+class Document {
+public:
+ Document(const Parser &parser, const ImportSettings &settings);
+
+ ~Document();
+
+ LazyObject *GetObject(uint64_t id) const;
+
+ bool IsSafeToImport() const {
+ return SafeToImport;
+ }
+
+ bool IsBinary() const {
+ return parser.IsBinary();
+ }
+
+ unsigned int FBXVersion() const {
+ return fbxVersion;
+ }
+
+ const std::string &Creator() const {
+ return creator;
+ }
+
+ // elements (in this order): Year, Month, Day, Hour, Second, Millisecond
+ const unsigned int *CreationTimeStamp() const {
+ return creationTimeStamp;
+ }
+
+ const FileGlobalSettings *GlobalSettingsPtr() const {
+ return globals.get();
+ }
+
+ const PropertyTable *GetMetadataProperties() const {
+ return metadata_properties;
+ }
+
+ const PropertyTemplateMap &Templates() const {
+ return templates;
+ }
+
+ const ObjectMap &Objects() const {
+ return objects;
+ }
+
+ const ImportSettings &Settings() const {
+ return settings;
+ }
+
+ const ConnectionMap &ConnectionsBySource() const {
+ return src_connections;
+ }
+
+ const ConnectionMap &ConnectionsByDestination() const {
+ return dest_connections;
+ }
+
+ // note: the implicit rule in all DOM classes is to always resolve
+ // from destination to source (since the FBX object hierarchy is,
+ // with very few exceptions, a DAG, this avoids cycles). In all
+ // cases that may involve back-facing edges in the object graph,
+ // use LazyObject::IsBeingConstructed() to check.
+
+ std::vector<const Connection *> GetConnectionsBySourceSequenced(uint64_t source) const;
+ std::vector<const Connection *> GetConnectionsByDestinationSequenced(uint64_t dest) const;
+
+ std::vector<const Connection *> GetConnectionsBySourceSequenced(uint64_t source, const char *classname) const;
+ std::vector<const Connection *> GetConnectionsByDestinationSequenced(uint64_t dest, const char *classname) const;
+
+ std::vector<const Connection *> GetConnectionsBySourceSequenced(uint64_t source,
+ const char *const *classnames, size_t count) const;
+ std::vector<const Connection *> GetConnectionsByDestinationSequenced(uint64_t dest,
+ const char *const *classnames,
+ size_t count) const;
+
+ const std::vector<const AnimationStack *> &AnimationStacks() const;
+ const std::vector<uint64_t> &GetAnimationStackIDs() const {
+ return animationStacks;
+ }
+
+ const std::vector<uint64_t> &GetConstraintStackIDs() const {
+ return constraints;
+ }
+
+ const std::vector<uint64_t> &GetBindPoseIDs() const {
+ return bind_poses;
+ };
+
+ const std::vector<uint64_t> &GetMaterialIDs() const {
+ return materials;
+ };
+
+ const std::vector<uint64_t> &GetSkinIDs() const {
+ return skins;
+ }
+
+private:
+ std::vector<const Connection *> GetConnectionsSequenced(uint64_t id, const ConnectionMap &) const;
+ std::vector<const Connection *> GetConnectionsSequenced(uint64_t id, bool is_src,
+ const ConnectionMap &,
+ const char *const *classnames,
+ size_t count) const;
+ bool ReadHeader();
+ void ReadObjects();
+ void ReadPropertyTemplates();
+ void ReadConnections();
+ void ReadGlobalSettings();
+
+private:
+ const ImportSettings &settings;
+
+ ObjectMap objects;
+ const Parser &parser;
+ bool SafeToImport = false;
+
+ PropertyTemplateMap templates;
+ ConnectionMap src_connections;
+ ConnectionMap dest_connections;
+
+ unsigned int fbxVersion = 0;
+ std::string creator;
+ unsigned int creationTimeStamp[7] = { 0 };
+
+ std::vector<uint64_t> animationStacks;
+ std::vector<uint64_t> bind_poses;
+ // constraints aren't in the tree / at least they are not easy to access.
+ std::vector<uint64_t> constraints;
+ std::vector<uint64_t> materials;
+ std::vector<uint64_t> skins;
+ mutable std::vector<const AnimationStack *> animationStacksResolved;
+ PropertyTable *metadata_properties = nullptr;
+ std::shared_ptr<FileGlobalSettings> globals = nullptr;
+};
+} // namespace FBXDocParser
+
+namespace std {
+template <>
+struct hash<const FBXDocParser::Video> {
+ std::size_t operator()(const FBXDocParser::Video &video) const {
+ using std::hash;
+ using std::size_t;
+ using std::string;
+
+ size_t res = 17;
+ res = res * 31 + hash<string>()(video.Name());
+ res = res * 31 + hash<string>()(video.RelativeFilename());
+ res = res * 31 + hash<string>()(video.Type());
+
+ return res;
+ }
+};
+} // namespace std
+
+#endif // FBX_DOCUMENT_H