소스 검색

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
aramis_acg 15 년 전
부모
커밋
255082c39b
2개의 변경된 파일273개의 추가작업 그리고 35개의 파일을 삭제
  1. 141 27
      include/aiAnim.h
  2. 132 8
      include/aiMesh.h

+ 141 - 27
include/aiAnim.h

@@ -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
 

+ 132 - 8
include/aiMesh.h

@@ -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"