summaryrefslogtreecommitdiff
path: root/libs/assimp/code/AssetLib/Collada/ColladaHelper.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/code/AssetLib/Collada/ColladaHelper.h')
-rw-r--r--libs/assimp/code/AssetLib/Collada/ColladaHelper.h679
1 files changed, 679 insertions, 0 deletions
diff --git a/libs/assimp/code/AssetLib/Collada/ColladaHelper.h b/libs/assimp/code/AssetLib/Collada/ColladaHelper.h
new file mode 100644
index 0000000..31d7b5a
--- /dev/null
+++ b/libs/assimp/code/AssetLib/Collada/ColladaHelper.h
@@ -0,0 +1,679 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** Helper structures for the Collada loader */
+
+#ifndef AI_COLLADAHELPER_H_INC
+#define AI_COLLADAHELPER_H_INC
+
+#include <assimp/light.h>
+#include <assimp/material.h>
+#include <assimp/mesh.h>
+
+#include <cstdint>
+#include <map>
+#include <set>
+#include <vector>
+
+struct aiMaterial;
+
+namespace Assimp {
+namespace Collada {
+
+/// Collada file versions which evolved during the years ...
+enum FormatVersion {
+ FV_1_5_n,
+ FV_1_4_n,
+ FV_1_3_n
+};
+
+/// Transformation types that can be applied to a node
+enum TransformType {
+ TF_LOOKAT,
+ TF_ROTATE,
+ TF_TRANSLATE,
+ TF_SCALE,
+ TF_SKEW,
+ TF_MATRIX
+};
+
+/// Different types of input data to a vertex or face
+enum InputType {
+ IT_Invalid,
+ IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
+ IT_Position,
+ IT_Normal,
+ IT_Texcoord,
+ IT_Color,
+ IT_Tangent,
+ IT_Bitangent
+};
+
+/// Supported controller types
+enum ControllerType {
+ Skin,
+ Morph
+};
+
+/// Supported morph methods
+enum MorphMethod {
+ Normalized,
+ Relative
+};
+
+/// Common metadata keys as <Collada, Assimp>
+using MetaKeyPair = std::pair<std::string, std::string>;
+using MetaKeyPairVector = std::vector<MetaKeyPair>;
+
+/// Collada as lower_case (native)
+const MetaKeyPairVector &GetColladaAssimpMetaKeys();
+
+// Collada as CamelCase (used by Assimp for consistency)
+const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase();
+
+/// Convert underscore_separated to CamelCase "authoring_tool" becomes "AuthoringTool"
+void ToCamelCase(std::string &text);
+
+/// Contains all data for one of the different transformation types
+struct Transform {
+ std::string mID; ///< SID of the transform step, by which anim channels address their target node
+ TransformType mType;
+ ai_real f[16]; ///< Interpretation of data depends on the type of the transformation
+};
+
+/// A collada camera.
+struct Camera {
+ Camera() :
+ mOrtho(false),
+ mHorFov(10e10f),
+ mVerFov(10e10f),
+ mAspect(10e10f),
+ mZNear(0.1f),
+ mZFar(1000.f) {}
+
+ /// Name of camera
+ std::string mName;
+
+ /// True if it is an orthographic camera
+ bool mOrtho;
+
+ /// Horizontal field of view in degrees
+ ai_real mHorFov;
+
+ /// Vertical field of view in degrees
+ ai_real mVerFov;
+
+ /// Screen aspect
+ ai_real mAspect;
+
+ /// Near& far z
+ ai_real mZNear, mZFar;
+};
+
+#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
+
+/** A collada light source. */
+struct Light {
+ Light() :
+ mType(aiLightSource_UNDEFINED),
+ mAttConstant(1.f),
+ mAttLinear(0.f),
+ mAttQuadratic(0.f),
+ mFalloffAngle(180.f),
+ mFalloffExponent(0.f),
+ mPenumbraAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
+ mOuterAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
+ mIntensity(1.f) {}
+
+ /// Type of the light source aiLightSourceType + ambient
+ unsigned int mType;
+
+ /// Color of the light
+ aiColor3D mColor;
+
+ /// Light attenuation
+ ai_real mAttConstant, mAttLinear, mAttQuadratic;
+
+ /// Spot light falloff
+ ai_real mFalloffAngle;
+ ai_real mFalloffExponent;
+
+ // -----------------------------------------------------
+ // FCOLLADA extension from here
+
+ /// ... related stuff from maja and max extensions
+ ai_real mPenumbraAngle;
+ ai_real mOuterAngle;
+
+ /// Common light intensity
+ ai_real mIntensity;
+};
+
+/** Short vertex index description */
+struct InputSemanticMapEntry {
+ InputSemanticMapEntry() :
+ mSet(0),
+ mType(IT_Invalid) {}
+
+ /// Index of set, optional
+ unsigned int mSet;
+
+ /// Type of referenced vertex input
+ InputType mType;
+};
+
+/// Table to map from effect to vertex input semantics
+struct SemanticMappingTable {
+ /// Name of material
+ std::string mMatName;
+
+ /// List of semantic map commands, grouped by effect semantic name
+ using InputSemanticMap = std::map<std::string, InputSemanticMapEntry>;
+ InputSemanticMap mMap;
+
+ /// For std::find
+ bool operator==(const std::string &s) const {
+ return s == mMatName;
+ }
+};
+
+/// A reference to a mesh inside a node, including materials assigned to the various subgroups.
+/// The ID refers to either a mesh or a controller which specifies the mesh
+struct MeshInstance {
+ ///< ID of the mesh or controller to be instanced
+ std::string mMeshOrController;
+
+ ///< Map of materials by the subgroup ID they're applied to
+ std::map<std::string, SemanticMappingTable> mMaterials;
+};
+
+/// A reference to a camera inside a node
+struct CameraInstance {
+ ///< ID of the camera
+ std::string mCamera;
+};
+
+/// A reference to a light inside a node
+struct LightInstance {
+ ///< ID of the camera
+ std::string mLight;
+};
+
+/// A reference to a node inside a node
+struct NodeInstance {
+ ///< ID of the node
+ std::string mNode;
+};
+
+/// A node in a scene hierarchy
+struct Node {
+ std::string mName;
+ std::string mID;
+ std::string mSID;
+ Node *mParent;
+ std::vector<Node *> mChildren;
+
+ /// Operations in order to calculate the resulting transformation to parent.
+ std::vector<Transform> mTransforms;
+
+ /// Meshes at this node
+ std::vector<MeshInstance> mMeshes;
+
+ /// Lights at this node
+ std::vector<LightInstance> mLights;
+
+ /// Cameras at this node
+ std::vector<CameraInstance> mCameras;
+
+ /// Node instances at this node
+ std::vector<NodeInstance> mNodeInstances;
+
+ /// Root-nodes: Name of primary camera, if any
+ std::string mPrimaryCamera;
+
+ /// Constructor. Begin with a zero parent
+ Node() :
+ mParent(nullptr) {
+ // empty
+ }
+
+ /// Destructor: delete all children subsequently
+ ~Node() {
+ for (std::vector<Node *>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) {
+ delete *it;
+ }
+ }
+};
+
+/// Data source array: either floats or strings
+struct Data {
+ bool mIsStringArray;
+ std::vector<ai_real> mValues;
+ std::vector<std::string> mStrings;
+};
+
+/// Accessor to a data array
+struct Accessor {
+ size_t mCount; // in number of objects
+ size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
+ size_t mOffset; // in number of values
+ size_t mStride; // Stride in number of values
+ std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
+ size_t mSubOffset[4]; // Sub-offset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
+ // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
+ std::string mSource; // URL of the source array
+ mutable const Data *mData; // Pointer to the source array, if resolved. nullptr else
+
+ Accessor() {
+ mCount = 0;
+ mSize = 0;
+ mOffset = 0;
+ mStride = 0;
+ mData = nullptr;
+ mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
+ }
+};
+
+/// A single face in a mesh
+struct Face {
+ std::vector<size_t> mIndices;
+};
+
+/// An input channel for mesh data, referring to a single accessor
+struct InputChannel {
+ InputType mType; // Type of the data
+ size_t mIndex; // Optional index, if multiple sets of the same data type are given
+ size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
+ std::string mAccessor; // ID of the accessor where to read the actual values from.
+ mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. nullptr else
+
+ InputChannel() {
+ mType = IT_Invalid;
+ mIndex = 0;
+ mOffset = 0;
+ mResolved = nullptr;
+ }
+};
+
+/// Subset of a mesh with a certain material
+struct SubMesh {
+ std::string mMaterial; ///< subgroup identifier
+ size_t mNumFaces; ///< number of faces in this sub-mesh
+};
+
+/// Contains data for a single mesh
+struct Mesh {
+ Mesh(const std::string &id) :
+ mId(id) {
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ mNumUVComponents[i] = 2;
+ }
+ }
+
+ const std::string mId;
+ std::string mName;
+
+ // just to check if there's some sophisticated addressing involved...
+ // which we don't support, and therefore should warn about.
+ std::string mVertexID;
+
+ // Vertex data addressed by vertex indices
+ std::vector<InputChannel> mPerVertexData;
+
+ // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
+ std::vector<aiVector3D> mPositions;
+ std::vector<aiVector3D> mNormals;
+ std::vector<aiVector3D> mTangents;
+ std::vector<aiVector3D> mBitangents;
+ std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+ // Faces. Stored are only the number of vertices for each face.
+ // 1 == point, 2 == line, 3 == triangle, 4+ == poly
+ std::vector<size_t> mFaceSize;
+
+ // Position indices for all faces in the sequence given in mFaceSize -
+ // necessary for bone weight assignment
+ std::vector<size_t> mFacePosIndices;
+
+ // Sub-meshes in this mesh, each with a given material
+ std::vector<SubMesh> mSubMeshes;
+};
+
+/// Which type of primitives the ReadPrimitives() function is going to read
+enum PrimitiveType {
+ Prim_Invalid,
+ Prim_Lines,
+ Prim_LineStrip,
+ Prim_Triangles,
+ Prim_TriStrips,
+ Prim_TriFans,
+ Prim_Polylist,
+ Prim_Polygon
+};
+
+/// A skeleton controller to deform a mesh with the use of joints
+struct Controller {
+ // controller type
+ ControllerType mType;
+
+ // Morphing method if type is Morph
+ MorphMethod mMethod;
+
+ // the URL of the mesh deformed by the controller.
+ std::string mMeshId;
+
+ // accessor URL of the joint names
+ std::string mJointNameSource;
+
+ ///< 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
+ ai_real mBindShapeMatrix[16];
+
+ // accessor URL of the joint inverse bind matrices
+ std::string mJointOffsetMatrixSource;
+
+ // input channel: joint names.
+ InputChannel mWeightInputJoints;
+ // input channel: joint weights
+ InputChannel mWeightInputWeights;
+
+ // Number of weights per vertex.
+ std::vector<size_t> mWeightCounts;
+
+ // JointIndex-WeightIndex pairs for all vertices
+ std::vector<std::pair<size_t, size_t>> mWeights;
+
+ std::string mMorphTarget;
+ std::string mMorphWeight;
+};
+
+/// A collada material. Pretty much the only member is a reference to an effect.
+struct Material {
+ std::string mName;
+ std::string mEffect;
+};
+
+/// Type of the effect param
+enum ParamType {
+ Param_Sampler,
+ Param_Surface
+};
+
+/// A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them
+struct EffectParam {
+ ParamType mType;
+ std::string mReference; // to which other thing the param is referring to.
+};
+
+/// Shading type supported by the standard effect spec of Collada
+enum ShadeType {
+ Shade_Invalid,
+ Shade_Constant,
+ Shade_Lambert,
+ Shade_Phong,
+ Shade_Blinn
+};
+
+/// Represents a texture sampler in collada
+struct Sampler {
+ Sampler() :
+ mWrapU(true),
+ mWrapV(true),
+ mMirrorU(),
+ mMirrorV(),
+ mOp(aiTextureOp_Multiply),
+ mUVId(UINT_MAX),
+ mWeighting(1.f),
+ mMixWithPrevious(1.f) {}
+
+ /// Name of image reference
+ std::string mName;
+
+ /// Wrap U?
+ bool mWrapU;
+
+ /// Wrap V?
+ bool mWrapV;
+
+ /// Mirror U?
+ bool mMirrorU;
+
+ /// Mirror V?
+ bool mMirrorV;
+
+ /// Blend mode
+ aiTextureOp mOp;
+
+ /// UV transformation
+ aiUVTransform mTransform;
+
+ /// Name of source UV channel
+ std::string mUVChannel;
+
+ /// Resolved UV channel index or UINT_MAX if not known
+ unsigned int mUVId;
+
+ // OKINO/MAX3D extensions from here
+ // -------------------------------------------------------
+
+ /// Weighting factor
+ ai_real mWeighting;
+
+ /// Mixing factor from OKINO
+ ai_real mMixWithPrevious;
+};
+
+/// A collada effect. Can contain about anything according to the Collada spec,
+/// but we limit our version to a reasonable subset.
+struct Effect {
+ /// Shading mode
+ ShadeType mShadeType;
+
+ /// Colors
+ aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
+ mTransparent, mReflective;
+
+ /// Textures
+ Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
+ mTexTransparent, mTexBump, mTexReflective;
+
+ /// Scalar factory
+ ai_real mShininess, mRefractIndex, mReflectivity;
+ ai_real mTransparency;
+ bool mHasTransparency;
+ bool mRGBTransparency;
+ bool mInvertTransparency;
+
+ /// local params referring to each other by their SID
+ using ParamLibrary = std::map<std::string, Collada::EffectParam>;
+ ParamLibrary mParams;
+
+ // MAX3D extensions
+ // ---------------------------------------------------------
+ // Double-sided?
+ bool mDoubleSided, mWireframe, mFaceted;
+
+ Effect() :
+ mShadeType(Shade_Phong),
+ mEmissive(0, 0, 0, 1),
+ mAmbient(0.1f, 0.1f, 0.1f, 1),
+ mDiffuse(0.6f, 0.6f, 0.6f, 1),
+ mSpecular(0.4f, 0.4f, 0.4f, 1),
+ mTransparent(0, 0, 0, 1),
+ mShininess(10.0f),
+ mRefractIndex(1.f),
+ mReflectivity(0.f),
+ mTransparency(1.f),
+ mHasTransparency(false),
+ mRGBTransparency(false),
+ mInvertTransparency(false),
+ mDoubleSided(false),
+ mWireframe(false),
+ mFaceted(false) {
+ }
+};
+
+/// An image, meaning texture
+struct Image {
+ std::string mFileName;
+
+ /// Embedded image data
+ std::vector<uint8_t> mImageData;
+
+ /// File format hint of embedded image data
+ std::string mEmbeddedFormat;
+};
+
+/// An animation channel.
+struct AnimationChannel {
+ /// URL of the data to animate. Could be about anything, but we support only the
+ /// "NodeID/TransformID.SubElement" notation
+ std::string mTarget;
+
+ /// Source URL of the time values. Collada calls them "input". Meh.
+ std::string mSourceTimes;
+ /// Source URL of the value values. Collada calls them "output".
+ std::string mSourceValues;
+ /// Source URL of the IN_TANGENT semantic values.
+ std::string mInTanValues;
+ /// Source URL of the OUT_TANGENT semantic values.
+ std::string mOutTanValues;
+ /// Source URL of the INTERPOLATION semantic values.
+ std::string mInterpolationValues;
+};
+
+/// An animation. Container for 0-x animation channels or 0-x animations
+struct Animation {
+ /// Anim name
+ std::string mName;
+
+ /// the animation channels, if any
+ std::vector<AnimationChannel> mChannels;
+
+ /// the sub-animations, if any
+ std::vector<Animation *> mSubAnims;
+
+ /// Destructor
+ ~Animation() {
+ for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) {
+ delete *it;
+ }
+ }
+
+ /// Collect all channels in the animation hierarchy into a single channel list.
+ void CollectChannelsRecursively(std::vector<AnimationChannel> &channels) {
+ channels.insert(channels.end(), mChannels.begin(), mChannels.end());
+
+ for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) {
+ Animation *pAnim = (*it);
+ pAnim->CollectChannelsRecursively(channels);
+ }
+ }
+
+ /// Combine all single-channel animations' channel into the same (parent) animation channel list.
+ void CombineSingleChannelAnimations() {
+ CombineSingleChannelAnimationsRecursively(this);
+ }
+
+ void CombineSingleChannelAnimationsRecursively(Animation *pParent) {
+ std::set<std::string> childrenTargets;
+ bool childrenAnimationsHaveDifferentChannels = true;
+
+ for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
+ Animation *anim = *it;
+ CombineSingleChannelAnimationsRecursively(anim);
+
+ if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
+ childrenTargets.find(anim->mChannels[0].mTarget) == childrenTargets.end()) {
+ childrenTargets.insert(anim->mChannels[0].mTarget);
+ } else {
+ childrenAnimationsHaveDifferentChannels = false;
+ }
+
+ ++it;
+ }
+
+ // We only want to combine animations if they have different channels
+ if (childrenAnimationsHaveDifferentChannels) {
+ for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
+ Animation *anim = *it;
+
+ pParent->mChannels.push_back(anim->mChannels[0]);
+
+ it = pParent->mSubAnims.erase(it);
+
+ delete anim;
+ continue;
+ }
+ }
+ }
+};
+
+/// Description of a collada animation channel which has been determined to affect the current node
+struct ChannelEntry {
+ const Collada::AnimationChannel *mChannel; ///< the source channel
+ std::string mTargetId;
+ std::string mTransformId; // the ID of the transformation step of the node which is influenced
+ size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
+ size_t mSubElement; // starting index inside the transform data
+
+ // resolved data references
+ const Collada::Accessor *mTimeAccessor; ///> Collada accessor to the time values
+ const Collada::Data *mTimeData; ///> Source data array for the time values
+ const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values
+ const Collada::Data *mValueData; ///> Source datat array for the key value values
+
+ ChannelEntry() :
+ mChannel(),
+ mTransformIndex(),
+ mSubElement(),
+ mTimeAccessor(),
+ mTimeData(),
+ mValueAccessor(),
+ mValueData() {}
+};
+
+} // end of namespace Collada
+} // end of namespace Assimp
+
+#endif // AI_COLLADAHELPER_H_INC