diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index fe995b2e46e..ef10d02f10f 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -164,6 +164,9 @@ void compatible_eul(float eul[3], const float old[3]); void rotate_eul(float eul[3], const char axis, const float angle); +void add_eul_euleul(float r_eul[3], float a[3], float b[3], const short order); +void sub_eul_euleul(float r_eul[3], float a[3], float b[3], const short order); + /************************** Arbitrary Order Eulers ***************************/ /* warning: must match the eRotationModes in DNA_action_types.h diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 57fe99ce019..469cd573372 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1924,6 +1924,31 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order gmat[R->axis[2]][R->axis[2]] = 1; } +void add_eul_euleul(float r_eul[3], float a[3], float b[3], const short order) +{ + float quat[4], quat_b[4]; + + eulO_to_quat(quat, a, order); + eulO_to_quat(quat_b, b, order); + + mul_qt_qtqt(quat, quat_b, quat); + + quat_to_eulO(r_eul, order, quat); +} + +void sub_eul_euleul(float r_eul[3], float a[3], float b[3], const short order) +{ + float quat[4], quat_b[4]; + + eulO_to_quat(quat, a, order); + eulO_to_quat(quat_b, b, order); + + invert_qt_normalized(quat_b); + mul_qt_qtqt(quat, quat_b, quat); + + quat_to_eulO(r_eul, order, quat); +} + /******************************* Dual Quaternions ****************************/ /** diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 350be247014..6a946994e06 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -734,9 +734,25 @@ void ElementRotation_ex(TransInfo *t, /* can be called for texture space translate for example, then opt out */ if (td->ext->quat) { mul_m3_series(fmat, td->smtx, mat, td->mtx); + + if (!is_zero_v3(td->ext->dquat)) { + /* Correct for delta quat */ + float tmp_mat[3][3]; + quat_to_mat3(tmp_mat, td->ext->dquat); + mul_m3_m3m3(fmat, fmat, tmp_mat); + } + mat3_to_quat(quat, fmat); /* Actual transform */ + if (!is_zero_v4(td->ext->dquat)) { + /* Correct back for delta quat. */ + float idquat[4]; + invert_qt_qt_normalized(idquat, td->ext->dquat); + mul_qt_qtqt(quat, idquat, quat); + } + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } @@ -761,21 +777,28 @@ void ElementRotation_ex(TransInfo *t, td->ext->irotAngle); } else { + /* Calculate the total rotation in eulers. */ float obmat[3][3]; mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); - /* Calculate the total rotation in eulers. */ - add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ - eulO_to_mat3(obmat, eul, td->ext->rotOrder); - /* mat = transform, obmat = object rotation */ - mul_m3_m3m3(fmat, smat, obmat); + if (!is_zero_v3(td->ext->drot)) { + /* Correct for delta rot */ + add_eul_euleul(eul, td->ext->irot, td->ext->drot, td->ext->rotOrder); + } + else { + copy_v3_v3(eul, td->ext->irot); + } + eulO_to_mat3(obmat, eul, td->ext->rotOrder); + mul_m3_m3m3(fmat, smat, obmat); mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); - /* correct back for delta rot */ - sub_v3_v3v3(eul, eul, td->ext->drot); + if (!is_zero_v3(td->ext->drot)) { + /* Correct back for delta rot. */ + sub_eul_euleul(eul, eul, td->ext->drot, td->ext->rotOrder); + } /* and apply */ protectedRotateBits(td->protectflag, eul, td->ext->irot);