Coverage Report

Created: 2026-02-05 07:01

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