nuclear@0: /** Helper structures for the Collada loader */ nuclear@0: nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: #ifndef AI_COLLADAHELPER_H_INC nuclear@0: #define AI_COLLADAHELPER_H_INC nuclear@0: nuclear@0: namespace Assimp { nuclear@0: namespace Collada { nuclear@0: nuclear@0: /** Collada file versions which evolved during the years ... */ nuclear@0: enum FormatVersion nuclear@0: { nuclear@0: FV_1_5_n, nuclear@0: FV_1_4_n, nuclear@0: FV_1_3_n nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: /** Transformation types that can be applied to a node */ nuclear@0: enum TransformType nuclear@0: { nuclear@0: TF_LOOKAT, nuclear@0: TF_ROTATE, nuclear@0: TF_TRANSLATE, nuclear@0: TF_SCALE, nuclear@0: TF_SKEW, nuclear@0: TF_MATRIX nuclear@0: }; nuclear@0: nuclear@0: /** Different types of input data to a vertex or face */ nuclear@0: enum InputType nuclear@0: { nuclear@0: IT_Invalid, nuclear@0: IT_Vertex, // special type for per-index data referring to the element carrying the per-vertex data. nuclear@0: IT_Position, nuclear@0: IT_Normal, nuclear@0: IT_Texcoord, nuclear@0: IT_Color, nuclear@0: IT_Tangent, nuclear@0: IT_Bitangent nuclear@0: }; nuclear@0: nuclear@0: /** Contains all data for one of the different transformation types */ nuclear@0: struct Transform nuclear@0: { nuclear@0: std::string mID; ///< SID of the transform step, by which anim channels address their target node nuclear@0: TransformType mType; nuclear@0: float f[16]; ///< Interpretation of data depends on the type of the transformation nuclear@0: }; nuclear@0: nuclear@0: /** A collada camera. */ nuclear@0: struct Camera nuclear@0: { nuclear@0: Camera() nuclear@0: : mOrtho (false) nuclear@0: , mHorFov (10e10f) nuclear@0: , mVerFov (10e10f) nuclear@0: , mAspect (10e10f) nuclear@0: , mZNear (0.1f) nuclear@0: , mZFar (1000.f) nuclear@0: {} nuclear@0: nuclear@0: // Name of camera nuclear@0: std::string mName; nuclear@0: nuclear@0: // True if it is an orthografic camera nuclear@0: bool mOrtho; nuclear@0: nuclear@0: //! Horizontal field of view in degrees nuclear@0: float mHorFov; nuclear@0: nuclear@0: //! Vertical field of view in degrees nuclear@0: float mVerFov; nuclear@0: nuclear@0: //! Screen aspect nuclear@0: float mAspect; nuclear@0: nuclear@0: //! Near& far z nuclear@0: float mZNear, mZFar; nuclear@0: }; nuclear@0: nuclear@0: #define aiLightSource_AMBIENT 0xdeaddead nuclear@0: #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f nuclear@0: nuclear@0: /** A collada light source. */ nuclear@0: struct Light nuclear@0: { nuclear@0: Light() nuclear@0: : mAttConstant (1.f) nuclear@0: , mAttLinear (0.f) nuclear@0: , mAttQuadratic (0.f) nuclear@0: , mFalloffAngle (180.f) nuclear@0: , mFalloffExponent (0.f) nuclear@0: , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) nuclear@0: , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) nuclear@0: , mIntensity (1.f) nuclear@0: {} nuclear@0: nuclear@0: //! Type of the light source aiLightSourceType + ambient nuclear@0: unsigned int mType; nuclear@0: nuclear@0: //! Color of the light nuclear@0: aiColor3D mColor; nuclear@0: nuclear@0: //! Light attenuation nuclear@0: float mAttConstant,mAttLinear,mAttQuadratic; nuclear@0: nuclear@0: //! Spot light falloff nuclear@0: float mFalloffAngle; nuclear@0: float mFalloffExponent; nuclear@0: nuclear@0: // ----------------------------------------------------- nuclear@0: // FCOLLADA extension from here nuclear@0: nuclear@0: //! ... related stuff from maja and max extensions nuclear@0: float mPenumbraAngle; nuclear@0: float mOuterAngle; nuclear@0: nuclear@0: //! Common light intensity nuclear@0: float mIntensity; nuclear@0: }; nuclear@0: nuclear@0: /** Short vertex index description */ nuclear@0: struct InputSemanticMapEntry nuclear@0: { nuclear@0: InputSemanticMapEntry() nuclear@0: : mSet (0) nuclear@0: {} nuclear@0: nuclear@0: //! Index of set, optional nuclear@0: unsigned int mSet; nuclear@0: nuclear@0: //! Name of referenced vertex input nuclear@0: InputType mType; nuclear@0: }; nuclear@0: nuclear@0: /** Table to map from effect to vertex input semantics */ nuclear@0: struct SemanticMappingTable nuclear@0: { nuclear@0: //! Name of material nuclear@0: std::string mMatName; nuclear@0: nuclear@0: //! List of semantic map commands, grouped by effect semantic name nuclear@0: std::map mMap; nuclear@0: nuclear@0: //! For std::find nuclear@0: bool operator == (const std::string& s) const { nuclear@0: return s == mMatName; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: /** A reference to a mesh inside a node, including materials assigned to the various subgroups. nuclear@0: * The ID refers to either a mesh or a controller which specifies the mesh nuclear@0: */ nuclear@0: struct MeshInstance nuclear@0: { nuclear@0: ///< ID of the mesh or controller to be instanced nuclear@0: std::string mMeshOrController; nuclear@0: nuclear@0: ///< Map of materials by the subgroup ID they're applied to nuclear@0: std::map mMaterials; nuclear@0: }; nuclear@0: nuclear@0: /** A reference to a camera inside a node*/ nuclear@0: struct CameraInstance nuclear@0: { nuclear@0: ///< ID of the camera nuclear@0: std::string mCamera; nuclear@0: }; nuclear@0: nuclear@0: /** A reference to a light inside a node*/ nuclear@0: struct LightInstance nuclear@0: { nuclear@0: ///< ID of the camera nuclear@0: std::string mLight; nuclear@0: }; nuclear@0: nuclear@0: /** A reference to a node inside a node*/ nuclear@0: struct NodeInstance nuclear@0: { nuclear@0: ///< ID of the node nuclear@0: std::string mNode; nuclear@0: }; nuclear@0: nuclear@0: /** A node in a scene hierarchy */ nuclear@0: struct Node nuclear@0: { nuclear@0: std::string mName; nuclear@0: std::string mID; nuclear@0: std::string mSID; nuclear@0: Node* mParent; nuclear@0: std::vector mChildren; nuclear@0: nuclear@0: /** Operations in order to calculate the resulting transformation to parent. */ nuclear@0: std::vector mTransforms; nuclear@0: nuclear@0: /** Meshes at this node */ nuclear@0: std::vector mMeshes; nuclear@0: nuclear@0: /** Lights at this node */ nuclear@0: std::vector mLights; nuclear@0: nuclear@0: /** Cameras at this node */ nuclear@0: std::vector mCameras; nuclear@0: nuclear@0: /** Node instances at this node */ nuclear@0: std::vector mNodeInstances; nuclear@0: nuclear@0: /** Rootnodes: Name of primary camera, if any */ nuclear@0: std::string mPrimaryCamera; nuclear@0: nuclear@0: //! Constructor. Begin with a zero parent nuclear@0: Node() { nuclear@0: mParent = NULL; nuclear@0: } nuclear@0: nuclear@0: //! Destructor: delete all children subsequently nuclear@0: ~Node() { nuclear@0: for( std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) nuclear@0: delete *it; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: /** Data source array: either floats or strings */ nuclear@0: struct Data nuclear@0: { nuclear@0: bool mIsStringArray; nuclear@0: std::vector mValues; nuclear@0: std::vector mStrings; nuclear@0: }; nuclear@0: nuclear@0: /** Accessor to a data array */ nuclear@0: struct Accessor nuclear@0: { nuclear@0: size_t mCount; // in number of objects nuclear@0: size_t mSize; // size of an object, in elements (floats or strings, mostly 1) nuclear@0: size_t mOffset; // in number of values nuclear@0: size_t mStride; // Stride in number of values nuclear@0: std::vector mParams; // names of the data streams in the accessors. Empty string tells to ignore. nuclear@0: size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on. nuclear@0: // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. nuclear@0: std::string mSource; // URL of the source array nuclear@0: mutable const Data* mData; // Pointer to the source array, if resolved. NULL else nuclear@0: nuclear@0: Accessor() nuclear@0: { nuclear@0: mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL; nuclear@0: mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: /** A single face in a mesh */ nuclear@0: struct Face nuclear@0: { nuclear@0: std::vector mIndices; nuclear@0: }; nuclear@0: nuclear@0: /** An input channel for mesh data, referring to a single accessor */ nuclear@0: struct InputChannel nuclear@0: { nuclear@0: InputType mType; // Type of the data nuclear@0: size_t mIndex; // Optional index, if multiple sets of the same data type are given nuclear@0: size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. nuclear@0: std::string mAccessor; // ID of the accessor where to read the actual values from. nuclear@0: mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else nuclear@0: nuclear@0: InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; } nuclear@0: }; nuclear@0: nuclear@0: /** Subset of a mesh with a certain material */ nuclear@0: struct SubMesh nuclear@0: { nuclear@0: std::string mMaterial; ///< subgroup identifier nuclear@0: size_t mNumFaces; ///< number of faces in this submesh nuclear@0: }; nuclear@0: nuclear@0: /** Contains data for a single mesh */ nuclear@0: struct Mesh nuclear@0: { nuclear@0: Mesh() nuclear@0: { nuclear@0: for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) nuclear@0: mNumUVComponents[i] = 2; nuclear@0: } nuclear@0: nuclear@0: // just to check if there's some sophisticated addressing involved... nuclear@0: // which we don't support, and therefore should warn about. nuclear@0: std::string mVertexID; nuclear@0: nuclear@0: // Vertex data addressed by vertex indices nuclear@0: std::vector mPerVertexData; nuclear@0: nuclear@0: // actual mesh data, assembled on encounter of a

element. Verbose format, not indexed nuclear@0: std::vector mPositions; nuclear@0: std::vector mNormals; nuclear@0: std::vector mTangents; nuclear@0: std::vector mBitangents; nuclear@0: std::vector mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; nuclear@0: std::vector mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; nuclear@0: nuclear@0: unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; nuclear@0: nuclear@0: // Faces. Stored are only the number of vertices for each face. nuclear@0: // 1 == point, 2 == line, 3 == triangle, 4+ == poly nuclear@0: std::vector mFaceSize; nuclear@0: nuclear@0: // Position indices for all faces in the sequence given in mFaceSize - nuclear@0: // necessary for bone weight assignment nuclear@0: std::vector mFacePosIndices; nuclear@0: nuclear@0: // Submeshes in this mesh, each with a given material nuclear@0: std::vector mSubMeshes; nuclear@0: }; nuclear@0: nuclear@0: /** Which type of primitives the ReadPrimitives() function is going to read */ nuclear@0: enum PrimitiveType nuclear@0: { nuclear@0: Prim_Invalid, nuclear@0: Prim_Lines, nuclear@0: Prim_LineStrip, nuclear@0: Prim_Triangles, nuclear@0: Prim_TriStrips, nuclear@0: Prim_TriFans, nuclear@0: Prim_Polylist, nuclear@0: Prim_Polygon nuclear@0: }; nuclear@0: nuclear@0: /** A skeleton controller to deform a mesh with the use of joints */ nuclear@0: struct Controller nuclear@0: { nuclear@0: // the URL of the mesh deformed by the controller. nuclear@0: std::string mMeshId; nuclear@0: nuclear@0: // accessor URL of the joint names nuclear@0: std::string mJointNameSource; nuclear@0: nuclear@0: ///< 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 nuclear@0: float mBindShapeMatrix[16]; nuclear@0: nuclear@0: // accessor URL of the joint inverse bind matrices nuclear@0: std::string mJointOffsetMatrixSource; nuclear@0: nuclear@0: // input channel: joint names. nuclear@0: InputChannel mWeightInputJoints; nuclear@0: // input channel: joint weights nuclear@0: InputChannel mWeightInputWeights; nuclear@0: nuclear@0: // Number of weights per vertex. nuclear@0: std::vector mWeightCounts; nuclear@0: nuclear@0: // JointIndex-WeightIndex pairs for all vertices nuclear@0: std::vector< std::pair > mWeights; nuclear@0: }; nuclear@0: nuclear@0: /** A collada material. Pretty much the only member is a reference to an effect. */ nuclear@0: struct Material nuclear@0: { nuclear@0: std::string mEffect; nuclear@0: }; nuclear@0: nuclear@0: /** Type of the effect param */ nuclear@0: enum ParamType nuclear@0: { nuclear@0: Param_Sampler, nuclear@0: Param_Surface nuclear@0: }; nuclear@0: nuclear@0: /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */ nuclear@0: struct EffectParam nuclear@0: { nuclear@0: ParamType mType; nuclear@0: std::string mReference; // to which other thing the param is referring to. nuclear@0: }; nuclear@0: nuclear@0: /** Shading type supported by the standard effect spec of Collada */ nuclear@0: enum ShadeType nuclear@0: { nuclear@0: Shade_Invalid, nuclear@0: Shade_Constant, nuclear@0: Shade_Lambert, nuclear@0: Shade_Phong, nuclear@0: Shade_Blinn nuclear@0: }; nuclear@0: nuclear@0: /** Represents a texture sampler in collada */ nuclear@0: struct Sampler nuclear@0: { nuclear@0: Sampler() nuclear@0: : mWrapU (true) nuclear@0: , mWrapV (true) nuclear@0: , mMirrorU () nuclear@0: , mMirrorV () nuclear@0: , mOp (aiTextureOp_Multiply) nuclear@0: , mUVId (UINT_MAX) nuclear@0: , mWeighting (1.f) nuclear@0: , mMixWithPrevious (1.f) nuclear@0: {} nuclear@0: nuclear@0: /** Name of image reference nuclear@0: */ nuclear@0: std::string mName; nuclear@0: nuclear@0: /** Wrap U? nuclear@0: */ nuclear@0: bool mWrapU; nuclear@0: nuclear@0: /** Wrap V? nuclear@0: */ nuclear@0: bool mWrapV; nuclear@0: nuclear@0: /** Mirror U? nuclear@0: */ nuclear@0: bool mMirrorU; nuclear@0: nuclear@0: /** Mirror V? nuclear@0: */ nuclear@0: bool mMirrorV; nuclear@0: nuclear@0: /** Blend mode nuclear@0: */ nuclear@0: aiTextureOp mOp; nuclear@0: nuclear@0: /** UV transformation nuclear@0: */ nuclear@0: aiUVTransform mTransform; nuclear@0: nuclear@0: /** Name of source UV channel nuclear@0: */ nuclear@0: std::string mUVChannel; nuclear@0: nuclear@0: /** Resolved UV channel index or UINT_MAX if not known nuclear@0: */ nuclear@0: unsigned int mUVId; nuclear@0: nuclear@0: // OKINO/MAX3D extensions from here nuclear@0: // ------------------------------------------------------- nuclear@0: nuclear@0: /** Weighting factor nuclear@0: */ nuclear@0: float mWeighting; nuclear@0: nuclear@0: /** Mixing factor from OKINO nuclear@0: */ nuclear@0: float mMixWithPrevious; nuclear@0: }; nuclear@0: nuclear@0: /** A collada effect. Can contain about anything according to the Collada spec, nuclear@0: but we limit our version to a reasonable subset. */ nuclear@0: struct Effect nuclear@0: { nuclear@0: // Shading mode nuclear@0: ShadeType mShadeType; nuclear@0: nuclear@0: // Colors nuclear@0: aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular, nuclear@0: mTransparent, mReflective; nuclear@0: nuclear@0: // Textures nuclear@0: Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular, nuclear@0: mTexTransparent, mTexBump, mTexReflective; nuclear@0: nuclear@0: // Scalar factory nuclear@0: float mShininess, mRefractIndex, mReflectivity; nuclear@0: float mTransparency; nuclear@0: nuclear@0: // local params referring to each other by their SID nuclear@0: typedef std::map ParamLibrary; nuclear@0: ParamLibrary mParams; nuclear@0: nuclear@0: // MAX3D extensions nuclear@0: // --------------------------------------------------------- nuclear@0: // Double-sided? nuclear@0: bool mDoubleSided, mWireframe, mFaceted; nuclear@0: nuclear@0: Effect() nuclear@0: : mShadeType (Shade_Phong) nuclear@0: , mEmissive ( 0, 0, 0, 1) nuclear@0: , mAmbient ( 0.1f, 0.1f, 0.1f, 1) nuclear@0: , mDiffuse ( 0.6f, 0.6f, 0.6f, 1) nuclear@0: , mSpecular ( 0.4f, 0.4f, 0.4f, 1) nuclear@0: , mTransparent ( 0, 0, 0, 1) nuclear@0: , mShininess (10.0f) nuclear@0: , mRefractIndex (1.f) nuclear@0: , mReflectivity (1.f) nuclear@0: , mTransparency (0.f) nuclear@0: , mDoubleSided (false) nuclear@0: , mWireframe (false) nuclear@0: , mFaceted (false) nuclear@0: { nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: /** An image, meaning texture */ nuclear@0: struct Image nuclear@0: { nuclear@0: std::string mFileName; nuclear@0: nuclear@0: /** If image file name is zero, embedded image data nuclear@0: */ nuclear@0: std::vector mImageData; nuclear@0: nuclear@0: /** If image file name is zero, file format of nuclear@0: * embedded image data. nuclear@0: */ nuclear@0: std::string mEmbeddedFormat; nuclear@0: nuclear@0: }; nuclear@0: nuclear@0: /** An animation channel. */ nuclear@0: struct AnimationChannel nuclear@0: { nuclear@0: /** URL of the data to animate. Could be about anything, but we support only the nuclear@0: * "NodeID/TransformID.SubElement" notation nuclear@0: */ nuclear@0: std::string mTarget; nuclear@0: nuclear@0: /** Source URL of the time values. Collada calls them "input". Meh. */ nuclear@0: std::string mSourceTimes; nuclear@0: /** Source URL of the value values. Collada calls them "output". */ nuclear@0: std::string mSourceValues; nuclear@0: }; nuclear@0: nuclear@0: /** An animation. Container for 0-x animation channels or 0-x animations */ nuclear@0: struct Animation nuclear@0: { nuclear@0: /** Anim name */ nuclear@0: std::string mName; nuclear@0: nuclear@0: /** the animation channels, if any */ nuclear@0: std::vector mChannels; nuclear@0: nuclear@0: /** the sub-animations, if any */ nuclear@0: std::vector mSubAnims; nuclear@0: nuclear@0: /** Destructor */ nuclear@0: ~Animation() nuclear@0: { nuclear@0: for( std::vector::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) nuclear@0: delete *it; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: /** Description of a collada animation channel which has been determined to affect the current node */ nuclear@0: struct ChannelEntry nuclear@0: { nuclear@0: const Collada::AnimationChannel* mChannel; ///> the source channel nuclear@0: std::string mTransformId; // the ID of the transformation step of the node which is influenced nuclear@0: size_t mTransformIndex; // Index into the node's transform chain to apply the channel to nuclear@0: size_t mSubElement; // starting index inside the transform data nuclear@0: nuclear@0: // resolved data references nuclear@0: const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values nuclear@0: const Collada::Data* mTimeData; ///> Source data array for the time values nuclear@0: const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values nuclear@0: const Collada::Data* mValueData; ///> Source datat array for the key value values nuclear@0: nuclear@0: ChannelEntry() { mChannel = NULL; mSubElement = 0; } nuclear@0: }; nuclear@0: nuclear@0: } // end of namespace Collada nuclear@0: } // end of namespace Assimp nuclear@0: nuclear@0: #endif // AI_COLLADAHELPER_H_INC