diff options
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 25 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 289 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_armature.c | 148 | ||||
-rw-r--r-- | source/blender/editors/include/ED_armature.h | 2 |
4 files changed, 297 insertions, 167 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 44120d182b7..abcf1388c55 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -140,11 +140,34 @@ typedef struct Mat4 { float mat[4][4]; } Mat4; +typedef struct BBoneSplineParameters { + int segments; + float length; + + /* Non-uniform scale correction. */ + bool do_scale; + float scale[3]; + + /* Handle control bone data. */ + bool use_prev, prev_bbone; + bool use_next, next_bbone; + + float prev_h[3], next_h[3]; + float prev_mat[4][4], next_mat[4][4]; + + /* Control values. */ + float ease1, ease2; + float roll1, roll2; + float scaleIn, scaleOut; + float curveInX, curveInY, curveOutX, curveOutY; +} BBoneSplineParameters; + void BKE_pchan_get_bbone_handles(struct bPoseChannel *pchan, struct bPoseChannel **r_prev, struct bPoseChannel **r_next); -void equalize_bbone_bezier(float *data, int desired); void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]); +int BKE_compute_b_bone_spline(struct BBoneSplineParameters *param, Mat4 result_array[MAX_BBONE_SUBDIV]); + /* like EBONE_VISIBLE */ #define PBONE_VISIBLE(arm, bone) ( \ CHECK_TYPE_INLINE(arm, bArmature *), \ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 61472068399..5ffb38414a8 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -393,7 +393,7 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a /* ************* B-Bone support ******************* */ /* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount with equal distances */ -void equalize_bbone_bezier(float *data, int desired) +static void equalize_bbone_bezier(float *data, int desired) { float *fp, totdist, ddist, dist, fac1, fac2; float pdist[MAX_BBONE_SUBDIV + 1]; @@ -460,59 +460,63 @@ void BKE_pchan_get_bbone_handles(bPoseChannel *pchan, bPoseChannel **r_prev, bPo } } -/* returns pointer to static array, filled with desired amount of bone->segments elements */ -/* this calculation is done within unit bone space */ +/* Fills the array with the desired amount of bone->segments elements. + * This calculation is done within unit bone space. */ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]) { bPoseChannel *next, *prev; Bone *bone = pchan->bone; - float h1[3], h2[3], scale[3], length, roll1 = 0.0f, roll2; - float mat3[3][3], imat[4][4], posemat[4][4], scalemat[4][4], iscalemat[4][4]; - float data[MAX_BBONE_SUBDIV + 1][4], *fp; - int a; - bool do_scale = false; + BBoneSplineParameters param; + float imat[4][4], posemat[4][4]; - length = bone->length; + memset(¶m, 0, sizeof(param)); + + param.segments = bone->segments; + param.length = bone->length; if (!rest) { - /* check if we need to take non-uniform bone scaling into account */ + float scale[3]; + + /* Check if we need to take non-uniform bone scaling into account. */ mat4_to_size(scale, pchan->pose_mat); if (fabsf(scale[0] - scale[1]) > 1e-6f || fabsf(scale[1] - scale[2]) > 1e-6f) { - size_to_mat4(scalemat, scale); - invert_m4_m4(iscalemat, scalemat); - - length *= scale[1]; - do_scale = 1; + param.do_scale = true; + copy_v3_v3(param.scale, scale); } } BKE_pchan_get_bbone_handles(pchan, &prev, &next); - /* find the handle points, since this is inside bone space, the + /* Find the handle points, since this is inside bone space, the * first point = (0, 0, 0) * last point = (0, length, 0) */ if (rest) { invert_m4_m4(imat, pchan->bone->arm_mat); } - else if (do_scale) { + else if (param.do_scale) { copy_m4_m4(posemat, pchan->pose_mat); normalize_m4(posemat); invert_m4_m4(imat, posemat); } - else + else { invert_m4_m4(imat, pchan->pose_mat); + } if (prev) { - float difmat[4][4], result[3][3], imat3[3][3]; + float h1[3]; + bool done = false; - /* transform previous point inside this bone space */ - if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE) - { - /* Use delta movement (from restpose), and apply this relative to the current bone's head */ + param.use_prev = true; + param.prev_bbone = (prev->bone->segments > 1); + + /* Transform previous point inside this bone space. */ + if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE) { + /* Use delta movement (from restpose), and apply this relative to the current bone's head. */ if (rest) { - /* in restpose, arm_head == pose_head */ - h1[0] = h1[1] = h1[2] = 0.0f; + /* In restpose, arm_head == pose_head */ + zero_v3(param.prev_h); + done = true; } else { float delta[3]; @@ -521,16 +525,125 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB } } else { - /* Use bone head as absolute position */ - if (rest) - copy_v3_v3(h1, prev->bone->arm_head); - else - copy_v3_v3(h1, prev->pose_head); + /* Use bone head as absolute position. */ + copy_v3_v3(h1, rest ? prev->bone->arm_head : prev->pose_head); + } + + if (!done) { + mul_v3_m4v3(param.prev_h, imat, h1); + } + + if (!param.prev_bbone) { + /* Find the previous roll to interpolate. */ + mul_m4_m4m4(param.prev_mat, imat, rest ? prev->bone->arm_mat : prev->pose_mat); + } + } + + if (next) { + float h2[3]; + bool done = false; + + param.use_next = true; + param.next_bbone = (next->bone->segments > 1); + + /* Transform next point inside this bone space. */ + if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE) { + /* Use delta movement (from restpose), and apply this relative to the current bone's tail. */ + if (rest) { + /* In restpose, arm_tail == pose_tail */ + copy_v3_fl3(param.next_h, 0.0f, param.length, 0.0); + done = true; + } + else { + float delta[3]; + sub_v3_v3v3(delta, next->pose_tail, next->bone->arm_tail); + add_v3_v3v3(h2, pchan->pose_tail, delta); + } + } + else { + /* Use bone tail as absolute position. */ + copy_v3_v3(h2, rest ? next->bone->arm_tail : next->pose_tail); + } + + if (!done) { + mul_v3_m4v3(param.next_h, imat, h2); } - mul_m4_v3(imat, h1); - if (prev->bone->segments > 1) { - /* if previous bone is B-bone too, use average handle direction */ + /* Find the next roll to interpolate as well. */ + mul_m4_m4m4(param.next_mat, imat, rest ? next->bone->arm_mat : next->pose_mat); + } + + /* Add effects from bbone properties over the top + * - These properties allow users to hand-animate the + * bone curve/shape, without having to resort to using + * extra bones + * - The "bone" level offsets are for defining the restpose + * shape of the bone (e.g. for curved eyebrows for example). + * -> In the viewport, it's needed to define what the rest pose + * looks like + * -> For "rest == 0", we also still need to have it present + * so that we can "cancel out" this restpose when it comes + * time to deform some geometry, it won't cause double transforms. + * - The "pchan" level offsets are the ones that animators actually + * end up animating + */ + { + param.ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f); + param.ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f); + + param.roll1 = bone->roll1 + (!rest ? pchan->roll1 : 0.0f); + param.roll2 = bone->roll2 + (!rest ? pchan->roll2 : 0.0f); + + if (bone->flag & BONE_ADD_PARENT_END_ROLL) { + if (prev) { + if (prev->bone) { + param.roll1 += prev->bone->roll2; + } + + if (!rest) { + param.roll1 += prev->roll2; + } + } + } + + param.scaleIn = bone->scaleIn * (!rest ? pchan->scaleIn : 1.0f); + param.scaleOut = bone->scaleOut * (!rest ? pchan->scaleOut : 1.0f); + + /* Extra curve x / y */ + param.curveInX = bone->curveInX + (!rest ? pchan->curveInX : 0.0f); + param.curveInY = bone->curveInY + (!rest ? pchan->curveInY : 0.0f); + + param.curveOutX = bone->curveOutX + (!rest ? pchan->curveOutX : 0.0f); + param.curveOutY = bone->curveOutY + (!rest ? pchan->curveOutY : 0.0f); + } + + bone->segments = BKE_compute_b_bone_spline(¶m, result_array); +} + +/* Fills the array with the desired amount of bone->segments elements. + * This calculation is done within unit bone space. */ +int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 result_array[MAX_BBONE_SUBDIV]) +{ + float scalemat[4][4], iscalemat[4][4]; + float result[3][3], mat3[3][3], imat3[3][3]; + float h1[3], roll1, h2[3], roll2; + float data[MAX_BBONE_SUBDIV + 1][4], *fp; + int a; + + float length = param->length; + + if (param->do_scale) { + size_to_mat4(scalemat, param->scale); + invert_m4_m4(iscalemat, scalemat); + + length *= param->scale[1]; + } + + if (param->use_prev) { + copy_v3_v3(h1, param->prev_h); + + if (param->prev_bbone) { + /* If previous bone is B-bone too, use average handle direction. */ h1[1] -= length; roll1 = 0.0f; } @@ -538,13 +651,9 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB normalize_v3(h1); negate_v3(h1); - if (prev->bone->segments == 1) { - /* find the previous roll to interpolate */ - if (rest) - mul_m4_m4m4(difmat, imat, prev->bone->arm_mat); - else - mul_m4_m4m4(difmat, imat, prev->pose_mat); - copy_m3_m4(result, difmat); /* the desired rotation at beginning of next bone */ + if (!param->prev_bbone) { + /* Find the previous roll to interpolate. */ + copy_m3_m4(result, param->prev_mat); /* the desired rotation at beginning of next bone */ vec_roll_to_mat3(h1, 0.0f, mat3); /* the result of vec_roll without roll */ @@ -558,47 +667,22 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB h1[0] = 0.0f; h1[1] = 1.0; h1[2] = 0.0f; roll1 = 0.0f; } - if (next) { - float difmat[4][4], result[3][3], imat3[3][3]; - /* transform next point inside this bone space */ - if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE) - { - /* Use delta movement (from restpose), and apply this relative to the current bone's tail */ - if (rest) { - /* in restpose, arm_tail == pose_tail */ - h2[0] = h2[1] = h2[2] = 0.0f; - } - else { - float delta[3]; - sub_v3_v3v3(delta, next->pose_tail, next->bone->arm_tail); - add_v3_v3v3(h2, pchan->pose_tail, delta); - } - } - else { - /* Use bone tail as absolute position */ - if (rest) - copy_v3_v3(h2, next->bone->arm_tail); - else - copy_v3_v3(h2, next->pose_tail); - } - mul_m4_v3(imat, h2); + if (param->use_next) { + copy_v3_v3(h2, param->next_h); - /* if next bone is B-bone too, use average handle direction */ - if (next->bone->segments > 1) { + /* If next bone is B-bone too, use average handle direction. */ + if (param->next_bbone) { /* pass */ } else { h2[1] -= length; } + normalize_v3(h2); - /* find the next roll to interpolate as well */ - if (rest) - mul_m4_m4m4(difmat, imat, next->bone->arm_mat); - else - mul_m4_m4m4(difmat, imat, next->pose_mat); - copy_m3_m4(result, difmat); /* the desired rotation at beginning of next bone */ + /* Find the next roll to interpolate as well. */ + copy_m3_m4(result, param->next_mat); /* the desired rotation at beginning of next bone */ vec_roll_to_mat3(h2, 0.0f, mat3); /* the result of vec_roll without roll */ @@ -606,7 +690,6 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB mul_m3_m3m3(mat3, imat3, result); /* the matrix transforming vec_roll to desired roll */ roll2 = atan2f(mat3[2][0], mat3[2][2]); - } else { h2[0] = 0.0f; h2[1] = 1.0f; h2[2] = 0.0f; @@ -616,10 +699,8 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB { const float circle_factor = length * (cubic_tangent_factor_circle_v3(h1, h2) / 0.75f); - const float combined_ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f); - const float combined_ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f); - const float hlength1 = combined_ease1 * circle_factor; - const float hlength2 = combined_ease2 * circle_factor; + const float hlength1 = param->ease1 * circle_factor; + const float hlength2 = param->ease2 * circle_factor; /* and only now negate h2 */ mul_v3_fl(h1, hlength1); @@ -641,67 +722,56 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB * end up animating */ { - /* add extra rolls */ - roll1 += bone->roll1 + (!rest ? pchan->roll1 : 0.0f); - roll2 += bone->roll2 + (!rest ? pchan->roll2 : 0.0f); - - if (bone->flag & BONE_ADD_PARENT_END_ROLL) { - if (prev) { - if (prev->bone) - roll1 += prev->bone->roll2; - - if (!rest) - roll1 += prev->roll2; - } - } + /* Add extra rolls. */ + roll1 += param->roll1; + roll2 += param->roll2; - /* extra curve x / y */ + /* Extra curve x / y */ /* NOTE: Scale correction factors here are to compensate for some random floating-point glitches * when scaling up the bone or it's parent by a factor of approximately 8.15/6, which results * in the bone length getting scaled up too (from 1 to 8), causing the curve to flatten out. */ - const float xscale_correction = (do_scale) ? scale[0] : 1.0f; - const float yscale_correction = (do_scale) ? scale[2] : 1.0f; + const float xscale_correction = (param->do_scale) ? param->scale[0] : 1.0f; + const float yscale_correction = (param->do_scale) ? param->scale[2] : 1.0f; - h1[0] += (bone->curveInX + (!rest ? pchan->curveInX : 0.0f)) * xscale_correction; - h1[2] += (bone->curveInY + (!rest ? pchan->curveInY : 0.0f)) * yscale_correction; + h1[0] += param->curveInX * xscale_correction; + h1[2] += param->curveInY * yscale_correction; - h2[0] += (bone->curveOutX + (!rest ? pchan->curveOutX : 0.0f)) * xscale_correction; - h2[2] += (bone->curveOutY + (!rest ? pchan->curveOutY : 0.0f)) * yscale_correction; + h2[0] += param->curveOutX * xscale_correction; + h2[2] += param->curveOutY * yscale_correction; } - /* make curve */ - if (bone->segments > MAX_BBONE_SUBDIV) - bone->segments = MAX_BBONE_SUBDIV; + /* Make curve. */ + CLAMP_MAX(param->segments, MAX_BBONE_SUBDIV); BKE_curve_forward_diff_bezier(0.0f, h1[0], h2[0], 0.0f, data[0], MAX_BBONE_SUBDIV, 4 * sizeof(float)); BKE_curve_forward_diff_bezier(0.0f, h1[1], length + h2[1], length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float)); BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float)); BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float)); - equalize_bbone_bezier(data[0], bone->segments); /* note: does stride 4! */ + equalize_bbone_bezier(data[0], param->segments); /* note: does stride 4! */ - /* make transformation matrices for the segments for drawing */ - for (a = 0, fp = data[0]; a < bone->segments; a++, fp += 4) { + /* Make transformation matrices for the segments for drawing. */ + for (a = 0, fp = data[0]; a < param->segments; a++, fp += 4) { sub_v3_v3v3(h1, fp + 4, fp); vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */ copy_m4_m3(result_array[a].mat, mat3); copy_v3_v3(result_array[a].mat[3], fp); - if (do_scale) { - /* correct for scaling when this matrix is used in scaled space */ + if (param->do_scale) { + /* Correct for scaling when this matrix is used in scaled space. */ mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat); } /* BBone scale... */ { - const int num_segments = bone->segments; + const int num_segments = param->segments; - const float scaleIn = bone->scaleIn * (!rest ? pchan->scaleIn : 1.0f); + const float scaleIn = param->scaleIn; const float scaleFactorIn = 1.0f + (scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments); - const float scaleOut = bone->scaleOut * (!rest ? pchan->scaleOut : 1.0f); + const float scaleOut = param->scaleOut; const float scaleFactorOut = 1.0f + (scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments); const float scalefac = scaleFactorIn * scaleFactorOut; @@ -717,8 +787,9 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB /*mul_m4_series(result_array[a].mat, ibscalemat, result_array[a].mat, bscalemat);*/ mul_m4_series(result_array[a].mat, result_array[a].mat, bscalemat); } - } + + return param->segments; } /* ************ Armature Deform ******************* */ diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 777775cf8ca..e0ce5751956 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -918,80 +918,113 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel * translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); } -/* XXX Direct copy from drawarmature.c... This is ugly! */ -/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings - * - * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight" - * position here anyway), and that we can simply apply the bbone settings to get the desired effect... - */ -static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4]) +/* compute connected child pointer for B-Bone drawing */ +static void edbo_compute_bbone_child(bArmature *arm) { - float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f; - float mat3[3][3]; - float data[MAX_BBONE_SUBDIV + 1][4], *fp; - int a; - - length = ebone->length; + EditBone *eBone; - hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */ - hlength2 = ebone->ease2 * length * 0.390464f; + for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { + eBone->bbone_child = NULL; + } - /* find the handle points, since this is inside bone space, the - * first point = (0, 0, 0) - * last point = (0, length, 0) - * - * we also just apply all the "extra effects", since they're the whole reason we're doing this... - */ - h1[0] = ebone->curveInX; - h1[1] = hlength1; - h1[2] = ebone->curveInY; - roll1 = ebone->roll1; + for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { + if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { + eBone->parent->bbone_child = eBone; + } + } +} - h2[0] = ebone->curveOutX; - h2[1] = -hlength2; - h2[2] = ebone->curveOutY; - roll2 = ebone->roll2; +/* A version of b_bone_spline_setup() for previewing editmode curve settings. */ +static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4]) +{ + BBoneSplineParameters param; + EditBone *prev, *next; + float imat[4][4], bonemat[4][4]; - /* make curve */ - if (ebone->segments > MAX_BBONE_SUBDIV) - ebone->segments = MAX_BBONE_SUBDIV; + memset(¶m, 0, sizeof(param)); - BKE_curve_forward_diff_bezier(0.0f, h1[0], h2[0], 0.0f, data[0], MAX_BBONE_SUBDIV, 4 * sizeof(float)); - BKE_curve_forward_diff_bezier(0.0f, h1[1], length + h2[1], length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float)); - BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float)); - BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float)); + param.segments = ebone->segments; + param.length = ebone->length; - equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */ + /* Get "next" and "prev" bones - these are used for handle calculations. */ + if (ebone->bbone_prev_type == BBONE_HANDLE_AUTO) { + /* Use connected parent. */ + if (ebone->flag & BONE_CONNECTED) { + prev = ebone->parent; + } + else { + prev = NULL; + } + } + else { + prev = ebone->bbone_prev; + } - /* make transformation matrices for the segments for drawing */ - for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) { - sub_v3_v3v3(h1, fp + 4, fp); - vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */ + if (ebone->bbone_next_type == BBONE_HANDLE_AUTO) { + /* Use connected child. */ + next = ebone->bbone_child; + } + else { + next = ebone->bbone_next; + } - copy_m4_m3(result_array[a], mat3); - copy_v3_v3(result_array[a][3], fp); + /* compute handles from connected bones */ + if (prev || next) { + ED_armature_ebone_to_mat4(ebone, imat); + invert_m4(imat); - /* "extra" scale facs... */ - { - const int num_segments = ebone->segments; + if (prev) { + param.use_prev = true; + param.prev_bbone = (prev->segments > 1); - const float scaleFactorIn = 1.0f + (ebone->scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments); - const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments); + if (ebone->bbone_prev_type == BBONE_HANDLE_RELATIVE) { + zero_v3(param.prev_h); + } + else { + mul_v3_m4v3(param.prev_h, imat, prev->head); + } - const float scalefac = scaleFactorIn * scaleFactorOut; - float bscalemat[4][4], bscale[3]; + if (!param.prev_bbone) { + ED_armature_ebone_to_mat4(prev, bonemat); + mul_m4_m4m4(param.prev_mat, imat, bonemat); + } + } - bscale[0] = scalefac; - bscale[1] = 1.0f; - bscale[2] = scalefac; + if (next) { + param.use_next = true; + param.next_bbone = (next->segments > 1); - size_to_mat4(bscalemat, bscale); + if (ebone->bbone_next_type == BBONE_HANDLE_RELATIVE) { + copy_v3_fl3(param.next_h, 0.0f, param.length, 0.0); + } + else { + mul_v3_m4v3(param.next_h, imat, next->tail); + } - /* Note: don't multiply by inverse scale mat here, - * as it causes problems with scaling shearing and breaking segment chains */ - mul_m4_series(result_array[a], result_array[a], bscalemat); + ED_armature_ebone_to_mat4(next, bonemat); + mul_m4_m4m4(param.next_mat, imat, bonemat); } } + + param.ease1 = ebone->ease1; + param.ease2 = ebone->ease2; + param.roll1 = ebone->roll1; + param.roll2 = ebone->roll2; + + if (prev && (ebone->flag & BONE_ADD_PARENT_END_ROLL)) { + param.roll1 += prev->roll2; + } + + param.scaleIn = ebone->scaleIn; + param.scaleOut = ebone->scaleOut; + + param.curveInX = ebone->curveInX; + param.curveInY = ebone->curveInY; + + param.curveOutX = ebone->curveOutX; + param.curveOutY = ebone->curveOutY; + + ebone->segments = BKE_compute_b_bone_spline(¶m, (Mat4*)result_array); } static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pchan) @@ -1624,6 +1657,7 @@ static void draw_armature_edit(Object *ob) const bool is_select = DRW_state_is_select(); update_color(ob, NULL); + edbo_compute_bbone_child(arm); const bool show_text = DRW_state_show_text(); const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 9347d2037b0..7bade53cdf4 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -101,6 +101,8 @@ typedef struct EditBone { /* 32 == MAX_BBONE_SUBDIV */ float disp_bbone_mat[32][4][4]; /* in Armature space, rest pos matrix */ + struct EditBone *bbone_child; /* connected child temporary during drawing */ + /* Used to store temporary data */ union { struct EditBone *ebone; |