diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-09-11 16:05:09 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-09-11 16:05:09 +0400 |
commit | d5009eb1423c3c0359cbc85c7346412c597b8663 (patch) | |
tree | c56d97bdd477682c5dacbf42f500c4e3eec79fef | |
parent | 40576677b1dff5373d5b673b599ea9beb094b1ea (diff) |
2.5 Rotations: As a experiment, enabling Axis-Angle for Bones
The support for this is really quite hacky, and I might disable this later if we cannot get some parts to work nicely.
Some notes:
* This is currently stored in the same variable that quaternions are stored in, since they both have 4 components. However, in RNA, I've added 2 properties specially for this.
* There are some shearing issues using certain axes - i.e. (1,1,0) - that will need to be checked on.
* Transform code is really quite temporary for this. Just a quick demo of what can be done...
-rw-r--r-- | release/ui/buttons_data_bone.py | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 8 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 11 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_pose.c | 74 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 2 |
6 files changed, 92 insertions, 11 deletions
diff --git a/release/ui/buttons_data_bone.py b/release/ui/buttons_data_bone.py index 0d379a4788f..5aac44bbc94 100644 --- a/release/ui/buttons_data_bone.py +++ b/release/ui/buttons_data_bone.py @@ -58,6 +58,10 @@ class BONE_PT_transform(BoneButtonsPanel): col = row.column() if pchan.rotation_mode == 'QUATERNION': col.itemR(pchan, "rotation", text="Rotation") + elif pchan.rotation_mode == 'AXIS_ANGLE': + col.itemL(text="Rotation") + col.itemR(pchan, "rotation_angle", text="Angle") + col.itemR(pchan, "rotation_axis", text="Axis") else: col.itemR(pchan, "euler_rotation", text="Rotation") diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 95c4c2966c6..0c18817f8be 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1986,11 +1986,15 @@ void chan_calc_mat(bPoseChannel *chan) /* get scaling matrix */ SizeToMat3(chan->size, smat); - /* rotations may either be quats or eulers (no rotation modes for now...) */ + /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ if (chan->rotmode > 0) { - /* euler rotations (will cause gimble lock... no rotation order to solve that yet) */ + /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ EulOToMat3(chan->eul, chan->rotmode, rmat); } + else if (chan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ + VecRotToMat3(&chan->quat[1], chan->quat[0], rmat); + } else { /* quats are normalised before use to eliminate scaling issues */ NormalQuat(chan->quat); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f049566d640..ac5d688cd1c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2663,7 +2663,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* rotation */ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself - /* euler or quaternion? */ + /* euler or quaternion/axis-angle? */ if (td->flag & TD_USEQUAT) { Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); @@ -2672,6 +2672,15 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short QuatMul(td->ext->quat, quat, td->ext->iquat); /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + + /* if axis-angle, we now convert the quat representation to axis-angle again + * - this means that the math above is not totally correct, but it works well enough so far... + */ + if (td->rotOrder == PCHAN_ROT_AXISANGLE) { + /* make temp copy (since stored in same place) */ + QuatCopy(quat, td->ext->quat); + QuatToAxisAngle(quat, &td->ext->quat[1], &td->ext->quat[0]); + } } else { float eulmat[3][3]; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 504563b797b..7a37ffdeeca 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -552,8 +552,9 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ob = ob; td->flag = TD_SELECTED; - if (pchan->rotmode == PCHAN_ROT_QUAT) + if ((pchan->rotmode == PCHAN_ROT_QUAT) || (pchan->rotmode == PCHAN_ROT_AXISANGLE)) { + // XXX: for now, axis-angle will be treated like for quats (the only difference is the normalisation) td->flag |= TD_USEQUAT; } if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) @@ -587,6 +588,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ext->quat= pchan->quat; QUATCOPY(td->ext->iquat, pchan->quat); + td->rotOrder= pchan->rotmode; } diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 7d7f37a8f43..0a88b084307 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -110,26 +110,64 @@ IDProperty *rna_PoseChannel_idproperties(PointerRNA *ptr, int create) return pchan->prop; } +/* rotation - euler angles */ static void rna_PoseChannel_euler_rotation_get(PointerRNA *ptr, float *value) { bPoseChannel *pchan= ptr->data; - - if(pchan->rotmode == PCHAN_ROT_QUAT) + + if(pchan->rotmode == PCHAN_ROT_AXISANGLE) { + float m[3][3]; + + /* go through a 3x3 matrix */ + VecRotToMat3(&pchan->quat[1], pchan->quat[0], m); + Mat3ToEul(m, value); + } + else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using axis-angle... */ QuatToEul(pchan->quat, value); else VECCOPY(value, pchan->eul); } +/* rotation - euler angles */ static void rna_PoseChannel_euler_rotation_set(PointerRNA *ptr, const float *value) { bPoseChannel *pchan= ptr->data; - - if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using quats... */ + + if(pchan->rotmode == PCHAN_ROT_AXISANGLE) { /* default XYZ eulers when using axis-angle... */ + float q[4]; + + /* convert to temp quat, then to axis angle (since stored in same var) */ + EulToQuat((float *)value, q); + QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); + } + else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using quats... */ EulToQuat((float*)value, pchan->quat); else VECCOPY(pchan->eul, value); } +/* rotation - axis angle only */ +static void rna_PoseChannel_rotation_axis_get(PointerRNA *ptr, float *value) +{ + bPoseChannel *pchan= ptr->data; + + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis is stord in quat for now */ + VecCopyf(value, &pchan->quat[1]); + } +} + +/* rotation - axis angle only */ +static void rna_PoseChannel_rotation_axis_set(PointerRNA *ptr, const float *value) +{ + bPoseChannel *pchan= ptr->data; + + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis is stored in quat for now */ + VecCopyf(&pchan->quat[1], (float *)value); + } +} + static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) { bPoseChannel *pchan= ptr->data; @@ -185,6 +223,12 @@ static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) QuatCopy(q, pchan->quat); QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); } + + /* when converting to axis-angle, we need a special exception for the case when there is no axis */ + if (IS_EQ(pchan->quat[1], pchan->quat[2]) && IS_EQ(pchan->quat[2], pchan->quat[3])) { + /* for now, rotate around y-axis then (so that it simply becomes the roll) */ + pchan->quat[2]= 1.0f; + } } /* finally, set the new rotation type */ @@ -421,7 +465,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) {PCHAN_ROT_YZX, "YZX", 0, "YZX Euler", "YZX Rotation Order. Prone to Gimbal Lock"}, {PCHAN_ROT_ZXY, "ZXY", 0, "ZXY Euler", "ZXY Rotation Order. Prone to Gimbal Lock"}, {PCHAN_ROT_ZYX, "ZYX", 0, "ZYX Euler", "ZYX Rotation Order. Prone to Gimbal Lock"}, - //{PCHAN_ROT_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, + {PCHAN_ROT_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, {0, NULL, 0, NULL, NULL}}; StructRNA *srna; @@ -493,6 +537,18 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Rotation", "Rotation in Quaternions."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); + prop= RNA_def_property(srna, "rotation_angle", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "quat[0]"); + RNA_def_property_ui_text(prop, "Rotation Angle", "Angle of Rotation for Axis-Angle rotation representation."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); + + prop= RNA_def_property(srna, "rotation_axis", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "quat"); + RNA_def_property_float_funcs(prop, "rna_PoseChannel_rotation_axis_get", "rna_PoseChannel_rotation_axis_set", NULL); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Rotation Axis", "Axis for Axis-Angle rotation representation."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); + prop= RNA_def_property(srna, "euler_rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "eul"); RNA_def_property_float_funcs(prop, "rna_PoseChannel_euler_rotation_get", "rna_PoseChannel_euler_rotation_set", NULL); @@ -662,8 +718,14 @@ static void rna_def_pose_channel(BlenderRNA *brna) prop= RNA_def_property(srna, "lock_rotation", PROP_BOOLEAN, PROP_XYZ); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROTX); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Lock Rotation", "Lock editing of rotation in the interface."); + RNA_def_property_ui_text(prop, "Lock Rotation", "Lock editing of rotation (with three components) in the interface."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + + //prop= RNA_def_property(srna, "lock_rotation_4d", PROP_BOOLEAN, PROP_XYZ); + //RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROTW); + //RNA_def_property_array(prop, 4); + //RNA_def_property_ui_text(prop, "Lock Rotation (4D)", "Lock editing of rotations (with four components) in the interface."); + //RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); prop= RNA_def_property(srna, "lock_scale", PROP_BOOLEAN, PROP_XYZ); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_SCALEX); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index a6e38a61e0f..9694a8fa1c6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -281,7 +281,7 @@ void WM_read_file(bContext *C, char *name, ReportList *reports) /* called on startup, (context entirely filled with NULLs) */ -/* or called for 'Erase All' */ +/* or called for 'New File' */ /* op can be NULL */ int WM_read_homefile(bContext *C, wmOperator *op) { |