1 /** Helper structures for the Collada loader */ 2 3 /* 4 Open Asset Import Library (assimp) 5 ---------------------------------------------------------------------- 6 7 Copyright (c) 2006-2017, assimp team 8 9 All rights reserved. 10 11 Redistribution and use of this software in source and binary forms, 12 with or without modification, are permitted provided that the 13 following conditions are met: 14 15 * Redistributions of source code must retain the above 16 copyright notice, this list of conditions and the 17 following disclaimer. 18 19 * Redistributions in binary form must reproduce the above 20 copyright notice, this list of conditions and the 21 following disclaimer in the documentation and/or other 22 materials provided with the distribution. 23 24 * Neither the name of the assimp team, nor the names of its 25 contributors may be used to endorse or promote products 26 derived from this software without specific prior 27 written permission of the assimp team. 28 29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 41 ---------------------------------------------------------------------- 42 */ 43 44 #ifndef AI_COLLADAHELPER_H_INC 45 #define AI_COLLADAHELPER_H_INC 46 47 #include <map> 48 #include <vector> 49 #include <stdint.h> 50 #include <assimp/light.h> 51 #include <assimp/mesh.h> 52 #include <assimp/material.h> 53 54 struct aiMaterial; 55 56 namespace Assimp { 57 namespace Collada { 58 59 /** Collada file versions which evolved during the years ... */ 60 enum FormatVersion 61 { 62 FV_1_5_n, 63 FV_1_4_n, 64 FV_1_3_n 65 }; 66 67 68 /** Transformation types that can be applied to a node */ 69 enum TransformType 70 { 71 TF_LOOKAT, 72 TF_ROTATE, 73 TF_TRANSLATE, 74 TF_SCALE, 75 TF_SKEW, 76 TF_MATRIX 77 }; 78 79 /** Different types of input data to a vertex or face */ 80 enum InputType 81 { 82 IT_Invalid, 83 IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data. 84 IT_Position, 85 IT_Normal, 86 IT_Texcoord, 87 IT_Color, 88 IT_Tangent, 89 IT_Bitangent 90 }; 91 92 /** Supported controller types */ 93 enum ControllerType 94 { 95 Skin, 96 Morph 97 }; 98 99 /** Supported morph methods */ 100 enum MorphMethod 101 { 102 Normalized, 103 Relative 104 }; 105 106 107 /** Contains all data for one of the different transformation types */ 108 struct Transform 109 { 110 std::string mID; ///< SID of the transform step, by which anim channels address their target node 111 TransformType mType; 112 ai_real f[16]; ///< Interpretation of data depends on the type of the transformation 113 }; 114 115 /** A collada camera. */ 116 struct Camera 117 { CameraCamera118 Camera() 119 : mOrtho (false) 120 , mHorFov (10e10f) 121 , mVerFov (10e10f) 122 , mAspect (10e10f) 123 , mZNear (0.1f) 124 , mZFar (1000.f) 125 {} 126 127 // Name of camera 128 std::string mName; 129 130 // True if it is an orthografic camera 131 bool mOrtho; 132 133 //! Horizontal field of view in degrees 134 ai_real mHorFov; 135 136 //! Vertical field of view in degrees 137 ai_real mVerFov; 138 139 //! Screen aspect 140 ai_real mAspect; 141 142 //! Near& far z 143 ai_real mZNear, mZFar; 144 }; 145 146 #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f 147 148 /** A collada light source. */ 149 struct Light 150 { LightLight151 Light() 152 : mType (aiLightSource_UNDEFINED) 153 , mAttConstant (1.f) 154 , mAttLinear (0.f) 155 , mAttQuadratic (0.f) 156 , mFalloffAngle (180.f) 157 , mFalloffExponent (0.f) 158 , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) 159 , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) 160 , mIntensity (1.f) 161 {} 162 163 //! Type of the light source aiLightSourceType + ambient 164 unsigned int mType; 165 166 //! Color of the light 167 aiColor3D mColor; 168 169 //! Light attenuation 170 ai_real mAttConstant,mAttLinear,mAttQuadratic; 171 172 //! Spot light falloff 173 ai_real mFalloffAngle; 174 ai_real mFalloffExponent; 175 176 // ----------------------------------------------------- 177 // FCOLLADA extension from here 178 179 //! ... related stuff from maja and max extensions 180 ai_real mPenumbraAngle; 181 ai_real mOuterAngle; 182 183 //! Common light intensity 184 ai_real mIntensity; 185 }; 186 187 /** Short vertex index description */ 188 struct InputSemanticMapEntry 189 { InputSemanticMapEntryInputSemanticMapEntry190 InputSemanticMapEntry() 191 : mSet(0) 192 , mType(IT_Invalid) 193 {} 194 195 //! Index of set, optional 196 unsigned int mSet; 197 198 //! Type of referenced vertex input 199 InputType mType; 200 }; 201 202 /** Table to map from effect to vertex input semantics */ 203 struct SemanticMappingTable 204 { 205 //! Name of material 206 std::string mMatName; 207 208 //! List of semantic map commands, grouped by effect semantic name 209 std::map<std::string, InputSemanticMapEntry> mMap; 210 211 //! For std::find 212 bool operator == (const std::string& s) const { 213 return s == mMatName; 214 } 215 }; 216 217 /** A reference to a mesh inside a node, including materials assigned to the various subgroups. 218 * The ID refers to either a mesh or a controller which specifies the mesh 219 */ 220 struct MeshInstance 221 { 222 ///< ID of the mesh or controller to be instanced 223 std::string mMeshOrController; 224 225 ///< Map of materials by the subgroup ID they're applied to 226 std::map<std::string, SemanticMappingTable> mMaterials; 227 }; 228 229 /** A reference to a camera inside a node*/ 230 struct CameraInstance 231 { 232 ///< ID of the camera 233 std::string mCamera; 234 }; 235 236 /** A reference to a light inside a node*/ 237 struct LightInstance 238 { 239 ///< ID of the camera 240 std::string mLight; 241 }; 242 243 /** A reference to a node inside a node*/ 244 struct NodeInstance 245 { 246 ///< ID of the node 247 std::string mNode; 248 }; 249 250 /** A node in a scene hierarchy */ 251 struct Node 252 { 253 std::string mName; 254 std::string mID; 255 std::string mSID; 256 Node* mParent; 257 std::vector<Node*> mChildren; 258 259 /** Operations in order to calculate the resulting transformation to parent. */ 260 std::vector<Transform> mTransforms; 261 262 /** Meshes at this node */ 263 std::vector<MeshInstance> mMeshes; 264 265 /** Lights at this node */ 266 std::vector<LightInstance> mLights; 267 268 /** Cameras at this node */ 269 std::vector<CameraInstance> mCameras; 270 271 /** Node instances at this node */ 272 std::vector<NodeInstance> mNodeInstances; 273 274 /** Rootnodes: Name of primary camera, if any */ 275 std::string mPrimaryCamera; 276 277 //! Constructor. Begin with a zero parent NodeNode278 Node() { 279 mParent = NULL; 280 } 281 282 //! Destructor: delete all children subsequently ~NodeNode283 ~Node() { 284 for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) 285 delete *it; 286 } 287 }; 288 289 /** Data source array: either floats or strings */ 290 struct Data 291 { 292 bool mIsStringArray; 293 std::vector<ai_real> mValues; 294 std::vector<std::string> mStrings; 295 }; 296 297 /** Accessor to a data array */ 298 struct Accessor 299 { 300 size_t mCount; // in number of objects 301 size_t mSize; // size of an object, in elements (floats or strings, mostly 1) 302 size_t mOffset; // in number of values 303 size_t mStride; // Stride in number of values 304 std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore. 305 size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on. 306 // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. 307 std::string mSource; // URL of the source array 308 mutable const Data* mData; // Pointer to the source array, if resolved. NULL else 309 AccessorAccessor310 Accessor() 311 { 312 mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL; 313 mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; 314 } 315 }; 316 317 /** A single face in a mesh */ 318 struct Face 319 { 320 std::vector<size_t> mIndices; 321 }; 322 323 /** An input channel for mesh data, referring to a single accessor */ 324 struct InputChannel 325 { 326 InputType mType; // Type of the data 327 size_t mIndex; // Optional index, if multiple sets of the same data type are given 328 size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. 329 std::string mAccessor; // ID of the accessor where to read the actual values from. 330 mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else 331 InputChannelInputChannel332 InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; } 333 }; 334 335 /** Subset of a mesh with a certain material */ 336 struct SubMesh 337 { 338 std::string mMaterial; ///< subgroup identifier 339 size_t mNumFaces; ///< number of faces in this submesh 340 }; 341 342 /** Contains data for a single mesh */ 343 struct Mesh 344 { MeshMesh345 Mesh() 346 { 347 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) 348 mNumUVComponents[i] = 2; 349 } 350 351 std::string mName; 352 353 // just to check if there's some sophisticated addressing involved... 354 // which we don't support, and therefore should warn about. 355 std::string mVertexID; 356 357 // Vertex data addressed by vertex indices 358 std::vector<InputChannel> mPerVertexData; 359 360 // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed 361 std::vector<aiVector3D> mPositions; 362 std::vector<aiVector3D> mNormals; 363 std::vector<aiVector3D> mTangents; 364 std::vector<aiVector3D> mBitangents; 365 std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; 366 std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; 367 368 unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; 369 370 // Faces. Stored are only the number of vertices for each face. 371 // 1 == point, 2 == line, 3 == triangle, 4+ == poly 372 std::vector<size_t> mFaceSize; 373 374 // Position indices for all faces in the sequence given in mFaceSize - 375 // necessary for bone weight assignment 376 std::vector<size_t> mFacePosIndices; 377 378 // Submeshes in this mesh, each with a given material 379 std::vector<SubMesh> mSubMeshes; 380 }; 381 382 /** Which type of primitives the ReadPrimitives() function is going to read */ 383 enum PrimitiveType 384 { 385 Prim_Invalid, 386 Prim_Lines, 387 Prim_LineStrip, 388 Prim_Triangles, 389 Prim_TriStrips, 390 Prim_TriFans, 391 Prim_Polylist, 392 Prim_Polygon 393 }; 394 395 /** A skeleton controller to deform a mesh with the use of joints */ 396 struct Controller 397 { 398 // controller type 399 ControllerType mType; 400 401 // Morphing method if type is Morph 402 MorphMethod mMethod; 403 404 // the URL of the mesh deformed by the controller. 405 std::string mMeshId; 406 407 // accessor URL of the joint names 408 std::string mJointNameSource; 409 410 ///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases 411 ai_real mBindShapeMatrix[16]; 412 413 // accessor URL of the joint inverse bind matrices 414 std::string mJointOffsetMatrixSource; 415 416 // input channel: joint names. 417 InputChannel mWeightInputJoints; 418 // input channel: joint weights 419 InputChannel mWeightInputWeights; 420 421 // Number of weights per vertex. 422 std::vector<size_t> mWeightCounts; 423 424 // JointIndex-WeightIndex pairs for all vertices 425 std::vector< std::pair<size_t, size_t> > mWeights; 426 427 std::string mMorphTarget; 428 std::string mMorphWeight; 429 }; 430 431 /** A collada material. Pretty much the only member is a reference to an effect. */ 432 struct Material 433 { 434 std::string mName; 435 std::string mEffect; 436 }; 437 438 /** Type of the effect param */ 439 enum ParamType 440 { 441 Param_Sampler, 442 Param_Surface 443 }; 444 445 /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */ 446 struct EffectParam 447 { 448 ParamType mType; 449 std::string mReference; // to which other thing the param is referring to. 450 }; 451 452 /** Shading type supported by the standard effect spec of Collada */ 453 enum ShadeType 454 { 455 Shade_Invalid, 456 Shade_Constant, 457 Shade_Lambert, 458 Shade_Phong, 459 Shade_Blinn 460 }; 461 462 /** Represents a texture sampler in collada */ 463 struct Sampler 464 { SamplerSampler465 Sampler() 466 : mWrapU (true) 467 , mWrapV (true) 468 , mMirrorU () 469 , mMirrorV () 470 , mOp (aiTextureOp_Multiply) 471 , mUVId (UINT_MAX) 472 , mWeighting (1.f) 473 , mMixWithPrevious (1.f) 474 {} 475 476 /** Name of image reference 477 */ 478 std::string mName; 479 480 /** Wrap U? 481 */ 482 bool mWrapU; 483 484 /** Wrap V? 485 */ 486 bool mWrapV; 487 488 /** Mirror U? 489 */ 490 bool mMirrorU; 491 492 /** Mirror V? 493 */ 494 bool mMirrorV; 495 496 /** Blend mode 497 */ 498 aiTextureOp mOp; 499 500 /** UV transformation 501 */ 502 aiUVTransform mTransform; 503 504 /** Name of source UV channel 505 */ 506 std::string mUVChannel; 507 508 /** Resolved UV channel index or UINT_MAX if not known 509 */ 510 unsigned int mUVId; 511 512 // OKINO/MAX3D extensions from here 513 // ------------------------------------------------------- 514 515 /** Weighting factor 516 */ 517 ai_real mWeighting; 518 519 /** Mixing factor from OKINO 520 */ 521 ai_real mMixWithPrevious; 522 }; 523 524 /** A collada effect. Can contain about anything according to the Collada spec, 525 but we limit our version to a reasonable subset. */ 526 struct Effect 527 { 528 // Shading mode 529 ShadeType mShadeType; 530 531 // Colors 532 aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular, 533 mTransparent, mReflective; 534 535 // Textures 536 Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular, 537 mTexTransparent, mTexBump, mTexReflective; 538 539 // Scalar factory 540 ai_real mShininess, mRefractIndex, mReflectivity; 541 ai_real mTransparency; 542 bool mHasTransparency; 543 bool mRGBTransparency; 544 bool mInvertTransparency; 545 546 // local params referring to each other by their SID 547 typedef std::map<std::string, Collada::EffectParam> ParamLibrary; 548 ParamLibrary mParams; 549 550 // MAX3D extensions 551 // --------------------------------------------------------- 552 // Double-sided? 553 bool mDoubleSided, mWireframe, mFaceted; 554 EffectEffect555 Effect() 556 : mShadeType (Shade_Phong) 557 , mEmissive ( 0, 0, 0, 1) 558 , mAmbient ( 0.1f, 0.1f, 0.1f, 1) 559 , mDiffuse ( 0.6f, 0.6f, 0.6f, 1) 560 , mSpecular ( 0.4f, 0.4f, 0.4f, 1) 561 , mTransparent ( 0, 0, 0, 1) 562 , mShininess (10.0f) 563 , mRefractIndex (1.f) 564 , mReflectivity (0.f) 565 , mTransparency (1.f) 566 , mHasTransparency (false) 567 , mRGBTransparency(false) 568 , mInvertTransparency(false) 569 , mDoubleSided (false) 570 , mWireframe (false) 571 , mFaceted (false) 572 { 573 } 574 }; 575 576 /** An image, meaning texture */ 577 struct Image 578 { 579 std::string mFileName; 580 581 /** If image file name is zero, embedded image data 582 */ 583 std::vector<uint8_t> mImageData; 584 585 /** If image file name is zero, file format of 586 * embedded image data. 587 */ 588 std::string mEmbeddedFormat; 589 590 }; 591 592 /** An animation channel. */ 593 struct AnimationChannel 594 { 595 /** URL of the data to animate. Could be about anything, but we support only the 596 * "NodeID/TransformID.SubElement" notation 597 */ 598 std::string mTarget; 599 600 /** Source URL of the time values. Collada calls them "input". Meh. */ 601 std::string mSourceTimes; 602 /** Source URL of the value values. Collada calls them "output". */ 603 std::string mSourceValues; 604 /** Source URL of the IN_TANGENT semantic values. */ 605 std::string mInTanValues; 606 /** Source URL of the OUT_TANGENT semantic values. */ 607 std::string mOutTanValues; 608 /** Source URL of the INTERPOLATION semantic values. */ 609 std::string mInterpolationValues; 610 }; 611 612 /** An animation. Container for 0-x animation channels or 0-x animations */ 613 struct Animation 614 { 615 /** Anim name */ 616 std::string mName; 617 618 /** the animation channels, if any */ 619 std::vector<AnimationChannel> mChannels; 620 621 /** the sub-animations, if any */ 622 std::vector<Animation*> mSubAnims; 623 624 /** Destructor */ ~AnimationAnimation625 ~Animation() 626 { 627 for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) 628 delete *it; 629 } 630 631 /** Collect all channels in the animation hierarchy into a single channel list. */ CollectChannelsRecursivelyAnimation632 void CollectChannelsRecursively(std::vector<AnimationChannel> &channels) 633 { 634 channels.insert(channels.end(), mChannels.begin(), mChannels.end()); 635 636 for (std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) 637 { 638 Animation *pAnim = (*it); 639 640 pAnim->CollectChannelsRecursively(channels); 641 } 642 } 643 644 /** Combine all single-channel animations' channel into the same (parent) animation channel list. */ CombineSingleChannelAnimationsAnimation645 void CombineSingleChannelAnimations() 646 { 647 CombineSingleChannelAnimationsRecursively(this); 648 } 649 CombineSingleChannelAnimationsRecursivelyAnimation650 void CombineSingleChannelAnimationsRecursively(Animation *pParent) 651 { 652 for (std::vector<Animation*>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) 653 { 654 Animation *anim = *it; 655 656 CombineSingleChannelAnimationsRecursively(anim); 657 658 if (anim->mChannels.size() == 1) 659 { 660 pParent->mChannels.push_back(anim->mChannels[0]); 661 662 it = pParent->mSubAnims.erase(it); 663 664 delete anim; 665 } 666 else 667 { 668 ++it; 669 } 670 } 671 } 672 }; 673 674 /** Description of a collada animation channel which has been determined to affect the current node */ 675 struct ChannelEntry 676 { 677 const Collada::AnimationChannel* mChannel; ///> the source channel 678 std::string mTargetId; 679 std::string mTransformId; // the ID of the transformation step of the node which is influenced 680 size_t mTransformIndex; // Index into the node's transform chain to apply the channel to 681 size_t mSubElement; // starting index inside the transform data 682 683 // resolved data references 684 const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values 685 const Collada::Data* mTimeData; ///> Source data array for the time values 686 const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values 687 const Collada::Data* mValueData; ///> Source datat array for the key value values 688 ChannelEntryChannelEntry689 ChannelEntry() 690 : mChannel() 691 , mTransformIndex() 692 , mSubElement() 693 , mTimeAccessor() 694 , mTimeData() 695 , mValueAccessor() 696 , mValueData() 697 {} 698 }; 699 700 } // end of namespace Collada 701 } // end of namespace Assimp 702 703 #endif // AI_COLLADAHELPER_H_INC 704