diff options
Diffstat (limited to 'source/blender/blenkernel/intern/fcurve.c')
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index ef53c926daa..c4da2d2efc9 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1732,35 +1732,21 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) * - only an option for "transform space", if quality is really bad with a) */ float quat[4]; - float *const eul = quat + 1; int channel; if (dtar->transChan == DTAR_TRANSCHAN_ROTW) { channel = 0; - quat[0] = 0.0f; } else { channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX; BLI_assert(channel < 4); } - if (dtar->rotation_mode == DTAR_ROTMODE_AUTO) { - mat4_to_eulO(eul, rot_order, mat); + BKE_driver_target_matrix_to_rot_channels( + mat, rot_order, dtar->rotation_mode, channel, false, quat); - if (use_eulers) { - compatible_eul(eul, oldEul); - } - } - else if (dtar->rotation_mode >= DTAR_ROTMODE_EULER_MIN && - dtar->rotation_mode <= DTAR_ROTMODE_EULER_MAX) { - mat4_to_eulO(eul, dtar->rotation_mode, mat); - } - else if (dtar->rotation_mode == DTAR_ROTMODE_QUATERNION) { - mat4_to_quat(quat, mat); - } - else { - BLI_assert(false); - zero_v3(eul); + if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) { + compatible_eul(quat + 1, oldEul); } return quat[channel]; @@ -1771,6 +1757,52 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) } } +/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */ +static void quaternion_to_angles(float quat[4], int channel) +{ + if (channel < 0) { + quat[0] = 2.0f * saacosf(quat[0]); + + for (int i = 1; i < 4; i++) { + quat[i] = 2.0f * saasinf(quat[i]); + } + } + else if (channel == 0) { + quat[0] = 2.0f * saacosf(quat[0]); + } + else { + quat[channel] = 2.0f * saasinf(quat[channel]); + } +} + +/* Compute channel values for a rotational Transform Channel driver variable. */ +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]) +{ + float *const quat = r_buf; + float *const eul = r_buf + 1; + + zero_v4(r_buf); + + if (rotation_mode == DTAR_ROTMODE_AUTO) { + mat4_to_eulO(eul, auto_order, mat); + } + else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) { + mat4_to_eulO(eul, rotation_mode, mat); + } + else if (rotation_mode == DTAR_ROTMODE_QUATERNION) { + mat4_to_quat(quat, mat); + + /* For Transformation constraint convenience, convert to pseudo-angles. */ + if (angles) { + quaternion_to_angles(quat, channel); + } + } + else { + BLI_assert(false); + } +} + /* ......... */ /* Table of Driver Variable Type Info Data */ |