Add data structures for vertex animation. Basing on recent ML discussion.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@720 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2010-05-10 18:05:52 +00:00
parent 261f49c468
commit 255082c39b
2 changed files with 273 additions and 35 deletions

View File

@ -57,9 +57,10 @@ extern "C" {
/** A time-value pair specifying a certain 3D vector for the given time. */ /** A time-value pair specifying a certain 3D vector for the given time. */
struct aiVectorKey struct aiVectorKey
{ {
//! The time of this key /** The time of this key */
double mTime; double mTime;
//! The value of this key
/** The value of this key */
C_STRUCT aiVector3D mValue; C_STRUCT aiVector3D mValue;
#ifdef __cplusplus #ifdef __cplusplus
@ -76,8 +77,7 @@ struct aiVectorKey
typedef aiVector3D elem_type; typedef aiVector3D elem_type;
//! Comparison operators. Just the key value is compared // Comparison operators. For use with std::find();
//! For use with std::find();
bool operator == (const aiVectorKey& o) const { bool operator == (const aiVectorKey& o) const {
return o.mValue == this->mValue; return o.mValue == this->mValue;
} }
@ -85,8 +85,7 @@ struct aiVectorKey
return o.mValue != this->mValue; return o.mValue != this->mValue;
} }
//! Relational operators. Just the key time is compared // Relational operators. For use with std::sort();
//! For use with std::sort();
bool operator < (const aiVectorKey& o) const { bool operator < (const aiVectorKey& o) const {
return mTime < o.mTime; return mTime < o.mTime;
} }
@ -97,22 +96,21 @@ struct aiVectorKey
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** A time-value pair specifying a rotation for the given time. For joint /** A time-value pair specifying a rotation for the given time.
* animations the rotation is usually expressed using a quaternion. * Rotations are expressed with quaternions. */
*/
struct aiQuatKey struct aiQuatKey
{ {
//! The time of this key /** The time of this key */
double mTime; double mTime;
//! The value of this key
/** The value of this key */
C_STRUCT aiQuaternion mValue; C_STRUCT aiQuaternion mValue;
#ifdef __cplusplus #ifdef __cplusplus
aiQuatKey(){
}
//! Default constructor /** Construction from a given time and key value */
aiQuatKey(){}
//! Construction from a given time and key value
aiQuatKey(double time, const aiQuaternion& value) aiQuatKey(double time, const aiQuaternion& value)
: mTime (time) : mTime (time)
, mValue (value) , mValue (value)
@ -120,8 +118,7 @@ struct aiQuatKey
typedef aiQuaternion elem_type; typedef aiQuaternion elem_type;
//! Comparison operators. Just the key value is compared // Comparison operators. For use with std::find();
//! For use with std::find();
bool operator == (const aiQuatKey& o) const { bool operator == (const aiQuatKey& o) const {
return o.mValue == this->mValue; return o.mValue == this->mValue;
} }
@ -129,8 +126,7 @@ struct aiQuatKey
return o.mValue != this->mValue; return o.mValue != this->mValue;
} }
//! Relational operators. Just the key time is compared // Relational operators. For use with std::sort();
//! For use with std::sort();
bool operator < (const aiQuatKey& o) const { bool operator < (const aiQuatKey& o) const {
return mTime < o.mTime; return mTime < o.mTime;
} }
@ -140,6 +136,51 @@ struct aiQuatKey
#endif #endif
}; };
// ---------------------------------------------------------------------------
/** Binds a anim mesh to a specific point in time. */
struct aiMeshKey
{
/** The time of this key */
double mTime;
/** Index into the aiMesh::mAnimMeshes array of the
* mesh coresponding to the #aiMeshAnim hosting this
* key frame. The referenced anim mesh is evaluated
* according to the rules defined in the docs for #aiAnimMesh.*/
unsigned int mValue;
#ifdef __cplusplus
aiMeshKey() {
}
/** Construction from a given time and key value */
aiMeshKey(double time, const unsigned int value)
: mTime (time)
, mValue (value)
{}
typedef unsigned int elem_type;
// Comparison operators. For use with std::find();
bool operator == (const aiMeshKey& o) const {
return o.mValue == this->mValue;
}
bool operator != (const aiMeshKey& o) const {
return o.mValue != this->mValue;
}
// Relational operators. For use with std::sort();
bool operator < (const aiMeshKey& o) const {
return mTime < o.mTime;
}
bool operator > (const aiMeshKey& o) const {
return mTime > o.mTime;
}
#endif
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Defines how an animation channel behaves outside the defined time /** Defines how an animation channel behaves outside the defined time
* range. This corresponds to aiNodeAnim::mPreState and * range. This corresponds to aiNodeAnim::mPreState and
@ -184,8 +225,8 @@ enum aiAnimBehaviour
* *
* @note All keys are returned in their correct, chronological order. * @note All keys are returned in their correct, chronological order.
* Duplicate keys don't pass the validation step. Most likely there * Duplicate keys don't pass the validation step. Most likely there
* will be no negative time values, but they are not forbidden ( so you should * will be no negative time values, but they are not forbidden also ( so
* be able to handle them ) */ * implementations need to cope with them! ) */
struct aiNodeAnim struct aiNodeAnim
{ {
/** The name of the node affected by this animation. The node /** The name of the node affected by this animation. The node
@ -258,6 +299,41 @@ struct aiNodeAnim
#endif // __cplusplus #endif // __cplusplus
}; };
// ---------------------------------------------------------------------------
/** Describes vertex-based animations for a single mesh or a group of
* meshes. Meshes carry the animation data for each frame in their
* aiMesh::mAnimMeshes array. The purpose of aiMeshAnim is to
* define keyframes linking each mesh attachment to a particular
* point in time. */
struct aiMeshAnim
{
/** Name of the mesh to be animated. An empty string is not allowed,
* animated meshes need to be named (not necessarily uniquely,
* the name can basically serve as wildcard to select a group
* of meshes with similar animation setup)*/
C_STRUCT aiString mName;
/** Size of the #mKeys array. Must be 1, at least. */
unsigned int mNumKeys;
/** Key frames of the animation. May not be NULL. */
C_STRUCT aiMeshKey* mKeys;
#ifdef __cplusplus
aiMeshAnim()
: mNumKeys()
, mKeys()
{}
~aiMeshAnim()
{
delete[] mKeys;
}
#endif
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** An animation consists of keyframe data for a number of nodes. For /** An animation consists of keyframe data for a number of nodes. For
* each node affected by the animation a separate series of data is given.*/ * each node affected by the animation a separate series of data is given.*/
@ -282,24 +358,43 @@ struct aiAnimation
* The array is mNumChannels in size. */ * The array is mNumChannels in size. */
C_STRUCT aiNodeAnim** mChannels; C_STRUCT aiNodeAnim** mChannels;
/** The number of mesh animation channels. Each channel affects
* a single mesh and defines vertex-based animation. */
unsigned int mNumMeshChannels;
/** The mesh animation channels. Each channel affects a single mesh.
* The array is mNumMeshChannels in size. */
C_STRUCT aiMeshAnim** mMeshChannels;
#ifdef __cplusplus #ifdef __cplusplus
aiAnimation() aiAnimation()
: mDuration(-1.)
, mTicksPerSecond()
, mNumChannels()
, mChannels()
, mNumMeshChannels()
, mMeshChannels()
{ {
mDuration = -1.;
mTicksPerSecond = 0;
mNumChannels = 0; mChannels = NULL;
} }
~aiAnimation() ~aiAnimation()
{ {
// DO NOT REMOVE THIS ADDITIONAL CHECK // DO NOT REMOVE THIS ADDITIONAL CHECK
if (mNumChannels && mChannels) if (mNumChannels && mChannels) {
{ for( unsigned int a = 0; a < mNumChannels; a++) {
for( unsigned int a = 0; a < mNumChannels; a++)
delete mChannels[a]; delete mChannels[a];
}
delete [] mChannels; delete [] mChannels;
} }
if (mNumMeshChannels && mMeshChannels) {
for( unsigned int a = 0; a < mNumMeshChannels; a++) {
delete mMeshChannels[a];
}
delete [] mMeshChannels;
}
} }
#endif // __cplusplus #endif // __cplusplus
}; };
@ -341,6 +436,15 @@ struct Interpolator <aiQuaternion> {
} }
}; // ! Interpolator <aiQuaternion> }; // ! Interpolator <aiQuaternion>
template <>
struct Interpolator <unsigned int> {
void operator () (unsigned int& out,unsigned int a,
unsigned int b, float d) const
{
out = d>0.5f ? b : a;
}
}; // ! Interpolator <aiQuaternion>
template <> template <>
struct Interpolator <aiVectorKey> { struct Interpolator <aiVectorKey> {
void operator () (aiVector3D& out,const aiVectorKey& a, void operator () (aiVector3D& out,const aiVectorKey& a,
@ -361,6 +465,16 @@ struct Interpolator <aiQuatKey> {
} }
}; // ! Interpolator <aiQuatKey> }; // ! Interpolator <aiQuatKey>
template <>
struct Interpolator <aiMeshKey> {
void operator () (unsigned int& out, const aiMeshKey a,
const aiMeshKey& b, float d) const
{
Interpolator<unsigned int> ipl;
ipl(out,a.mValue,b.mValue,d);
}
}; // ! Interpolator <aiQuatKey>
//! @endcond //! @endcond
} // ! end namespace Assimp } // ! end namespace Assimp

View File

@ -302,6 +302,110 @@ enum aiPrimitiveType
#define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \ #define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1))) ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
// ---------------------------------------------------------------------------
/** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex
* animations for a particular frame.
*
* You may think of an #aiAnimMesh as a `patch` for the host mesh, which
* replaces only certain vertex data streams at a particular time.
* Each mesh stores n attached attached meshes (#aiMesh::mAnimMeshes).
* The actual relationship between the time line and anim meshes is
* established by #aiMeshAnim, which references singular mesh attachments
* by their ID and binds them to a time offset.
*/
struct aiAnimMesh
{
/** Replacement for aiMesh::mVertices. If this array is non-NULL,
* it *must* contain aiMesh::mNumVertices entries. The corresponding
* array in the host mesh must be non-NULL as well - animation
* meshes may neither add or nor remove vertex components (if
* a replacement array is NULL and the corresponding source
* array is not, the source data is taken instead)*/
C_STRUCT aiVector3D* mVertices;
/** Replacement for aiMesh::mNormals. */
C_STRUCT aiVector3D* mNormals;
/** Replacement for aiMesh::mTangents. */
C_STRUCT aiVector3D* mTangents;
/** Replacement for aiMesh::mBitangents. */
C_STRUCT aiVector3D* mBitangents;
/** Replacement for aiMesh::mColors */
C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
/** Replacement for aiMesh::mTextureCoords */
C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
#ifdef __cplusplus
aiAnimMesh()
: mVertices()
, mNormals()
, mTangents()
, mBitangents()
{
// fixme consider moving this to the ctor initializer list as well
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
mTextureCoords[a] = NULL;
}
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
mColors[a] = NULL;
}
}
~aiAnimMesh()
{
delete [] mVertices;
delete [] mNormals;
delete [] mTangents;
delete [] mBitangents;
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
delete [] mTextureCoords[a];
}
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
delete [] mColors[a];
}
}
/** Check whether the anim mesh overrides the vertex positions
* of its host mesh*/
bool HasPositions() const {
return mVertices != NULL;
}
/** Check whether the anim mesh overrides the vertex normals
* of its host mesh*/
bool HasNormals() const {
return mNormals != NULL;
}
/** Check whether the anim mesh overrides the vertex tangents
* and bitangents of its host mesh. As for aiMesh,
* tangents and bitangents always go together. */
bool HasTangentsAndBitangents() const {
return mTangents != NULL;
}
/** Check whether the anim mesh overrides a particular
* set of vertex colors on his host mesh.
* @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS */
bool HasVertexColors( unsigned int pIndex) const {
return pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != NULL;
}
/** Check whether the anim mesh overrides a particular
* set of texture coordinates on his host mesh.
* @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS */
bool HasTextureCoords( unsigned int pIndex) const {
return pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != NULL;
}
#endif
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief A mesh represents a geometry or model with a single material. /** @brief A mesh represents a geometry or model with a single material.
* *
@ -453,6 +557,14 @@ struct aiMesh
**/ **/
aiString mName; aiString mName;
/** The number of attachment meshes */
unsigned int mNumAnimMeshes;
/** Attachment meshes for this mesh, for vertex-based animation.
* Attachment meshes carry replacement data for some of the
* mesh'es vertex components (usually positions, normals). */
C_STRUCT aiAnimMesh** mAnimMeshes;
#ifdef __cplusplus #ifdef __cplusplus
//! Default constructor. Initializes all members to 0 //! Default constructor. Initializes all members to 0
@ -460,10 +572,12 @@ struct aiMesh
{ {
mNumVertices = 0; mNumVertices = 0;
mNumFaces = 0; mNumFaces = 0;
mNumAnimMeshes = 0;
mPrimitiveTypes = 0; mPrimitiveTypes = 0;
mVertices = NULL; mFaces = NULL; mVertices = NULL; mFaces = NULL;
mNormals = NULL; mTangents = NULL; mNormals = NULL; mTangents = NULL;
mBitangents = NULL; mBitangents = NULL;
mAnimMeshes = NULL;
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{ {
mNumUVComponents[a] = 0; mNumUVComponents[a] = 0;
@ -482,24 +596,33 @@ struct aiMesh
delete [] mNormals; delete [] mNormals;
delete [] mTangents; delete [] mTangents;
delete [] mBitangents; delete [] mBitangents;
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
delete [] mTextureCoords[a]; delete [] mTextureCoords[a];
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) }
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
delete [] mColors[a]; delete [] mColors[a];
}
// DO NOT REMOVE THIS ADDITIONAL CHECK // DO NOT REMOVE THIS ADDITIONAL CHECK
if (mNumBones && mBones) if (mNumBones && mBones) {
{ for( unsigned int a = 0; a < mNumBones; a++) {
for( unsigned int a = 0; a < mNumBones; a++)
delete mBones[a]; delete mBones[a];
}
delete [] mBones; delete [] mBones;
} }
if (mNumAnimMeshes && mAnimMeshes) {
for( unsigned int a = 0; a < mNumAnimMeshes; a++) {
delete mAnimMeshes[a];
}
delete [] mBones;
}
delete [] mFaces; delete [] mFaces;
} }
//! Check whether the mesh contains positions. If no special scene flags //! Check whether the mesh contains positions. Provided no special
//! (such as AI_SCENE_FLAGS_ANIM_SKELETON_ONLY) are set this will //! scene flags are set (such as AI_SCENE_FLAGS_ANIM_SKELETON_ONLY),
//! always return true //! this will always be true
bool HasPositions() const bool HasPositions() const
{ return mVertices != NULL && mNumVertices > 0; } { return mVertices != NULL && mNumVertices > 0; }
@ -562,6 +685,7 @@ struct aiMesh
#endif // __cplusplus #endif // __cplusplus
}; };
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif //! extern "C" #endif //! extern "C"