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. */
struct aiVectorKey
{
//! The time of this key
/** The time of this key */
double mTime;
//! The value of this key
/** The value of this key */
C_STRUCT aiVector3D mValue;
#ifdef __cplusplus
@ -76,8 +77,7 @@ struct aiVectorKey
typedef aiVector3D elem_type;
//! Comparison operators. Just the key value is compared
//! For use with std::find();
// Comparison operators. For use with std::find();
bool operator == (const aiVectorKey& o) const {
return o.mValue == this->mValue;
}
@ -85,8 +85,7 @@ struct aiVectorKey
return o.mValue != this->mValue;
}
//! Relational operators. Just the key time is compared
//! For use with std::sort();
// Relational operators. For use with std::sort();
bool operator < (const aiVectorKey& o) const {
return mTime < o.mTime;
}
@ -97,22 +96,21 @@ struct aiVectorKey
};
// ---------------------------------------------------------------------------
/** A time-value pair specifying a rotation for the given time. For joint
* animations the rotation is usually expressed using a quaternion.
*/
/** A time-value pair specifying a rotation for the given time.
* Rotations are expressed with quaternions. */
struct aiQuatKey
{
//! The time of this key
/** The time of this key */
double mTime;
//! The value of this key
/** The value of this key */
C_STRUCT aiQuaternion mValue;
#ifdef __cplusplus
aiQuatKey(){
}
//! Default constructor
aiQuatKey(){}
//! Construction from a given time and key value
/** Construction from a given time and key value */
aiQuatKey(double time, const aiQuaternion& value)
: mTime (time)
, mValue (value)
@ -120,8 +118,7 @@ struct aiQuatKey
typedef aiQuaternion elem_type;
//! Comparison operators. Just the key value is compared
//! For use with std::find();
// Comparison operators. For use with std::find();
bool operator == (const aiQuatKey& o) const {
return o.mValue == this->mValue;
}
@ -129,8 +126,7 @@ struct aiQuatKey
return o.mValue != this->mValue;
}
//! Relational operators. Just the key time is compared
//! For use with std::sort();
// Relational operators. For use with std::sort();
bool operator < (const aiQuatKey& o) const {
return mTime < o.mTime;
}
@ -140,6 +136,51 @@ struct aiQuatKey
#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
* range. This corresponds to aiNodeAnim::mPreState and
@ -184,8 +225,8 @@ enum aiAnimBehaviour
*
* @note All keys are returned in their correct, chronological order.
* 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
* be able to handle them ) */
* will be no negative time values, but they are not forbidden also ( so
* implementations need to cope with them! ) */
struct aiNodeAnim
{
/** The name of the node affected by this animation. The node
@ -258,6 +299,41 @@ struct aiNodeAnim
#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
* 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. */
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
aiAnimation()
: mDuration(-1.)
, mTicksPerSecond()
, mNumChannels()
, mChannels()
, mNumMeshChannels()
, mMeshChannels()
{
mDuration = -1.;
mTicksPerSecond = 0;
mNumChannels = 0; mChannels = NULL;
}
~aiAnimation()
{
// DO NOT REMOVE THIS ADDITIONAL CHECK
if (mNumChannels && mChannels)
{
for( unsigned int a = 0; a < mNumChannels; a++)
if (mNumChannels && mChannels) {
for( unsigned int a = 0; a < mNumChannels; a++) {
delete mChannels[a];
}
delete [] mChannels;
}
if (mNumMeshChannels && mMeshChannels) {
for( unsigned int a = 0; a < mNumMeshChannels; a++) {
delete mMeshChannels[a];
}
delete [] mMeshChannels;
}
}
#endif // __cplusplus
};
@ -341,6 +436,15 @@ struct 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 <>
struct Interpolator <aiVectorKey> {
void operator () (aiVector3D& out,const aiVectorKey& a,
@ -361,6 +465,16 @@ struct 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
} // ! end namespace Assimp

View File

@ -302,6 +302,110 @@ enum aiPrimitiveType
#define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
((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.
*
@ -453,6 +557,14 @@ struct aiMesh
**/
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
//! Default constructor. Initializes all members to 0
@ -460,10 +572,12 @@ struct aiMesh
{
mNumVertices = 0;
mNumFaces = 0;
mNumAnimMeshes = 0;
mPrimitiveTypes = 0;
mVertices = NULL; mFaces = NULL;
mNormals = NULL; mTangents = NULL;
mBitangents = NULL;
mAnimMeshes = NULL;
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{
mNumUVComponents[a] = 0;
@ -482,24 +596,33 @@ struct aiMesh
delete [] mNormals;
delete [] mTangents;
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];
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];
}
// DO NOT REMOVE THIS ADDITIONAL CHECK
if (mNumBones && mBones)
{
for( unsigned int a = 0; a < mNumBones; a++)
if (mNumBones && mBones) {
for( unsigned int a = 0; a < mNumBones; a++) {
delete mBones[a];
}
delete [] mBones;
}
if (mNumAnimMeshes && mAnimMeshes) {
for( unsigned int a = 0; a < mNumAnimMeshes; a++) {
delete mAnimMeshes[a];
}
delete [] mBones;
}
delete [] mFaces;
}
//! Check whether the mesh contains positions. If no special scene flags
//! (such as AI_SCENE_FLAGS_ANIM_SKELETON_ONLY) are set this will
//! always return true
//! Check whether the mesh contains positions. Provided no special
//! scene flags are set (such as AI_SCENE_FLAGS_ANIM_SKELETON_ONLY),
//! this will always be true
bool HasPositions() const
{ return mVertices != NULL && mNumVertices > 0; }
@ -562,6 +685,7 @@ struct aiMesh
#endif // __cplusplus
};
#ifdef __cplusplus
}
#endif //! extern "C"