Browse Source

Bugfix: Properly apply default bone transforms when bones aren't directly animated

BearishSun 7 years ago
parent
commit
f9180cb090
1 changed files with 19 additions and 15 deletions
  1. 19 15
      Source/BansheeCore/Animation/BsSkeleton.cpp

+ 19 - 15
Source/BansheeCore/Animation/BsSkeleton.cpp

@@ -170,6 +170,9 @@ namespace bs
 			localPose.scales[i] = Vector3::ONE;
 		}
 
+		bool* hasAnimCurve = bs_stack_alloc<bool>(mNumBones);
+		bs_zero_out(hasAnimCurve, mNumBones);
+
 		// Note: For a possible performance improvement consider keeping an array of only active (non-disabled) bones and
 		// just iterate over them without mask checks. Possibly also a list of active curve mappings to avoid those checks
 		// as well.
@@ -206,8 +209,6 @@ namespace bs
 					if (!mask.isEnabled(k))
 						continue;
 
-					bool hasAnimCurve = false;
-
 					const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
 					UINT32 curveIdx = mapping.position;
 					if (curveIdx != (UINT32)-1)
@@ -216,7 +217,7 @@ namespace bs
 						localPose.positions[k] += curve.evaluate(state.time, state.positionCaches[curveIdx], state.loop) * normWeight;
 
 						localPose.hasOverride[k] = false;
-						hasAnimCurve = true;
+						hasAnimCurve[k] = true;
 					}
 
 					curveIdx = mapping.scale;
@@ -226,7 +227,7 @@ namespace bs
 						localPose.scales[k] *= curve.evaluate(state.time, state.scaleCaches[curveIdx], state.loop) * normWeight;
 
 						localPose.hasOverride[k] = false;
-						hasAnimCurve = true;
+						hasAnimCurve[k] = true;
 					}
 
 					if (layer.additive)
@@ -245,7 +246,7 @@ namespace bs
 
 							localPose.rotations[k] *= value;
 							localPose.hasOverride[k] = false;
-							hasAnimCurve = true;
+							hasAnimCurve[k] = true;
 						}
 					}
 					else
@@ -261,22 +262,24 @@ namespace bs
 
 							localPose.rotations[k] += value;
 							localPose.hasOverride[k] = false;
-							hasAnimCurve = true;
+							hasAnimCurve[k] = true;
 						}
 					}
-
-					// If no animation for this bone, apply its default transform
-					// (Even if this bone isn't used for the skin, the child bones need to inherit this transform)
-					if(!hasAnimCurve)
-					{
-						localPose.positions[k] = mBoneTransforms[k].getPosition();
-						localPose.rotations[k] = mBoneTransforms[k].getRotation();
-						localPose.scales[k] = mBoneTransforms[k].getScale();
-					}
 				}
 			}
 		}
 
+		// Apply default local tranform to non-animated bones (so that any potential child bones are transformed properly)
+		for(UINT32 i = 0; i < mNumBones; i++)
+		{
+			if(hasAnimCurve[i])
+				continue;
+
+			localPose.positions[i] = mBoneTransforms[i].getPosition();
+			localPose.rotations[i] = mBoneTransforms[i].getRotation();
+			localPose.scales[i] = mBoneTransforms[i].getScale();
+		}
+
 		// Calculate local pose matrices
 		UINT32 isGlobalBytes = sizeof(bool) * mNumBones;
 		bool* isGlobal = (bool*)bs_stack_alloc(isGlobalBytes);
@@ -328,6 +331,7 @@ namespace bs
 			pose[i] = pose[i] * mInvBindPoses[i];
 
 		bs_stack_free(isGlobal);
+		bs_stack_free(hasAnimCurve);
 	}
 
 	UINT32 Skeleton::getRootBoneIndex() const