Browse Source

Scale animation on import if required
Bake non-standard transform parameters into FBX nodes before import
Properly apply correct material technique when rendering

BearishSun 9 years ago
parent
commit
20ee889512

+ 1 - 1
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -121,7 +121,7 @@ namespace BansheeEngine
 	{
 	{
 		RenderAPICore& rapi = RenderAPICore::instance();
 		RenderAPICore& rapi = RenderAPICore::instance();
 
 
-		SPtr<PassCore> pass = material->getPass(passIdx);
+		SPtr<PassCore> pass = material->getPass(passIdx, techniqueIdx);
 
 
 		struct StageData
 		struct StageData
 		{
 		{

+ 6 - 0
Source/BansheeFBXImporter/Include/BsFBXImporter.h

@@ -97,6 +97,9 @@ namespace BansheeEngine
 		void importAnimations(FbxAnimLayer* layer, FbxNode* node, FBXImportOptions& importOptions, 
 		void importAnimations(FbxAnimLayer* layer, FbxNode* node, FBXImportOptions& importOptions, 
 			FBXAnimationClip& clip, FBXImportScene& importScene);
 			FBXAnimationClip& clip, FBXImportScene& importScene);
 
 
+		/** Bakes all FBX node transforms into standard translation-rotation-scale transform components. */
+		void bakeTransforms(FbxScene* scene);
+
 		/**	Converts a single FBX animation curve into an engine curve format, resampling it if necessary. */
 		/**	Converts a single FBX animation curve into an engine curve format, resampling it if necessary. */
 		template<class T, int C>
 		template<class T, int C>
 		TAnimationCurve<T> importCurve(FbxAnimCurve*(&fbxCurve)[C], FBXImportOptions& importOptions, float start, float end);
 		TAnimationCurve<T> importCurve(FbxAnimCurve*(&fbxCurve)[C], FBXImportOptions& importOptions, float start, float end);
@@ -111,6 +114,9 @@ namespace BansheeEngine
 		 */
 		 */
 		TAnimationCurve<Vector3> reduceKeyframes(TAnimationCurve<Vector3>& curve);
 		TAnimationCurve<Vector3> reduceKeyframes(TAnimationCurve<Vector3>& curve);
 
 
+		/** Applies a scale to all keyframe values and tangents. */
+		TAnimationCurve<Vector3> scaleKeyframes(TAnimationCurve<Vector3>& curve, float scale);
+
 		/**
 		/**
 		 * Converts all the meshes from per-index attributes to per-vertex attributes.
 		 * Converts all the meshes from per-index attributes to per-vertex attributes.
 		 *
 		 *

+ 76 - 1
Source/BansheeFBXImporter/Source/BsFBXImporter.cpp

@@ -217,6 +217,7 @@ namespace BansheeEngine
 		fbxImportOptions.importScale = meshImportOptions->getImportScale();
 		fbxImportOptions.importScale = meshImportOptions->getImportScale();
 
 
 		FBXImportScene importedScene;
 		FBXImportScene importedScene;
+		bakeTransforms(fbxScene);
 		parseScene(fbxScene, fbxImportOptions, importedScene);
 		parseScene(fbxScene, fbxImportOptions, importedScene);
 
 
 		if (fbxImportOptions.importBlendShapes)
 		if (fbxImportOptions.importBlendShapes)
@@ -1250,7 +1251,6 @@ namespace BansheeEngine
 			Matrix4 bakedTransform = mesh.referencedBy[0]->worldTransform * importScale;
 			Matrix4 bakedTransform = mesh.referencedBy[0]->worldTransform * importScale;
 
 
 			invBakedTransform = bakedTransform.inverseAffine();
 			invBakedTransform = bakedTransform.inverseAffine();
-			invBakedTransform.inverseAffine();
 		}
 		}
 		else
 		else
 			invBakedTransform = Matrix4::IDENTITY;
 			invBakedTransform = Matrix4::IDENTITY;
@@ -1503,6 +1503,9 @@ namespace BansheeEngine
 				eulerAnimation = reduceKeyframes(eulerAnimation);
 				eulerAnimation = reduceKeyframes(eulerAnimation);
 			}
 			}
 
 
+			if (importOptions.importScale != 1.0f)
+				boneAnim.translation = scaleKeyframes(boneAnim.translation, importOptions.importScale);
+
 			boneAnim.rotation = AnimationUtility::eulerToQuaternionCurve(eulerAnimation);
 			boneAnim.rotation = AnimationUtility::eulerToQuaternionCurve(eulerAnimation);
 		}
 		}
 
 
@@ -1544,6 +1547,60 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
+	void FBXImporter::bakeTransforms(FbxScene* scene)
+	{
+		// FBX stores transforms in a more complex way than just translation-rotation-scale as used by Banshee.
+		// Instead they also support rotations offsets and pivots, scaling pivots and more. We wish to bake all this data
+		// into a standard transform so we can access it using node's local TRS properties (e.g. FbxNode::LclTranslation).
+
+		double frameRate = FbxTime::GetFrameRate(scene->GetGlobalSettings().GetTimeMode());
+
+		bs_frame_mark();
+		{
+			FrameStack<FbxNode*> todo;
+			todo.push(scene->GetRootNode());
+
+			while(todo.size() > 0)
+			{
+				FbxNode* node = todo.top();
+				todo.pop();
+
+				FbxVector4 zero(0, 0, 0);
+				FbxVector4 one(1, 1, 1);
+
+				// Activate pivot converting
+				node->SetPivotState(FbxNode::eSourcePivot, FbxNode::ePivotActive);
+				node->SetPivotState(FbxNode::eDestinationPivot, FbxNode::ePivotActive);
+
+				// We want to set all these to 0 (1 for scale) and bake them into the transforms
+				node->SetPostRotation(FbxNode::eDestinationPivot, zero);
+				node->SetPreRotation(FbxNode::eDestinationPivot, zero);
+				node->SetRotationOffset(FbxNode::eDestinationPivot, zero);
+				node->SetScalingOffset(FbxNode::eDestinationPivot, zero);
+				node->SetRotationPivot(FbxNode::eDestinationPivot, zero);
+				node->SetScalingPivot(FbxNode::eDestinationPivot, zero);
+				node->SetGeometricTranslation(FbxNode::eDestinationPivot, zero);
+				node->SetGeometricRotation(FbxNode::eDestinationPivot, zero);
+				node->SetGeometricScaling(FbxNode::eDestinationPivot, one);
+
+				// Banshee assumes euler angles are in YXZ order
+				node->SetRotationOrder(FbxNode::eDestinationPivot, FbxEuler::eOrderYXZ);
+
+				// Keep interpolation as is
+				node->SetQuaternionInterpolation(FbxNode::eDestinationPivot, node->GetQuaternionInterpolation(FbxNode::eSourcePivot));
+
+				for (int i = 0; i < node->GetChildCount(); i++)
+				{
+					FbxNode* childNode = node->GetChild(i);
+					todo.push(childNode);
+				}
+			}
+
+			scene->GetRootNode()->ConvertPivotAnimationRecursive(nullptr, FbxNode::eDestinationPivot, frameRate, false);
+		}
+		bs_frame_clear();
+	}
+
 	TAnimationCurve<Vector3> FBXImporter::reduceKeyframes(TAnimationCurve<Vector3>& curve)
 	TAnimationCurve<Vector3> FBXImporter::reduceKeyframes(TAnimationCurve<Vector3>& curve)
 	{
 	{
 		UINT32 keyCount = curve.getNumKeyFrames();
 		UINT32 keyCount = curve.getNumKeyFrames();
@@ -1584,6 +1641,24 @@ namespace BansheeEngine
 
 
 		return TAnimationCurve<Vector3>(newKeyframes);
 		return TAnimationCurve<Vector3>(newKeyframes);
 	}
 	}
+
+	TAnimationCurve<Vector3> FBXImporter::scaleKeyframes(TAnimationCurve<Vector3>& curve, float scale)
+	{
+		UINT32 keyCount = curve.getNumKeyFrames();
+
+		Vector<TKeyframe<Vector3>> newKeyframes(keyCount);
+		for (UINT32 i = 0; i < keyCount; i++)
+		{
+			TKeyframe<Vector3> curKey = curve.getKeyFrame(i);
+			curKey.value *= scale;
+			curKey.inTangent *= scale;
+			curKey.outTangent *= scale;
+
+			newKeyframes[i] = curKey;
+		}
+
+		return TAnimationCurve<Vector3>(newKeyframes);
+	}
 	
 	
 	template<class T>
 	template<class T>
 	void setKeyframeValues(TKeyframe<T>& keyFrame, int idx, float value, float inTangent, float outTangent)
 	void setKeyframeValues(TKeyframe<T>& keyFrame, int idx, float value, float inTangent, float outTangent)