My program must interpolate between two sets of quaternion fcurves by a given value. Normally, one would SLERP or LERP. However, my program includes the option to 'turn off' the individual x/y/z axes, as well as adjust the overall influence of the rotation.
It is my understanding that I must convert my quaternions to Eulers in order to align the individual axes of two fcurves.
The problem is that the converted Eulers' values shift at specific points in my animation: When the +/- signs of my two quaternations' 'W' axes are misaligned (i.e., when one is positive and the other negative). When this happens, the resulting Euler values aren't property aligned. Given that the behavior seems predictable, I was wondering if there was a predictable, elegant way to solve for it, or alternatively, a different method for disabling axes when dealing with quaternations.
My code:
def_rot_quat = mathutils.Quaternion([fcurve.evaluate(frame) for fcurve in def_rot_fcurves])
# Convert to euler
bake_euler = bake_rot_quat.to_euler()
def_euler = def_rot_quat.to_euler()
# disable axes
for axis in range(3):
if rot_axes_inf[axis] == 0:
def_euler[axis] = bake_euler[axis]
# Convert back to quaternion
def_rot_quat = def_euler.to_quaternion()
influenced_rot_quat = bake_rot_quat.slerp(def_rot_quat, influence)
print statement, where the x-axis was disabled
frame: 15.0 (broken result)
bake_rot_quat: <Quaternion (w=-0.0784, x=0.6405, y=0.2995, z=0.7027)>
def_rot_quat (before update): <Quaternion (w=0.0107, x=0.6732, y=0.2165, z=0.7070)>
bake_rot_euler: (-89.99996835353231, -108.69269347023982, -58.57019718955832)
def_rot_euler (before update): (90.00000933466734, -71.30731836890568, 106.95994960988845)
def_rot_euler (after update): (-89.99996835353231, -71.30731836890568, 106.95994960988845)
def_rot_quat (after conversion): <Quaternion (w=0.6732, x=-0.0107, y=-0.7070, z=0.2165)>
frame: 16.0 (correct result)
bake_rot_quat: <Quaternion (w=-0.1036, x=0.6294, y=0.3223, z=0.6995)>
def_rot_quat (before update): <Quaternion (w=-0.0208, x=0.6628, y=0.2462, z=0.7068)>
bake_rot_euler: (-89.99997518372149, -108.69268664005064, -54.45409638437144)
def_rot_euler (before update): (-89.99997518372149, -108.69269347023982, -67.93306148494682)
def_rot_euler (after update): (-89.99997518372149, -108.69269347023982, -67.93306148494682)
def_rot_quat (after conversion): <Quaternion (w=0.0208, x=-0.6628, y=-0.2462, z=-0.7068)>