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