Просмотр исходного кода

Dummy animation support for AssimpView - work in progress. Uses boost in a new way, just because I can.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@191 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
ulfjorensen 17 лет назад
Родитель
Сommit
013ff599a5

+ 138 - 0
tools/assimp_view/AnimEvaluator.cpp

@@ -0,0 +1,138 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+#include "stdafx.h"
+#include "assimp_view.h"
+
+using namespace AssimpView;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor on a given animation. 
+AnimEvaluator::AnimEvaluator( const aiAnimation* pAnim)
+{
+	mAnim = pAnim;
+	mLastTime = 0.0;
+	mLastPositions.resize( pAnim->mNumChannels, boost::make_tuple( 0, 0, 0));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Evaluates the animation tracks for a given time stamp. 
+void AnimEvaluator::Evaluate( double pTime)
+{
+	// extract ticks per second. Assume default value if not given
+	double ticksPerSecond = mAnim->mTicksPerSecond != 0.0 ? mAnim->mTicksPerSecond : 25.0;
+	// every following time calculation happens in ticks
+	pTime *= ticksPerSecond;
+
+	// map into anim's duration
+	double time = 0.0f;
+	if( mAnim->mDuration > 0.0)
+		time = fmod( pTime, mAnim->mDuration);
+
+	// calculate the transformations for each animation channel
+	for( unsigned int a = 0; a < mAnim->mNumChannels; a++)
+	{
+		const aiNodeAnim* channel = mAnim->mChannels[a];
+
+		// ******** Position *****
+		aiVector3D presentPosition( 0, 0, 0);
+		if( channel->mPositionKeys > 0)
+		{
+			// Look for present frame number. Search from last position if time is after the last time, else from beginning
+			// Should be much quicker than always looking from start for the average use case.
+			unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<0>() : 0;
+			while( frame < channel->mNumPositionKeys - 1)
+			{
+				if( time < channel->mPositionKeys[frame+1].mTime)
+					break;
+				frame++;
+			}
+
+			// TODO: (thom) interpolation maybe?
+			presentPosition = channel->mPositionKeys[frame].mValue;
+			mLastPositions[a].get<0>() = frame;
+		}
+
+		// ******** Rotation *********
+		aiQuaternion presentRotation( 1, 0, 0, 0);
+		if( channel->mRotationKeys > 0)
+		{
+			unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<1>() : 0;
+			while( frame < channel->mNumRotationKeys - 1)
+			{
+				if( time < channel->mRotationKeys[frame+1].mTime)
+					break;
+				frame++;
+			}
+
+			// TODO: (thom) quaternions are a prime target for interpolation
+			presentRotation = channel->mRotationKeys[frame].mValue;
+			mLastPositions[a].get<1>() = frame;
+		}
+
+		// ******** Scaling **********
+		aiVector3D presentScaling( 0, 0, 0);
+		if( channel->mScalingKeys > 0)
+		{
+			unsigned int frame = (time >= mLastTime) ? mLastPositions[a].get<2>() : 0;
+			while( frame < channel->mNumScalingKeys - 1)
+			{
+				if( time < channel->mScalingKeys[frame+1].mTime)
+					break;
+				frame++;
+			}
+
+			// TODO: (thom) interpolation maybe? This time maybe even logarithmic, not linear
+			presentScaling = channel->mScalingKeys[frame].mValue;
+			mLastPositions[a].get<2>() = frame;
+		}
+
+		// build a transformation matrix from it
+		aiMatrix4x4& mat = mTransforms[a];
+		mat = aiMatrix4x4( presentRotation.GetMatrix());
+		mat.a1 *= presentScaling.x; mat.b1 *= presentScaling.x; mat.c1 *= presentScaling.x;
+		mat.a2 *= presentScaling.y; mat.b2 *= presentScaling.y; mat.c2 *= presentScaling.y;
+		mat.a3 *= presentScaling.z; mat.b3 *= presentScaling.z; mat.c3 *= presentScaling.z;
+		mat.a4 = presentPosition.x; mat.b4 = presentPosition.y; mat.c4 = presentPosition.z;
+	}
+
+	mLastTime = time;
+}

+ 88 - 0
tools/assimp_view/AnimEvaluator.h

@@ -0,0 +1,88 @@
+/** Calculates a pose for a given time of an animation */
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+#ifndef AV_ANIMEVALUATOR_H_INCLUDED
+#define AV_ANIMEVALUATOR_H_INCLUDED
+
+#include <boost/tuple/tuple.hpp>
+
+namespace AssimpView
+{
+
+class AnimEvaluator
+{
+public:
+	/** Constructor on a given animation. The animation is fixed throughout the lifetime of
+	 * the object.
+	 * @param pAnim The animation to calculate poses for. Ownership of the animation object stays
+	 *   at the caller, the evaluator just keeps a reference to it as long as it persists.
+	 */
+	AnimEvaluator( const aiAnimation* pAnim);
+
+	/** Evaluates the animation tracks for a given time stamp. The calculated pose can be retrieved as a
+	 * array of transformation matrices afterwards by calling GetTransformations().
+	 * @param pTime The time for which you want to evaluate the animation, in seconds. Will be mapped into the animation cycle, so
+	 *   it can be an arbitrary value. Best use with ever-increasing time stamps.
+	 */
+	void Evaluate( double pTime);
+
+	/** Returns the transform matrices calculated at the last Evaluate() call. The array matches the mChannels array of
+	 * the aiAnimation. */
+	const std::vector<aiMatrix4x4>& GetTransformations() const { return mTransforms; }
+
+protected:
+	/** The animation we're working on */
+	const aiAnimation* mAnim;
+
+	/** At which frame the last evaluation happened for each channel. 
+	 * Useful to quickly find the corresponding frame for slightly increased time stamps
+	 */
+	double mLastTime;
+	std::vector<boost::tuple<unsigned int, unsigned int, unsigned int> > mLastPositions;
+
+	/** The array to store the transformations results of the evaluation */
+	std::vector<aiMatrix4x4> mTransforms;
+};
+
+} // end of namespace AssimpView
+
+#endif // AV_ANIMEVALUATOR_H_INCLUDED

+ 4 - 1
tools/assimp_view/assimp_view.h

@@ -255,6 +255,9 @@ enum EClickPos
 
 	extern float g_fACMR /*= 3.0f*/;
 	extern IDirect3DQuery9* g_piQuery;
-	};
+	}
+
+// outside of namespace, to help Intellisense and solve boost::metatype_stuff_miracle
+#include "AnimEvaluator.h"
 
 #endif // !! AV_MAIN_H_INCLUDED

+ 8 - 0
workspaces/vc8/assimp_view.vcproj

@@ -679,6 +679,14 @@
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
+			<File
+				RelativePath="..\..\tools\assimp_view\AnimEvaluator.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\tools\assimp_view\AnimEvaluator.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\tools\assimp_view\AssetHelper.h"
 				>