瀏覽代碼

Animation sockets (bone binding) functional

BearishSun 9 年之前
父節點
當前提交
ab7c1385b9
共有 2 個文件被更改,包括 75 次插入4 次删除
  1. 74 3
      Source/BansheeCore/Source/BsAnimation.cpp
  2. 1 1
      Source/MBansheeEngine/Animation/Animation.cs

+ 74 - 3
Source/BansheeCore/Source/BsAnimation.cpp

@@ -1099,6 +1099,8 @@ namespace BansheeEngine
 
 	void Animation::updateFromProxy()
 	{
+		HSceneObject rootSO;
+
 		// Write TRS animation results to relevant SceneObjects
 		for(UINT32 i = 0; i < mAnimProxy->numSceneObjects; i++)
 		{
@@ -1109,14 +1111,83 @@ namespace BansheeEngine
 				continue;
 
 			HSceneObject so = iterFind->second.so;
+			if (iterFind->second.curveName.empty())
+				rootSO = so;
+
 			if (so.isDestroyed(true))
 				continue;
 
 			if(soInfo.boneIdx != -1)
 			{
-				so->setPosition(mAnimProxy->skeletonPose.positions[soInfo.boneIdx]);
-				so->setRotation(mAnimProxy->skeletonPose.rotations[soInfo.boneIdx]);
-				so->setScale(mAnimProxy->skeletonPose.scales[soInfo.boneIdx]);
+				Vector3 position = mAnimProxy->skeletonPose.positions[soInfo.boneIdx];
+				Quaternion rotation = mAnimProxy->skeletonPose.rotations[soInfo.boneIdx];
+				Vector3 scale = mAnimProxy->skeletonPose.scales[soInfo.boneIdx];
+
+				const SPtr<Skeleton>& skeleton = mAnimProxy->skeleton;
+
+				UINT32 parentBoneIdx = skeleton->getBoneInfo(soInfo.boneIdx).parent;
+				if (parentBoneIdx == -1)
+				{
+					so->setPosition(position);
+					so->setRotation(rotation);
+					so->setScale(scale);
+				}
+				else
+				{
+					while(parentBoneIdx != -1)
+					{
+						// Update rotation
+						const Quaternion& parentOrientation = mAnimProxy->skeletonPose.rotations[parentBoneIdx];
+						rotation = parentOrientation * rotation;
+
+						// Update scale
+						const Vector3& parentScale = mAnimProxy->skeletonPose.scales[parentBoneIdx];
+						scale = parentScale * scale;
+
+						// Update position
+						position = parentOrientation.rotate(parentScale * position);
+						position += mAnimProxy->skeletonPose.positions[parentBoneIdx];
+
+						parentBoneIdx = skeleton->getBoneInfo(parentBoneIdx).parent;
+					}
+
+					// Search for root if not already found
+					if(rootSO == nullptr)
+					{
+						for(auto& entry : mSceneObjects)
+						{
+							if (entry.second.curveName.empty())
+								rootSO = entry.second.so;
+						}
+					}
+
+					Vector3 rootParentPos = Vector3::ZERO;
+					Quaternion rootParentRot = Quaternion::IDENTITY;
+					Vector3 rootParentScale = Vector3::ONE;
+
+					if(rootSO.isDestroyed(true))
+					{
+						HSceneObject rootParent = rootSO->getParent();
+						if(!rootParent.isDestroyed(true))
+						{
+							rootParentPos = rootParent->getWorldPosition();
+							rootParentRot = rootParent->getWorldRotation();
+							rootParentScale = rootParent->getWorldScale();
+						}
+					}
+
+					// Transform from space relative to root's parent to world space
+					rotation = rootParentRot * rotation;
+
+					scale = rootParentScale * scale;
+
+					position = rootParentRot.rotate(rootParentScale * position);
+					position += rootParentPos;
+
+					so->setWorldPosition(position);
+					so->setWorldRotation(rotation);
+					so->setWorldScale(scale);
+				}
 			}
 			else
 			{

+ 1 - 1
Source/MBansheeEngine/Animation/Animation.cs

@@ -695,8 +695,8 @@ namespace BansheeEngine
             {
                 if (mappingInfo[i].bone == bone)
                 {
-                    mappingInfo.RemoveAt(i);
                     _native.UnmapSceneObject(mappingInfo[i].sceneObject);
+                    mappingInfo.RemoveAt(i);
                     i--;
                 }
             }