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