diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-10-08 04:57:00 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-10-08 04:57:00 +0400 |
commit | 475ab5ceb4875eb37dd761f7a71ff569dd493395 (patch) | |
tree | a545c13c1ea502e60b4c64fb56756c8a3432ed83 /source/blender | |
parent | fd511eb984a23b63b373e171666667c8213579c0 (diff) |
Rotation Modes Bugfix:
Animating rotations using different rotation modes should now work more often than before.
Previously, quaternion and axis-angle values were stored in the same variable in DNA, but that was causing problems with other animation curves overwriting the values and causing the rotations to not work as expected.
There are still some issues, but I'll track those down later tonight
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 28 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 8 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_general.c | 1 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 49 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 14 | ||||
-rw-r--r-- | source/blender/editors/object/object_transform.c | 50 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_buttons.c | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 11 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object.c | 30 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_pose.c | 32 |
14 files changed, 172 insertions, 77 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index e5d0c4274b3..8f109034e3e 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -104,7 +104,7 @@ void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float * void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]); /* Rotation Mode Conversions - Used for PoseChannels + Objects... */ -void BKE_rotMode_change_values(float quat[4], float eul[3], short oldMode, short newMode); +void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode); /* B-Bone support */ typedef struct Mat4 { diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 7be763eae9d..25f539a1992 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -446,7 +446,7 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) strncpy(chan->name, name, 31); /* init vars to prevent math errors */ - chan->quat[0] = 1.0f; + chan->quat[0] = chan->rotAxis[1]= 1.0f; chan->size[0] = chan->size[1] = chan->size[2] = 1.0f; chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; @@ -607,6 +607,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); VECCOPY(pchan->eul, chan->eul); + VECCOPY(pchan->rotAxis, chan->rotAxis); + pchan->rotAngle= chan->rotAngle; QUATCOPY(pchan->quat, chan->quat); pchan->rotmode= chan->rotmode; Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat); @@ -975,14 +977,16 @@ void rest_pose(bPose *pose) memset(pose->stride_offset, 0, sizeof(pose->stride_offset)); memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset)); - for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){ + for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) { for (i=0; i<3; i++) { pchan->loc[i]= 0.0f; pchan->quat[i+1]= 0.0f; pchan->eul[i]= 0.0f; pchan->size[i]= 1.0f; + pchan->rotAxis[i]= 0.0f; } - pchan->quat[0]= 1.0f; + pchan->quat[0]= pchan->rotAxis[1]= 1.0f; + pchan->rotAngle= 0.0f; pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 6220835a620..a0abe780273 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1285,16 +1285,14 @@ void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float /* Called from RNA when rotation mode changes * - the result should be that the rotations given in the provided pointers have had conversions * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed - * - * - as in SDNA data, quat is used to store quaternions AND axis-angle rotations... */ -void BKE_rotMode_change_values (float quat[4], float eul[3], short oldMode, short newMode) +void BKE_rotMode_change_values (float quat[4], float eul[3], float *axis, float angle[3], short oldMode, short newMode) { /* check if any change - if so, need to convert data */ if (newMode > 0) { /* to euler */ if (oldMode == ROT_MODE_AXISANGLE) { /* axis-angle to euler */ - AxisAngleToEulO(&quat[1], quat[0], eul, newMode); + AxisAngleToEulO(axis, *angle, eul, newMode); } else if (oldMode == ROT_MODE_QUAT) { /* quat to euler */ @@ -1305,11 +1303,7 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], short oldMode, shor else if (newMode == ROT_MODE_QUAT) { /* to quat */ if (oldMode == ROT_MODE_AXISANGLE) { /* axis angle to quat */ - float q[4]; - - /* copy to temp var first, since quats and axis-angle are stored in same place */ - QuatCopy(q, quat); - AxisAngleToQuat(q, &quat[1], quat[0]); + AxisAngleToQuat(quat, axis, *angle); } else if (oldMode > 0) { /* euler to quat */ @@ -1317,24 +1311,20 @@ void BKE_rotMode_change_values (float quat[4], float eul[3], short oldMode, shor } /* else { no conversion needed } */ } - else { /* to axis-angle */ + else if (newMode == ROT_MODE_AXISANGLE) { /* to axis-angle */ if (oldMode > 0) { /* euler to axis angle */ EulOToAxisAngle(eul, oldMode, &quat[1], &quat[0]); } else if (oldMode == ROT_MODE_QUAT) { /* quat to axis angle */ - float q[4]; - - /* copy to temp var first, since quats and axis-angle are stored in same place */ - QuatCopy(q, quat); - QuatToAxisAngle(q, &quat[1], &quat[0]); + QuatToAxisAngle(quat, axis, angle); } /* when converting to axis-angle, we need a special exception for the case when there is no axis */ - if (IS_EQ(quat[1], quat[2]) && IS_EQ(quat[2], quat[3])) { + if (IS_EQ(axis[0], axis[1]) && IS_EQ(axis[1], axis[2])) { /* for now, rotate around y-axis then (so that it simply becomes the roll) */ - quat[2]= 1.0f; + axis[1]= 1.0f; } } } @@ -1651,8 +1641,8 @@ void chan_calc_mat(bPoseChannel *chan) EulOToMat3(chan->eul, chan->rotmode, rmat); } else if (chan->rotmode == ROT_MODE_AXISANGLE) { - /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ - AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat); + /* axis-angle - not really that great for 3D-changing orientations */ + AxisAngleToMat3(chan->rotAxis, chan->rotAngle, rmat); } else { /* quats are normalised before use to eliminate scaling issues */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ddf7e7ff4a3..89757533fb8 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1041,6 +1041,8 @@ Object *add_object(struct Scene *scene, int type) * but rotations default to quaternions */ ob->rotmode= ROT_MODE_EUL; + /* axis-angle must not have a 0,0,0 axis, so set y-axis as default... */ + ob->rotAxis[1]= ob->drotAxis[1]= 1.0f; base= scene_add_base(scene, ob); scene_select_base(scene, base); @@ -1602,9 +1604,9 @@ void object_rot_to_mat3(Object *ob, float mat[][3]) EulOToMat3(ob->drot, ob->rotmode, dmat); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { - /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ - AxisAngleToMat3(&ob->quat[1], ob->quat[0], rmat); - AxisAngleToMat3(&ob->dquat[1], ob->dquat[0], dmat); + /* axis-angle - not really that great for 3D-changing orientations */ + AxisAngleToMat3(ob->rotAxis, ob->rotAngle, rmat); + AxisAngleToMat3(ob->drotAxis, ob->drotAngle, dmat); } else { /* quats are normalised before use to eliminate scaling issues */ diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index f13d35c7d4a..3ad6ddf2c6f 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -581,6 +581,7 @@ short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data) for (aci= animcopybuf.first; aci; aci= aci->next) { /* check that paths exist */ if (aci->rna_path && fcu->rna_path) { + // FIXME: this breaks for bone names! if (strcmp(aci->rna_path, fcu->rna_path) == 0) { /* should be a match unless there's more than one of these */ if ((no_name) || (aci->array_index == fcu->array_index)) diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index c32837be420..0343fea5bfb 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -4875,14 +4875,39 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) /* check if convert to eulers for locking... */ if (pchan->protectflag & OB_LOCK_ROT4D) { /* perform clamping on a component by component basis */ - if ((pchan->protectflag & OB_LOCK_ROTW) == 0) - pchan->quat[0]= (pchan->rotmode == ROT_MODE_AXISANGLE) ? 0.0f : 1.0f; - if ((pchan->protectflag & OB_LOCK_ROTX) == 0) - pchan->quat[1]= 0.0f; - if ((pchan->protectflag & OB_LOCK_ROTY) == 0) - pchan->quat[2]= 0.0f; - if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) - pchan->quat[3]= 0.0f; + if (pchan->rotmode == ROT_MODE_AXISANGLE) { + if ((pchan->protectflag & OB_LOCK_ROTW) == 0) + pchan->rotAngle= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTX) == 0) + pchan->rotAxis[0]= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTY) == 0) + pchan->rotAxis[1]= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) + pchan->rotAxis[2]= 0.0f; + + /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */ + if (IS_EQ(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQ(pchan->rotAxis[1], pchan->rotAxis[2])) + pchan->rotAxis[1] = 1.0f; + } + else if (pchan->rotmode == ROT_MODE_QUAT) { + if ((pchan->protectflag & OB_LOCK_ROTW) == 0) + pchan->quat[0]= 1.0f; + if ((pchan->protectflag & OB_LOCK_ROTX) == 0) + pchan->quat[1]= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTY) == 0) + pchan->quat[2]= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) + pchan->quat[3]= 0.0f; + } + else { + /* the flag may have been set for the other modes, so just ignore the extra flag... */ + if ((pchan->protectflag & OB_LOCK_ROTX) == 0) + pchan->eul[0]= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTY) == 0) + pchan->eul[1]= 0.0f; + if ((pchan->protectflag & OB_LOCK_ROTZ) == 0) + pchan->eul[2]= 0.0f; + } } else { /* perform clamping using euler form (3-components) */ @@ -4893,7 +4918,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) QuatToEul(pchan->quat, oldeul); } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { - AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT); + AxisAngleToEulO(pchan->rotAxis, pchan->rotAngle, oldeul, EULER_ORDER_DEFAULT); } else { VECCOPY(oldeul, pchan->eul); @@ -4916,7 +4941,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) } } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { - AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT); + EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, &pchan->rotAngle); } else { VECCOPY(pchan->eul, eul); @@ -4930,8 +4955,8 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { /* by default, make rotation of 0 radians around y-axis (roll) */ - pchan->quat[0]=pchan->quat[1]=pchan->quat[3]= 0.0f; - pchan->quat[2]= 1.0f; + pchan->rotAxis[0]=pchan->rotAxis[2]=pchan->rotAngle= 0.0f; + pchan->rotAxis[1]= 1.0f; } else { pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f; diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index edbc7b9ae9b..461a70bbf86 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -819,7 +819,7 @@ void pose_copy_menu(Scene *scene) /* need to convert to quat first (in temp var)... */ Mat4ToQuat(delta_mat, tmp_quat); - QuatToAxisAngle(tmp_quat, &pchan->quat[1], &pchan->quat[0]); + QuatToAxisAngle(tmp_quat, pchan->rotAxis, &pchan->rotAngle); } else if (pchan->rotmode == ROT_MODE_QUAT) Mat4ToQuat(delta_mat, pchan->quat); @@ -1024,23 +1024,23 @@ static int pose_paste_exec (bContext *C, wmOperator *op) else if (pchan->rotmode > 0) { /* quat/axis-angle to euler */ if (chan->rotmode == ROT_MODE_AXISANGLE) - AxisAngleToEulO(&chan->quat[1], chan->quat[0], pchan->eul, pchan->rotmode); + AxisAngleToEulO(chan->rotAxis, chan->rotAngle, pchan->eul, pchan->rotmode); else QuatToEulO(chan->quat, pchan->eul, pchan->rotmode); } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { /* quat/euler to axis angle */ if (chan->rotmode > 0) - EulOToAxisAngle(chan->eul, chan->rotmode, &pchan->quat[1], &pchan->quat[0]); + EulOToAxisAngle(chan->eul, chan->rotmode, pchan->rotAxis, &pchan->rotAngle); else - QuatToAxisAngle(chan->quat, &pchan->quat[1], &pchan->quat[0]); + QuatToAxisAngle(chan->quat, pchan->rotAxis, &pchan->rotAngle); } else { /* euler/axis-angle to quat */ if (chan->rotmode > 0) EulOToQuat(chan->eul, chan->rotmode, pchan->quat); else - AxisAngleToQuat(pchan->quat, &chan->quat[1], chan->quat[0]); + AxisAngleToQuat(pchan->quat, chan->rotAxis, pchan->rotAngle); } /* paste flipped pose? */ @@ -1055,10 +1055,10 @@ static int pose_paste_exec (bContext *C, wmOperator *op) else if (pchan->rotmode == ROT_MODE_AXISANGLE) { float eul[3]; - AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], eul, EULER_ORDER_DEFAULT); + AxisAngleToEulO(pchan->rotAxis, pchan->rotAngle, eul, EULER_ORDER_DEFAULT); eul[1]*= -1; eul[2]*= -1; - EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, &pchan->quat[1], &pchan->quat[0]); + EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, &pchan->rotAngle); // experimental method (uncomment to test): #if 0 diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index cd0d97eed44..898d541d09d 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -117,17 +117,41 @@ static int object_rotation_clear_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) { if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) { - /* check if convert to eulers for locking... */ if (ob->protectflag & OB_LOCK_ROT4D) { /* perform clamping on a component by component basis */ - if ((ob->protectflag & OB_LOCK_ROTW) == 0) - ob->quat[0]= (ob->rotmode == ROT_MODE_AXISANGLE) ? 0.0f : 1.0f; - if ((ob->protectflag & OB_LOCK_ROTX) == 0) - ob->quat[1]= 0.0f; - if ((ob->protectflag & OB_LOCK_ROTY) == 0) - ob->quat[2]= 0.0f; - if ((ob->protectflag & OB_LOCK_ROTZ) == 0) - ob->quat[3]= 0.0f; + if (ob->rotmode == ROT_MODE_AXISANGLE) { + if ((ob->protectflag & OB_LOCK_ROTW) == 0) + ob->rotAngle= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTX) == 0) + ob->rotAxis[0]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTY) == 0) + ob->rotAxis[1]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) + ob->rotAxis[2]= 0.0f; + + /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */ + if (IS_EQ(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQ(ob->rotAxis[1], ob->rotAxis[2])) + ob->rotAxis[1] = 1.0f; + } + else if (ob->rotmode == ROT_MODE_QUAT) { + if ((ob->protectflag & OB_LOCK_ROTW) == 0) + ob->quat[0]= 1.0f; + if ((ob->protectflag & OB_LOCK_ROTX) == 0) + ob->quat[1]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTY) == 0) + ob->quat[2]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) + ob->quat[3]= 0.0f; + } + else { + /* the flag may have been set for the other modes, so just ignore the extra flag... */ + if ((ob->protectflag & OB_LOCK_ROTX) == 0) + ob->rot[0]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTY) == 0) + ob->rot[1]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) + ob->rot[2]= 0.0f; + } } else { /* perform clamping using euler form (3-components) */ @@ -138,7 +162,7 @@ static int object_rotation_clear_exec(bContext *C, wmOperator *op) QuatToEul(ob->quat, oldeul); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { - AxisAngleToEulO(&ob->quat[1], ob->quat[0], oldeul, EULER_ORDER_DEFAULT); + AxisAngleToEulO(ob->rotAxis, ob->rotAngle, oldeul, EULER_ORDER_DEFAULT); } else { VECCOPY(oldeul, ob->rot); @@ -161,7 +185,7 @@ static int object_rotation_clear_exec(bContext *C, wmOperator *op) } } else if (ob->rotmode == ROT_MODE_AXISANGLE) { - AxisAngleToEulO(&ob->quat[1], ob->quat[0], oldeul, EULER_ORDER_DEFAULT); + EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, ob->rotAxis, &ob->rotAngle); } else { VECCOPY(ob->rot, eul); @@ -175,8 +199,8 @@ static int object_rotation_clear_exec(bContext *C, wmOperator *op) } else if (ob->rotmode == ROT_MODE_AXISANGLE) { /* by default, make rotation of 0 radians around y-axis (roll) */ - ob->quat[0]=ob->quat[1]=ob->quat[3]= 0.0f; - ob->quat[2]= 1.0f; + ob->rotAxis[0]=ob->rotAxis[2]=ob->rotAngle= 0.0f; + ob->rotAxis[1]= 1.0f; } else { ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0f; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index ec72d72013b..c2f5d736875 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -689,6 +689,7 @@ static void do_view3d_region_buttons(bContext *C, void *arg, int event) case B_OBJECTPANELROT: if(ob) { + // TODO: need to support roation modes ob->rot[0]= M_PI*tfp->ob_eul[0]/180.0; ob->rot[1]= M_PI*tfp->ob_eul[1]/180.0; ob->rot[2]= M_PI*tfp->ob_eul[2]/180.0; @@ -870,13 +871,12 @@ static void do_view3d_region_buttons(bContext *C, void *arg, int event) float quat[4]; /* convert to axis-angle, passing through quats */ EulToQuat(eul, quat); - QuatToAxisAngle(quat, &pchan->quat[1], &pchan->quat[0]); + QuatToAxisAngle(quat, pchan->rotAxis, &pchan->rotAngle); } else if (pchan->rotmode == ROT_MODE_QUAT) EulToQuat(eul, pchan->quat); else VecCopyf(pchan->eul, eul); - } /* no break, pass on */ case B_ARMATUREPANEL2: diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f6d30a7bec9..1b11d43c200 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -509,7 +509,7 @@ static short apply_targetless_ik(Object *ob) if (parchan->rotmode > 0) Mat3ToEulO(rmat3, parchan->eul, parchan->rotmode); else if (parchan->rotmode == ROT_MODE_AXISANGLE) - Mat3ToAxisAngle(rmat3, &parchan->quat[1], &parchan->quat[0]); + Mat3ToAxisAngle(rmat3, parchan->rotAxis, &pchan->rotAngle); else Mat3ToQuat(rmat3, parchan->quat); @@ -519,7 +519,7 @@ static short apply_targetless_ik(Object *ob) if (parchan->rotmode > 0) EulOToMat3(parchan->eul, parchan->rotmode, qrmat); else if (parchan->rotmode == ROT_MODE_AXISANGLE) - AxisAngleToMat3(&parchan->quat[1], parchan->quat[0], qrmat); + AxisAngleToMat3(parchan->rotAxis, parchan->rotAngle, qrmat); else QuatToMat3(parchan->quat, qrmat); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 3201a1df6a5..e2eb13f0bdf 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -128,12 +128,15 @@ typedef struct bPoseChannel { void *dual_quat; void *b_bone_dual_quats; - float loc[3]; /* transforms - written in by actions or transform */ + /* transforms - written in by actions or transform */ + float loc[3]; float size[3]; - float eul[3]; /* rotations - written in by actions or transform (but only euler/quat in use at any one time!) */ - float quat[4]; - short rotmode; /* for now either quat (0), or xyz-euler (1) */ + /* rotations - written in by actions or transform (but only one representation gets used at any time) */ + float eul[3]; /* euler rotation */ + float quat[4]; /* quaternion rotation */ + float rotAxis[3], rotAngle; /* axis-angle rotation */ + short rotmode; /* eRotationModes - rotation representation to use */ short pad; float chan_mat[4][4]; /* matrix result of loc/quat/size , and where we put deform in, see next line */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index ade22e4ebd4..0940a88267c 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -133,8 +133,10 @@ typedef struct Object { /* rot en drot have to be together! (transform('r' en 's')) */ float loc[3], dloc[3], orig[3]; float size[3], dsize[3]; - float rot[3], drot[3]; - float quat[4], dquat[4]; + float rot[3], drot[3]; /* euler rotation */ + float quat[4], dquat[4]; /* quaternion rotation */ + float rotAxis[3], drotAxis[3]; /* axis angle rotation - axis part */ + float rotAngle, drotAngle; /* axis angle rotation - angle part */ float obmat[4][4]; float parentinv[4][4]; /* inverse result of parent, so that object doesn't 'stick' to parent */ float constinv[4][4]; /* inverse result of constraints. doesn't include effect of parent or object local transform */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 4fb2db42b8b..3184ebc6db2 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -484,12 +484,34 @@ static void rna_Object_rotation_euler_set(PointerRNA *ptr, const float *value) VECCOPY(ob->rot, value); } +/* rotation - axis-angle */ +static void rna_Object_rotation_axis_angle_get(PointerRNA *ptr, float *value) +{ + Object *ob= ptr->data; + + /* for now, assume that rotation mode is axis-angle */ + value[0]= ob->rotAngle; + VecCopyf(&value[1], ob->rotAxis); +} + +/* rotation - axis-angle */ +static void rna_Object_rotation_axis_angle_set(PointerRNA *ptr, const float *value) +{ + Object *ob= ptr->data; + + /* for now, assume that rotation mode is axis-angle */ + ob->rotAngle= value[0]; + VecCopyf(ob->rotAxis, (float *)&value[1]); + + // TODO: validate axis? +} + static void rna_Object_rotation_mode_set(PointerRNA *ptr, int value) { Object *ob= ptr->data; /* use API Method for conversions... */ - BKE_rotMode_change_values(ob->quat, ob->rot, ob->rotmode, (short)value); + BKE_rotMode_change_values(ob->quat, ob->rot, ob->rotAxis, &ob->rotAngle, ob->rotmode, (short)value); /* finally, set the new rotation type */ ob->rotmode= value; @@ -1242,8 +1264,8 @@ static void rna_def_object(BlenderRNA *brna) * having a single one is better for Keyframing and other property-management situations... */ prop= RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); - RNA_def_property_float_sdna(prop, NULL, "quat"); - // TODO: we may need some validation funcs + RNA_def_property_array(prop, 4); // TODO: maybe we'll need to define the 'default value' getter too... + RNA_def_property_float_funcs(prop, "rna_Object_rotation_axis_angle_get", "rna_Object_rotation_axis_angle_set", NULL); RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); @@ -1283,7 +1305,7 @@ static void rna_def_object(BlenderRNA *brna) #if 0 // XXX not supported well yet... prop= RNA_def_property(srna, "delta_rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); - RNA_def_property_float_sdna(prop, NULL, "dquat"); + RNA_def_property_float_sdna(prop, NULL, "dquat"); // FIXME: this is not a single field any more! (drotAxis and drotAngle) RNA_def_property_ui_text(prop, "Delta Rotation (Axis Angle)", "Extra added rotation to the rotation of the object (when using Axis-Angle rotations)."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); #endif diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index ecb2dba0197..27069b361fd 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -162,7 +162,7 @@ static void rna_PoseChannel_rotation_euler_get(PointerRNA *ptr, float *value) bPoseChannel *pchan= ptr->data; if(pchan->rotmode == ROT_MODE_AXISANGLE) /* default XYZ eulers */ - AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], value, EULER_ORDER_DEFAULT); + AxisAngleToEulO(pchan->rotAxis, pchan->rotAngle, value, EULER_ORDER_DEFAULT); else if(pchan->rotmode == ROT_MODE_QUAT) /* default XYZ eulers */ QuatToEul(pchan->quat, value); else @@ -175,19 +175,41 @@ static void rna_PoseChannel_rotation_euler_set(PointerRNA *ptr, const float *val bPoseChannel *pchan= ptr->data; if(pchan->rotmode == ROT_MODE_AXISANGLE) /* default XYZ eulers */ - EulOToAxisAngle((float *)value, EULER_ORDER_DEFAULT, &pchan->quat[1], &pchan->quat[0]); + EulOToAxisAngle((float *)value, EULER_ORDER_DEFAULT, pchan->rotAxis, &pchan->rotAngle); else if(pchan->rotmode == ROT_MODE_QUAT) /* default XYZ eulers */ EulToQuat((float*)value, pchan->quat); else VECCOPY(pchan->eul, value); } +/* rotation - axis-angle */ +static void rna_PoseChannel_rotation_axis_angle_get(PointerRNA *ptr, float *value) +{ + bPoseChannel *pchan= ptr->data; + + /* for now, assume that rotation mode is axis-angle */ + value[0]= pchan->rotAngle; + VecCopyf(&value[1], pchan->rotAxis); +} + +/* rotation - axis-angle */ +static void rna_PoseChannel_rotation_axis_angle_set(PointerRNA *ptr, const float *value) +{ + bPoseChannel *pchan= ptr->data; + + /* for now, assume that rotation mode is axis-angle */ + pchan->rotAngle= value[0]; + VecCopyf(pchan->rotAxis, (float *)&value[1]); + + // TODO: validate axis? +} + static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) { bPoseChannel *pchan= ptr->data; /* use API Method for conversions... */ - BKE_rotMode_change_values(pchan->quat, pchan->eul, pchan->rotmode, (short)value); + BKE_rotMode_change_values(pchan->quat, pchan->eul, pchan->rotAxis, &pchan->rotAngle, pchan->rotmode, (short)value); /* finally, set the new rotation type */ pchan->rotmode= value; @@ -578,8 +600,8 @@ static void rna_def_pose_channel(BlenderRNA *brna) * having a single one is better for Keyframing and other property-management situations... */ prop= RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); - RNA_def_property_float_sdna(prop, NULL, "quat"); - // TODO: we may need some validation funcs + RNA_def_property_array(prop, 4); // TODO: maybe we'll need to define the 'default value' getter too... + RNA_def_property_float_funcs(prop, "rna_PoseChannel_rotation_axis_angle_get", "rna_PoseChannel_rotation_axis_angle_set", NULL); RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); |