Fix #141718: Discontinuous rotations on some USD skeleton imports
Due to ambiguity when decomposing the incoming skeleton joint matrix, it's possible for the returned quaternion rotation to be "flipped" from the perspective of prior/future frames due to the quaternion double-cover property. This would manifest as glitchy animations and subtly incorrect motion blur results during render. This PR implements the traditional mitigation of comparing with the prior frame's rotation data and negating the quat if necessary. An alternate method to instead compare with the rest positions was attempted but it still allowed flipped/discontinuous rotations for spinning objects like wheels and propellers. Pull Request: https://projects.blender.org/blender/blender/pulls/142026
This commit is contained in:
committed by
Jesse Yurkovich
parent
50ec3cb2d4
commit
1d2c1d2fa7
@@ -221,6 +221,7 @@ void import_skeleton_curves(Main *bmain,
|
||||
}
|
||||
|
||||
/* Set the curve samples. */
|
||||
blender::Array<pxr::GfQuatf> prev_rot(joint_order.size());
|
||||
uint bezt_index = 0;
|
||||
for (const double frame : samples) {
|
||||
pxr::VtMatrix4dArray joint_local_xforms;
|
||||
@@ -251,6 +252,17 @@ void import_skeleton_curves(Main *bmain,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bezt_index > 0) {
|
||||
/* Quaternion "neighborhood" check to prevent most cases of discontinuous rotations.
|
||||
* Note: An alternate method, comparing to the rotation of the rest position rather than
|
||||
* to the previous rotation, was attempted but yielded much worse results for joints
|
||||
* representing objects that are supposed to spin, like wheels and propellers. */
|
||||
if (pxr::GfDot(prev_rot[i], qrot) < 0.0f) {
|
||||
qrot = -qrot;
|
||||
}
|
||||
}
|
||||
prev_rot[i] = qrot;
|
||||
|
||||
const float re = qrot.GetReal();
|
||||
const pxr::GfVec3f &im = qrot.GetImaginary();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user