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