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