Преглед на файлове

- 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

ulfjorensen преди 17 години
родител
ревизия
d965f0d06a
променени са 5 файла, в които са добавени 100 реда и са изтрити 19 реда
  1. 50 1
      include/aiQuaternion.h
  2. 19 4
      tools/assimp_view/AnimEvaluator.cpp
  3. 15 12
      tools/assimp_view/Shaders.cpp
  4. 0 2
      workspaces/vc9_ATMNotUpToDate/assimp.sln
  5. 16 0
      workspaces/vc9_ATMNotUpToDate/assimp.vcproj

+ 50 - 1
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

+ 19 - 4
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;
 		}
 

+ 15 - 12
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"

+ 0 - 2
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

+ 16 - 0
workspaces/vc9_ATMNotUpToDate/assimp.vcproj

@@ -836,6 +836,14 @@
 				RelativePath="..\..\code\SceneCombiner.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\code\ScenePreprocessor.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\code\ScenePreprocessor.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\code\SGSpatialSort.cpp"
 				>
@@ -963,6 +971,14 @@
 			<Filter
 				Name="Loaders"
 				>
+				<File
+					RelativePath="..\..\code\Q3DLoader.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\code\Q3DLoader.h"
+					>
+				</File>
 				<Filter
 					Name="3DS"
 					>