From d965f0d06ad6d21820143e46af146f9bb495e693 Mon Sep 17 00:00:00 2001 From: ulfjorensen Date: Sun, 2 Nov 2008 17:20:29 +0000 Subject: [PATCH] - Viewer: additional bugfixes while trying to get the animations to work - added anim interpolation for anim playback - Bugfix: FindInvalidDataProcess was still mixed up a bit git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@219 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- include/aiQuaternion.h | 51 ++++++++++++++++++++- tools/assimp_view/AnimEvaluator.cpp | 23 ++++++++-- tools/assimp_view/Shaders.cpp | 27 ++++++----- workspaces/vc9_ATMNotUpToDate/assimp.sln | 2 - workspaces/vc9_ATMNotUpToDate/assimp.vcproj | 16 +++++++ 5 files changed, 100 insertions(+), 19 deletions(-) diff --git a/include/aiQuaternion.h b/include/aiQuaternion.h index 5bbe2c5ef..41373dad1 100644 --- a/include/aiQuaternion.h +++ b/include/aiQuaternion.h @@ -79,6 +79,14 @@ struct aiQuaternion bool operator!= (const aiQuaternion& o) const {return !(*this == o);} + /** Performs a spherical interpolation between two quaternions and writes the result into the third. + * @param pOut Target object to received the interpolated rotation. + * @param pStart Start rotation of the interpolation at factor == 0. + * @param pEnd End rotation, factor == 1. + * @param pFactor Interpolation factor between 0 and 1. Values outside of this range yield undefined results. + */ + static void Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor); + #endif // __cplusplus //! w,x,y,z components of the quaternion @@ -197,7 +205,48 @@ inline aiQuaternion::aiQuaternion( aiVector3D normalized) } - +// --------------------------------------------------------------------------- +// Performs a spherical interpolation between two quaternions +// Implementation adopted from the gmtl project. All others I found on the net fail in some cases. +// Congrats, gmtl! +inline void aiQuaternion::Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor) +{ + // calc cosine theta + float cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w; + + // adjust signs (if necessary) + aiQuaternion end = pEnd; + if( cosom < 0.0f) + { + cosom = -cosom; + end.x = -end.x; // Reverse all signs + end.y = -end.y; + end.z = -end.z; + end.w = -end.w; + } + + // Calculate coefficients + float sclp, sclq; + if( (1.0f - cosom) > 0.0001f) // 0.0001 -> some epsillon + { + // Standard case (slerp) + float omega, sinom; + omega = acos( cosom); // extract theta from dot product's cos theta + sinom = sin( omega); + sclp = sin( (1.0f - pFactor) * omega) / sinom; + sclq = sin( pFactor * omega) / sinom; + } else + { + // Very close, do linear interp (because it's faster) + sclp = 1.0f - pFactor; + sclq = pFactor; + } + + pOut.x = sclp * pStart.x + sclq * end.x; + pOut.y = sclp * pStart.y + sclq * end.y; + pOut.z = sclp * pStart.z + sclq * end.z; + pOut.w = sclp * pStart.w + sclq * end.w; +} } // end extern "C" #endif // __cplusplus diff --git a/tools/assimp_view/AnimEvaluator.cpp b/tools/assimp_view/AnimEvaluator.cpp index 9f86abc55..290dc0161 100644 --- a/tools/assimp_view/AnimEvaluator.cpp +++ b/tools/assimp_view/AnimEvaluator.cpp @@ -89,8 +89,15 @@ void AnimEvaluator::Evaluate( double pTime) frame++; } - // TODO: (thom) interpolation maybe? - presentPosition = channel->mPositionKeys[frame].mValue; + // interpolate between this frame's value and next frame's value + unsigned int nextFrame = (frame + 1) % channel->mNumPositionKeys; + const aiVectorKey& key = channel->mPositionKeys[frame]; + const aiVectorKey& nextKey = channel->mPositionKeys[nextFrame]; + double diffTime = nextKey.mTime - key.mTime; + if( diffTime < 0.0) + diffTime += mAnim->mDuration; + float factor = (time - key.mTime) / diffTime; + presentPosition = key.mValue + (nextKey.mValue - key.mValue) * factor; mLastPositions[a].get<0>() = frame; } @@ -106,8 +113,16 @@ void AnimEvaluator::Evaluate( double pTime) frame++; } - // TODO: (thom) quaternions are a prime target for interpolation - presentRotation = channel->mRotationKeys[frame].mValue; + // interpolate between this frame's value and next frame's value + unsigned int nextFrame = (frame + 1) % channel->mNumRotationKeys; + const aiQuatKey& key = channel->mRotationKeys[frame]; + const aiQuatKey& nextKey = channel->mRotationKeys[nextFrame]; + double diffTime = nextKey.mTime - key.mTime; + if( diffTime < 0.0) + diffTime += mAnim->mDuration; + float factor = (time - key.mTime) / diffTime; + + aiQuaternion::Interpolate( presentRotation, key.mValue, nextKey.mValue, factor); mLastPositions[a].get<1>() = frame; } diff --git a/tools/assimp_view/Shaders.cpp b/tools/assimp_view/Shaders.cpp index 3f3040f1a..3ec677b26 100644 --- a/tools/assimp_view/Shaders.cpp +++ b/tools/assimp_view/Shaders.cpp @@ -697,10 +697,11 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SKINNING \n" "float4 weights = IN.BlendWeights; \n" "weights.w = 1.0f - dot( weights.xyz, float3( 1, 1, 1)); \n" - "float3 objPos = mul( IN.Position, gBoneMatrix[IN.BlendIndices.x]) * weights.x; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.y]) * weights.y; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.z]) * weights.z; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.w]) * weights.w; \n" + "float4 localPos = float4( IN.Position, 1.0f); \n" + "float3 objPos = mul( localPos, gBoneMatrix[IN.BlendIndices.x]) * weights.x; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.y]) * weights.y; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.z]) * weights.z; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.w]) * weights.w; \n" "#else \n" "float3 objPos = IN.Position; \n" "#endif // AV_SKINNING \n" @@ -733,10 +734,11 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SKINNING \n" "float4 weights = IN.BlendWeights; \n" "weights.w = 1.0f - dot( weights.xyz, float3( 1, 1, 1)); \n" - "float3 objPos = mul( IN.Position, gBoneMatrix[IN.BlendIndices.x]) * weights.x; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.y]) * weights.y; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.z]) * weights.z; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.w]) * weights.w; \n" + "float4 localPos = float4( IN.Position, 1.0f); \n" + "float3 objPos = mul( localPos, gBoneMatrix[IN.BlendIndices.x]) * weights.x; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.y]) * weights.y; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.z]) * weights.z; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.w]) * weights.w; \n" "#else \n" "float3 objPos = IN.Position; \n" "#endif // AV_SKINNING \n" @@ -770,10 +772,11 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SKINNING \n" "float4 weights = IN.BlendWeights; \n" "weights.w = 1.0f - dot( weights.xyz, float3( 1, 1, 1)); \n" - "float3 objPos = mul( IN.Position, gBoneMatrix[IN.BlendIndices.x]) * weights.x; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.y]) * weights.y; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.z]) * weights.z; \n" - "objPos += mul( IN.Position, gBoneMatrix[IN.BlendIndices.w]) * weights.w; \n" + "float4 localPos = float4( IN.Position, 1.0f); \n" + "float3 objPos = mul( localPos, gBoneMatrix[IN.BlendIndices.x]) * weights.x; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.y]) * weights.y; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.z]) * weights.z; \n" + "objPos += mul( localPos, gBoneMatrix[IN.BlendIndices.w]) * weights.w; \n" "#else \n" "float3 objPos = IN.Position; \n" "#endif // AV_SKINNING \n" diff --git a/workspaces/vc9_ATMNotUpToDate/assimp.sln b/workspaces/vc9_ATMNotUpToDate/assimp.sln index 00bf8b248..51b553bb6 100644 --- a/workspaces/vc9_ATMNotUpToDate/assimp.sln +++ b/workspaces/vc9_ATMNotUpToDate/assimp.sln @@ -65,7 +65,6 @@ Global {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.Build.0 = Debug_DLL|x64 {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|Win32.ActiveCfg = Debug|Win32 {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.ActiveCfg = Debug|x64 - {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.Build.0 = Debug|x64 {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.ActiveCfg = Release_DLL|Win32 {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.Build.0 = Release_DLL|Win32 {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.ActiveCfg = Release_DLL|x64 @@ -78,7 +77,6 @@ Global {FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug_DLL|x64.ActiveCfg = Debug|x64 {FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug|Win32.ActiveCfg = Debug|Win32 {FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug|x64.ActiveCfg = Debug|x64 - {FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug|x64.Build.0 = Debug|x64 {FE78BFBA-4BA5-457D-8602-B800D498102D}.Release_DLL|Win32.ActiveCfg = Release|Win32 {FE78BFBA-4BA5-457D-8602-B800D498102D}.Release_DLL|x64.ActiveCfg = Release|x64 {FE78BFBA-4BA5-457D-8602-B800D498102D}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/workspaces/vc9_ATMNotUpToDate/assimp.vcproj b/workspaces/vc9_ATMNotUpToDate/assimp.vcproj index 6ad7e9b6f..99e3a6f7f 100644 --- a/workspaces/vc9_ATMNotUpToDate/assimp.vcproj +++ b/workspaces/vc9_ATMNotUpToDate/assimp.vcproj @@ -836,6 +836,14 @@ RelativePath="..\..\code\SceneCombiner.h" > + + + + @@ -963,6 +971,14 @@ + + + +