diff options
-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"); |