Add a new B-Bone Custom Handle type that uses the handle bone direction.
Both original handle types are based on location, and Absolute uses it in a weird way: the Start handle uses the head, while End uses the tail. This makes controlling the shape of the B-Bone via control bone rotation really non-intuitive, especially if trying to add a single control for the tangent in the middle of a B-Bone chain. To remedy this, add a new custom handle type that uses the orientation of the control bone, while completely ignoring location. It is even possible to control both ends of one B-Bone with the same handle bone, resulting in an S shape. Reviewers: brecht Differential Revision: https://developer.blender.org/D3769
This commit is contained in:
parent
6723e173a5
commit
25bd9feadb
|
@ -468,6 +468,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
|||
Bone *bone = pchan->bone;
|
||||
BBoneSplineParameters param;
|
||||
float imat[4][4], posemat[4][4];
|
||||
float delta[3];
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
|
||||
|
@ -518,11 +519,21 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
|||
done = true;
|
||||
}
|
||||
else {
|
||||
float delta[3];
|
||||
sub_v3_v3v3(delta, prev->pose_head, prev->bone->arm_head);
|
||||
sub_v3_v3v3(h1, pchan->pose_head, delta);
|
||||
}
|
||||
}
|
||||
else if (bone->bbone_prev_type == BBONE_HANDLE_TANGENT) {
|
||||
/* Use bone direction by offsetting so that its tail meets current bone's head */
|
||||
if (rest) {
|
||||
sub_v3_v3v3(delta, prev->bone->arm_tail, prev->bone->arm_head);
|
||||
sub_v3_v3v3(h1, bone->arm_head, delta);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(delta, prev->pose_tail, prev->pose_head);
|
||||
sub_v3_v3v3(h1, pchan->pose_head, delta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Apply special handling for smoothly joining B-Bone chains */
|
||||
param.prev_bbone = (prev->bone->segments > 1);
|
||||
|
@ -556,11 +567,21 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
|||
done = true;
|
||||
}
|
||||
else {
|
||||
float delta[3];
|
||||
sub_v3_v3v3(delta, next->pose_head, next->bone->arm_head);
|
||||
add_v3_v3v3(h2, pchan->pose_tail, delta);
|
||||
}
|
||||
}
|
||||
else if (bone->bbone_next_type == BBONE_HANDLE_TANGENT) {
|
||||
/* Use bone direction by offsetting so that its head meets current bone's tail */
|
||||
if (rest) {
|
||||
sub_v3_v3v3(delta, next->bone->arm_tail, next->bone->arm_head);
|
||||
add_v3_v3v3(h2, bone->arm_tail, delta);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(delta, next->pose_tail, next->pose_head);
|
||||
add_v3_v3v3(h2, pchan->pose_tail, delta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Apply special handling for smoothly joining B-Bone chains */
|
||||
param.next_bbone = (next->bone->segments > 1);
|
||||
|
|
|
@ -940,6 +940,7 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S
|
|||
BBoneSplineParameters param;
|
||||
EditBone *prev, *next;
|
||||
float imat[4][4], bonemat[4][4];
|
||||
float tmp[3];
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
|
||||
|
@ -979,6 +980,11 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S
|
|||
if (ebone->bbone_prev_type == BBONE_HANDLE_RELATIVE) {
|
||||
zero_v3(param.prev_h);
|
||||
}
|
||||
else if (ebone->bbone_prev_type == BBONE_HANDLE_TANGENT) {
|
||||
sub_v3_v3v3(tmp, prev->tail, prev->head);
|
||||
sub_v3_v3v3(tmp, ebone->head, tmp);
|
||||
mul_v3_m4v3(param.prev_h, imat, tmp);
|
||||
}
|
||||
else {
|
||||
param.prev_bbone = (prev->segments > 1);
|
||||
|
||||
|
@ -997,6 +1003,11 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S
|
|||
if (ebone->bbone_next_type == BBONE_HANDLE_RELATIVE) {
|
||||
copy_v3_fl3(param.next_h, 0.0f, param.length, 0.0);
|
||||
}
|
||||
else if (ebone->bbone_next_type == BBONE_HANDLE_TANGENT) {
|
||||
sub_v3_v3v3(tmp, next->tail, next->head);
|
||||
add_v3_v3v3(tmp, ebone->tail, tmp);
|
||||
mul_v3_m4v3(param.next_h, imat, tmp);
|
||||
}
|
||||
else {
|
||||
param.next_bbone = (next->segments > 1);
|
||||
|
||||
|
|
|
@ -221,6 +221,7 @@ typedef enum eBone_BBoneHandleType {
|
|||
BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */
|
||||
BBONE_HANDLE_ABSOLUTE, /* Custom handle in absolute position mode. */
|
||||
BBONE_HANDLE_RELATIVE, /* Custom handle in relative position mode. */
|
||||
BBONE_HANDLE_TANGENT, /* Custom handle in tangent mode (use direction, not location). */
|
||||
} eBone_BBoneHandleType;
|
||||
|
||||
#define MAXBONENAME 64
|
||||
|
|
|
@ -655,6 +655,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
|
|||
{BBONE_HANDLE_AUTO, "AUTO", 0, "Automatic", "Use connected parent and children to compute the handle"},
|
||||
{BBONE_HANDLE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Use the position of the specified bone to compute the handle"},
|
||||
{BBONE_HANDLE_RELATIVE, "RELATIVE", 0, "Relative", "Use the offset of the specified bone from rest pose to compute the handle"},
|
||||
{BBONE_HANDLE_TANGENT, "TANGENT", 0, "Tangent", "Use the orientation of the specified bone to compute the handle, ignoring the location"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue