diff options
Diffstat (limited to 'source/blender/blenkernel/intern/armature_update.c')
-rw-r--r-- | source/blender/blenkernel/intern/armature_update.c | 560 |
1 files changed, 356 insertions, 204 deletions
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 475b64cb9b3..9130c378121 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -63,40 +63,40 @@ typedef struct tSplineIK_Tree { bPoseChannel *root; /* bone that is the root node of the chain */ - bConstraint *con; /* constraint for this chain */ - bSplineIKConstraint *ikData; /* constraint settings for this chain */ + bConstraint *con; /* constraint for this chain */ + bSplineIKConstraint *ik_data; /* constraint settings for this chain */ } tSplineIK_Tree; /* ----------- */ -/* Tag the bones in the chain formed by the given bone for IK */ +/* Tag the bones in the chain formed by the given bone for IK. */ static void splineik_init_tree_from_pchan(Scene *UNUSED(scene), Object *UNUSED(ob), bPoseChannel *pchan_tip) { - bPoseChannel *pchan, *pchanRoot = NULL; - bPoseChannel *pchanChain[255]; + bPoseChannel *pchan, *pchan_root = NULL; + bPoseChannel *pchan_chain[255]; bConstraint *con = NULL; - bSplineIKConstraint *ikData = NULL; - float boneLengths[255]; - float totLength = 0.0f; + bSplineIKConstraint *ik_data = NULL; + float bone_lengths[255]; + float totlength = 0.0f; int segcount = 0; - /* find the SplineIK constraint */ + /* Find the SplineIK constraint. */ for (con = pchan_tip->constraints.first; con; con = con->next) { if (con->type == CONSTRAINT_TYPE_SPLINEIK) { - ikData = con->data; + ik_data = con->data; - /* target can only be curve */ - if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE)) { + /* Target can only be a curve. */ + if ((ik_data->tar == NULL) || (ik_data->tar->type != OB_CURVE)) { continue; } - /* skip if disabled */ + /* Skip if disabled. */ if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))) { continue; } - /* otherwise, constraint is ok... */ + /* Otherwise, constraint is ok... */ break; } } @@ -104,102 +104,102 @@ static void splineik_init_tree_from_pchan(Scene *UNUSED(scene), return; } - /* find the root bone and the chain of bones from the root to the tip + /* Find the root bone and the chain of bones from the root to the tip. * NOTE: this assumes that the bones are connected, but that may not be true... */ - for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); + for (pchan = pchan_tip; pchan && (segcount < ik_data->chainlen); pchan = pchan->parent, segcount++) { - /* store this segment in the chain */ - pchanChain[segcount] = pchan; + /* Store this segment in the chain. */ + pchan_chain[segcount] = pchan; - /* if performing rebinding, calculate the length of the bone */ - boneLengths[segcount] = pchan->bone->length; - totLength += boneLengths[segcount]; + /* If performing rebinding, calculate the length of the bone. */ + bone_lengths[segcount] = pchan->bone->length; + totlength += bone_lengths[segcount]; } if (segcount == 0) { return; } - pchanRoot = pchanChain[segcount - 1]; + pchan_root = pchan_chain[segcount - 1]; - /* perform binding step if required */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) { + /* Perform binding step if required. */ + if ((ik_data->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) { float segmentLen = (1.0f / (float)segcount); - /* setup new empty array for the points list */ - if (ikData->points) { - MEM_freeN(ikData->points); + /* Setup new empty array for the points list. */ + if (ik_data->points) { + MEM_freeN(ik_data->points); } - ikData->numpoints = ikData->chainlen + 1; - ikData->points = MEM_mallocN(sizeof(float) * ikData->numpoints, "Spline IK Binding"); + ik_data->numpoints = ik_data->chainlen + 1; + ik_data->points = MEM_mallocN(sizeof(float) * ik_data->numpoints, "Spline IK Binding"); - /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */ - ikData->points[0] = 1.0f; + /* Bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint). */ + ik_data->points[0] = 1.0f; - /* perform binding of the joints to parametric positions along the curve based - * proportion of the total length that each bone occupies + /* Perform binding of the joints to parametric positions along the curve based + * proportion of the total length that each bone occupies. */ for (int i = 0; i < segcount; i++) { - /* 'head' joints, traveling towards the root of the chain - * - 2 methods; the one chosen depends on whether we've got usable lengths + /* 'head' joints, traveling towards the root of the chain. + * - 2 methods; the one chosen depends on whether we've got usable lengths. */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) { - /* 1) equi-spaced joints */ - ikData->points[i + 1] = ikData->points[i] - segmentLen; + if ((ik_data->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totlength == 0.0f)) { + /* 1) Equi-spaced joints. */ + ik_data->points[i + 1] = ik_data->points[i] - segmentLen; } else { - /* 2) to find this point on the curve, we take a step from the previous joint - * a distance given by the proportion that this bone takes + /* 2) To find this point on the curve, we take a step from the previous joint + * a distance given by the proportion that this bone takes. */ - ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength); + ik_data->points[i + 1] = ik_data->points[i] - (bone_lengths[i] / totlength); } } - /* spline has now been bound */ - ikData->flag |= CONSTRAINT_SPLINEIK_BOUND; + /* Spline has now been bound. */ + ik_data->flag |= CONSTRAINT_SPLINEIK_BOUND; } - /* disallow negative values (happens with float precision) */ - CLAMP_MIN(ikData->points[segcount], 0.0f); + /* Disallow negative values (happens with float precision). */ + CLAMP_MIN(ik_data->points[segcount], 0.0f); - /* make a new Spline-IK chain, and store it in the IK chains */ + /* Make a new Spline-IK chain, and store it in the IK chains. */ /* TODO: we should check if there is already an IK chain on this, * since that would take precedence... */ { - /* make new tree */ + /* Make a new tree. */ tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree"); tree->type = CONSTRAINT_TYPE_SPLINEIK; tree->chainlen = segcount; - tree->totlength = totLength; + tree->totlength = totlength; - /* copy over the array of links to bones in the chain (from tip to root) */ + /* Copy over the array of links to bones in the chain (from tip to root). */ tree->chain = MEM_mallocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain"); - memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount); + memcpy(tree->chain, pchan_chain, sizeof(bPoseChannel *) * segcount); - /* store reference to joint position array */ - tree->points = ikData->points; + /* Store reference to joint position array. */ + tree->points = ik_data->points; - /* store references to different parts of the chain */ - tree->root = pchanRoot; + /* Store references to different parts of the chain. */ + tree->root = pchan_root; tree->con = con; - tree->ikData = ikData; + tree->ik_data = ik_data; - /* AND! link the tree to the root */ - BLI_addtail(&pchanRoot->siktree, tree); + /* AND! Link the tree to the root. */ + BLI_addtail(&pchan_root->siktree, tree); } - /* mark root channel having an IK tree */ - pchanRoot->flag |= POSE_IKSPLINE; + /* Mark root channel having an IK tree. */ + pchan_root->flag |= POSE_IKSPLINE; } -/* Tag which bones are members of Spline IK chains */ +/* Tag which bones are members of Spline IK chains. */ static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime)) { bPoseChannel *pchan; - /* find the tips of Spline IK chains, - * which are simply the bones which have been tagged as such */ + /* Find the tips of Spline IK chains, + * which are simply the bones which have been tagged as such. */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->constflag & PCHAN_HAS_SPLINEIK) { splineik_init_tree_from_pchan(scene, ob, pchan); @@ -213,21 +213,24 @@ typedef struct tSplineIk_EvalState { float curve_position; /* Current position along the curve. */ float curve_scale; /* Global scale to apply to curve positions. */ float locrot_offset[4][4]; /* Bone rotation and location offset inherited from parent. */ + float prev_tail_loc[3]; /* Tail location of the previous bone. */ + float prev_tail_radius; /* Tail curve radius of the previous bone. */ + int prev_tail_seg_idx; /* Curve segment the previous tail bone belongs to. */ } tSplineIk_EvalState; /* Prepare data to evaluate spline IK. */ static bool splineik_evaluate_init(tSplineIK_Tree *tree, tSplineIk_EvalState *state) { - bSplineIKConstraint *ikData = tree->ikData; + bSplineIKConstraint *ik_data = tree->ik_data; /* Make sure that the constraint targets are ok, to avoid crashes * in case of a depsgraph bug or dependency cycle. */ - if (ikData->tar == NULL) { + if (ik_data->tar == NULL) { return false; } - CurveCache *cache = ikData->tar->runtime.curve_cache; + CurveCache *cache = ik_data->tar->runtime.curve_cache; if (ELEM(NULL, cache, cache->anim_path_accum_length)) { return false; @@ -237,97 +240,249 @@ static bool splineik_evaluate_init(tSplineIK_Tree *tree, tSplineIk_EvalState *st state->curve_position = 0.0f; state->curve_scale = 1.0f; unit_m4(state->locrot_offset); + zero_v3(state->prev_tail_loc); + state->prev_tail_radius = 1.0f; + state->prev_tail_seg_idx = 0; /* Apply corrections for sensitivity to scaling. */ - if ((ikData->yScaleMode != CONSTRAINT_SPLINEIK_YS_FIT_CURVE) && (tree->totlength != 0.0f)) { - /* get the current length of the curve */ - /* NOTE: this is assumed to be correct even after the curve was resized */ - const float splineLen = BKE_anim_path_get_length(cache); + if ((ik_data->yScaleMode != CONSTRAINT_SPLINEIK_YS_FIT_CURVE) && (tree->totlength != 0.0f)) { + /* Get the current length of the curve. */ + /* NOTE: This is assumed to be correct even after the curve was resized. */ + const float spline_len = BKE_anim_path_get_length(cache); - /* calculate the scale factor to multiply all the path values by so that the - * bone chain retains its current length, such that + /* Calculate the scale factor to multiply all the path values by so that the + * bone chain retains its current length, such that: * maxScale * splineLen = totLength */ - state->curve_scale = tree->totlength / splineLen; + state->curve_scale = tree->totlength / spline_len; } return true; } +static void apply_curve_transform( + bSplineIKConstraint *ik_data, Object *ob, float radius, float r_vec[3], float *r_radius) +{ + /* Apply the curve's object-mode transforms to the position + * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root). + */ + if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) { + mul_m4_v3(ik_data->tar->obmat, r_vec); + } + + /* Convert the position to pose-space. */ + mul_m4_v3(ob->imat, r_vec); + + /* Set the new radius (it should be the average value). */ + *r_radius = (radius + *r_radius) / 2; +} + +/* This function positions the tail of the bone so that it preserves the length of it. + * The length of the bone can be seen as a sphere radius. + */ +static int position_tail_on_spline(bSplineIKConstraint *ik_data, + const float head_pos[3], + const float sphere_radius, + const int prev_seg_idx, + float r_tail_pos[3], + float *r_new_curve_pos, + float *r_radius) +{ + /* This is using the tesselated curve data. + * So we are working with piecewise linear curve segements. + * The same method is use in `BKE_where_on_path` to get curve location data. + */ + const CurveCache *cache = ik_data->tar->runtime.curve_cache; + const BevList *bl = cache->bev.first; + BevPoint *bp = bl->bevpoints; + const float spline_len = BKE_anim_path_get_length(cache); + const float *seg_accum_len = cache->anim_path_accum_length; + + int max_seg_idx = BKE_anim_path_get_array_size(cache) - 1; + + /* Convert our initial intersection point guess to a point index. + * If the curve was a straight line, then pointEnd would be the correct location. + * So make it our first initial guess. + */ + const float guessed_len = *r_new_curve_pos * spline_len; + + BLI_assert(prev_seg_idx >= 0); + + int cur_seg_idx = prev_seg_idx; + while (cur_seg_idx < max_seg_idx && guessed_len > seg_accum_len[cur_seg_idx]) { + cur_seg_idx++; + } + + int bp_idx = cur_seg_idx + 1; + + bp = bp + bp_idx; + bool is_cyclic = bl->poly >= 0; + BevPoint *prev_bp = bp - 1; + + /* Go to the next tesselated curve point until we cross to outside of the sphere. */ + while (len_v3v3(head_pos, bp->vec) < sphere_radius) { + if (bp_idx > max_seg_idx) { + /* We are outside the defined curve. We will now extrapolate the intersection point. */ + break; + } + prev_bp = bp; + if (is_cyclic && bp_idx == max_seg_idx) { + /* Wrap around to the start point. + * Don't set the bp_idx to zero here as we use it to get the segment index later. + */ + bp = bl->bevpoints; + } + else { + bp++; + } + bp_idx++; + } + + float isect_1[3], isect_2[3]; + + /* Calculate the intersection point. */ + isect_line_sphere_v3(prev_bp->vec, bp->vec, head_pos, sphere_radius, isect_1, isect_2); + + /* Because of how `isect_line_sphere_v3` works, we know that `isect_1` contains the + * intersection point we want. And it will always intersect as we go from inside to outside + * of the sphere. + */ + copy_v3_v3(r_tail_pos, isect_1); + + cur_seg_idx = bp_idx - 2; + float prev_seg_len = 0; + + if (cur_seg_idx < 0) { + cur_seg_idx = 0; + prev_seg_len = 0; + } + else { + prev_seg_len = seg_accum_len[cur_seg_idx]; + } + + /* Convert the point back into the 0-1 interpolation range. */ + const float isect_seg_len = len_v3v3(prev_bp->vec, isect_1); + const float frac = isect_seg_len / len_v3v3(prev_bp->vec, bp->vec); + *r_new_curve_pos = (prev_seg_len + isect_seg_len) / spline_len; + + if (*r_new_curve_pos > 1.0f) { + *r_radius = bp->radius; + } + else { + *r_radius = (1.0f - frac) * prev_bp->radius + frac * bp->radius; + } + + return cur_seg_idx; +} + /* Evaluate spline IK for a given bone. */ static void splineik_evaluate_bone( tSplineIK_Tree *tree, Object *ob, bPoseChannel *pchan, int index, tSplineIk_EvalState *state) { - bSplineIKConstraint *ikData = tree->ikData; - float origHead[3], origTail[3], poseHead[3], poseTail[3], basePoseMat[3][3], poseMat[3][3]; - float splineVec[3], scaleFac, radius = 1.0f; - float tailBlendFac = 0.0f; + bSplineIKConstraint *ik_data = tree->ik_data; + + if (pchan->bone->length == 0.0f) { + /* Only move the bone position with zero length bones. */ + float bone_pos[4], dir[3], rad; + BKE_where_on_path(ik_data->tar, state->curve_position, bone_pos, dir, NULL, &rad, NULL); + + apply_curve_transform(ik_data, ob, rad, bone_pos, &rad); + + copy_v3_v3(pchan->pose_mat[3], bone_pos); + copy_v3_v3(pchan->pose_head, bone_pos); + copy_v3_v3(pchan->pose_tail, bone_pos); + pchan->flag |= POSE_DONE; + return; + } - mul_v3_m4v3(poseHead, state->locrot_offset, pchan->pose_head); - mul_v3_m4v3(poseTail, state->locrot_offset, pchan->pose_tail); + float orig_head[3], orig_tail[3], pose_head[3], pose_tail[3]; + float base_pose_mat[3][3], pose_mat[3][3]; + float spline_vec[3], scale_fac, radius = 1.0f; + float tail_blend_fac = 0.0f; - copy_v3_v3(origHead, poseHead); + mul_v3_m4v3(pose_head, state->locrot_offset, pchan->pose_head); + mul_v3_m4v3(pose_tail, state->locrot_offset, pchan->pose_tail); - /* first, adjust the point positions on the curve */ + copy_v3_v3(orig_head, pose_head); + + /* First, adjust the point positions on the curve. */ float curveLen = tree->points[index] - tree->points[index + 1]; - float pointStart = state->curve_position; - float poseScale = len_v3v3(poseHead, poseTail) / pchan->bone->length; - float baseScale = 1.0f; + float bone_len = len_v3v3(pose_head, pose_tail); + float point_start = state->curve_position; + float pose_scale = bone_len / pchan->bone->length; + float base_scale = 1.0f; - if (ikData->yScaleMode == CONSTRAINT_SPLINEIK_YS_ORIGINAL) { + if (ik_data->yScaleMode == CONSTRAINT_SPLINEIK_YS_ORIGINAL) { /* Carry over the bone Y scale to the curve range. */ - baseScale = poseScale; + base_scale = pose_scale; } - float pointEnd = pointStart + curveLen * baseScale * state->curve_scale; + float point_end = point_start + curveLen * base_scale * state->curve_scale; - state->curve_position = pointEnd; + state->curve_position = point_end; - /* step 1: determine the positions for the endpoints of the bone */ - if (pointStart < 1.0f) { + /* Step 1: determine the positions for the endpoints of the bone. */ + if (point_start < 1.0f) { float vec[4], dir[3], rad; + radius = 0.0f; - /* determine if the bone should still be affected by SplineIK */ - if (pointEnd >= 1.0f) { - /* blending factor depends on the amount of the bone still left on the chain */ - tailBlendFac = (1.0f - pointStart) / (pointEnd - pointStart); + /* Calculate head position. */ + if (point_start == 0.0f) { + /* Start of the path. We have no previous tail position to copy. */ + BKE_where_on_path(ik_data->tar, point_start, vec, dir, NULL, &rad, NULL); } else { - tailBlendFac = 1.0f; + copy_v3_v3(vec, state->prev_tail_loc); + rad = state->prev_tail_radius; } - /* tail endpoint */ - if (BKE_where_on_path(ikData->tar, pointEnd, vec, dir, NULL, &rad, NULL)) { - /* apply curve's object-mode transforms to the position - * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) { - mul_m4_v3(ikData->tar->obmat, vec); + radius = rad; + copy_v3_v3(pose_head, vec); + apply_curve_transform(ik_data, ob, rad, pose_head, &radius); + + /* Calculate tail position. */ + if (ik_data->yScaleMode != CONSTRAINT_SPLINEIK_YS_FIT_CURVE) { + float sphere_radius; + + if (ik_data->yScaleMode == CONSTRAINT_SPLINEIK_YS_ORIGINAL) { + sphere_radius = bone_len; + } + else { + /* Don't take bone scale into account. */ + sphere_radius = pchan->bone->length; } - /* convert the position to pose-space, then store it */ - mul_m4_v3(ob->imat, vec); - copy_v3_v3(poseTail, vec); + /* Calculate the tail position with sphere curve intersection. */ + state->prev_tail_seg_idx = position_tail_on_spline( + ik_data, vec, sphere_radius, state->prev_tail_seg_idx, pose_tail, &point_end, &rad); - /* set the new radius */ - radius = rad; - } + state->prev_tail_radius = rad; + copy_v3_v3(state->prev_tail_loc, pose_tail); - /* head endpoint */ - if (BKE_where_on_path(ikData->tar, pointStart, vec, dir, NULL, &rad, NULL)) { - /* apply curve's object-mode transforms to the position - * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) { - mul_m4_v3(ikData->tar->obmat, vec); + apply_curve_transform(ik_data, ob, rad, pose_tail, &radius); + state->curve_position = point_end; + } + else { + /* Scale to fit curve end position. */ + if (BKE_where_on_path(ik_data->tar, point_end, vec, dir, NULL, &rad, NULL)) { + state->prev_tail_radius = rad; + copy_v3_v3(state->prev_tail_loc, vec); + copy_v3_v3(pose_tail, vec); + apply_curve_transform(ik_data, ob, rad, pose_tail, &radius); } + } - /* store the position, and convert it to pose space */ - mul_m4_v3(ob->imat, vec); - copy_v3_v3(poseHead, vec); - - /* set the new radius (it should be the average value) */ - radius = (radius + rad) / 2; + /* Determine if the bone should still be affected by SplineIK. + * This makes it so that the bone slowly becomes poseable again the further it rolls off the + * curve. When the whole bone has rolled off the curve, the IK contraint will not influence it + * anymore. + */ + if (point_end >= 1.0f) { + /* Blending factor depends on the amount of the bone still left on the chain. */ + tail_blend_fac = (1.0f - point_start) / (point_end - point_start); + } + else { + tail_blend_fac = 1.0f; } } @@ -335,11 +490,8 @@ static void splineik_evaluate_bone( * - splineVec: the vector direction that the spline applies on the bone. * - scaleFac: the factor that the bone length is scaled by to get the desired amount. */ - sub_v3_v3v3(splineVec, poseTail, poseHead); - scaleFac = len_v3(splineVec) / pchan->bone->length; - - /* Extrapolate the full length of the bone as it rolls off the end of the curve. */ - scaleFac = (tailBlendFac < 1e-5f) ? baseScale : scaleFac / tailBlendFac; + sub_v3_v3v3(spline_vec, pose_tail, pose_head); + scale_fac = len_v3(spline_vec) / pchan->bone->length; /* Step 3: compute the shortest rotation needed * to map from the bone rotation to the current axis. @@ -350,83 +502,83 @@ static void splineik_evaluate_bone( float dmat[3][3], rmat[3][3]; float raxis[3], rangle; - /* compute the raw rotation matrix from the bone's current matrix by extracting only the - * orientation-relevant axes, and normalizing them + /* Compute the raw rotation matrix from the bone's current matrix by extracting only the + * orientation-relevant axes, and normalizing them. */ - mul_m3_m4m4(basePoseMat, state->locrot_offset, pchan->pose_mat); - normalize_m3_m3(rmat, basePoseMat); + mul_m3_m4m4(base_pose_mat, state->locrot_offset, pchan->pose_mat); + normalize_m3_m3(rmat, base_pose_mat); /* Also, normalize the orientation imposed by the bone, * now that we've extracted the scale factor. */ - normalize_v3(splineVec); + normalize_v3(spline_vec); - /* calculate smallest axis-angle rotation necessary for getting from the - * current orientation of the bone, to the spline-imposed direction + /* Calculate smallest axis-angle rotation necessary for getting from the + * current orientation of the bone, to the spline-imposed direction. */ - cross_v3_v3v3(raxis, rmat[1], splineVec); + cross_v3_v3v3(raxis, rmat[1], spline_vec); - rangle = dot_v3v3(rmat[1], splineVec); + rangle = dot_v3v3(rmat[1], spline_vec); CLAMP(rangle, -1.0f, 1.0f); rangle = acosf(rangle); - /* multiply the magnitude of the angle by the influence of the constraint to - * control the influence of the SplineIK effect + /* Multiply the magnitude of the angle by the influence of the constraint to + * control the influence of the SplineIK effect. */ - rangle *= tree->con->enforce * tailBlendFac; + rangle *= tree->con->enforce * tail_blend_fac; - /* construct rotation matrix from the axis-angle rotation found above - * - this call takes care to make sure that the axis provided is a unit vector first + /* Construct rotation matrix from the axis-angle rotation found above. + * - This call takes care to make sure that the axis provided is a unit vector first. */ axis_angle_to_mat3(dmat, raxis, rangle); /* Combine these rotations so that the y-axis of the bone is now aligned as the * spline dictates, while still maintaining roll control from the existing bone animation. */ - mul_m3_m3m3(poseMat, dmat, rmat); + mul_m3_m3m3(pose_mat, dmat, rmat); - /* attempt to reduce shearing, though I doubt this'll really help too much now... */ - normalize_m3(poseMat); + /* Attempt to reduce shearing, though I doubt this'll really help too much now... */ + normalize_m3(pose_mat); - mul_m3_m3m3(basePoseMat, dmat, basePoseMat); + mul_m3_m3m3(base_pose_mat, dmat, base_pose_mat); - /* apply rotation to the accumulated parent transform */ + /* Apply rotation to the accumulated parent transform. */ mul_m4_m3m4(state->locrot_offset, dmat, state->locrot_offset); } - /* step 4: set the scaling factors for the axes */ + /* Step 4: Set the scaling factors for the axes. */ /* Always multiply the y-axis by the scaling factor to get the correct length. */ - mul_v3_fl(poseMat[1], scaleFac); + mul_v3_fl(pose_mat[1], scale_fac); /* After that, apply x/z scaling modes. */ - if (ikData->xzScaleMode != CONSTRAINT_SPLINEIK_XZS_NONE) { + if (ik_data->xzScaleMode != CONSTRAINT_SPLINEIK_XZS_NONE) { /* First, apply the original scale if enabled. */ - if (ikData->xzScaleMode == CONSTRAINT_SPLINEIK_XZS_ORIGINAL || - (ikData->flag & CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE) != 0) { + if (ik_data->xzScaleMode == CONSTRAINT_SPLINEIK_XZS_ORIGINAL || + (ik_data->flag & CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE) != 0) { float scale; - /* x-axis scale */ + /* X-axis scale. */ scale = len_v3(pchan->pose_mat[0]); - mul_v3_fl(poseMat[0], scale); - /* z-axis scale */ + mul_v3_fl(pose_mat[0], scale); + /* Z-axis scale. */ scale = len_v3(pchan->pose_mat[2]); - mul_v3_fl(poseMat[2], scale); + mul_v3_fl(pose_mat[2], scale); /* Adjust the scale factor used for volume preservation * to consider the pre-IK scaling as the initial volume. */ - scaleFac /= poseScale; + scale_fac /= pose_scale; } /* Apply volume preservation. */ - switch (ikData->xzScaleMode) { + switch (ik_data->xzScaleMode) { case CONSTRAINT_SPLINEIK_XZS_INVERSE: { - /* old 'volume preservation' method using the inverse scale */ + /* Old 'volume preservation' method using the inverse scale. */ float scale; - /* calculate volume preservation factor which is - * basically the inverse of the y-scaling factor + /* Calculate volume preservation factor which is + * basically the inverse of the y-scaling factor. */ - if (fabsf(scaleFac) != 0.0f) { - scale = 1.0f / fabsf(scaleFac); + if (fabsf(scale_fac) != 0.0f) { + scale = 1.0f / fabsf(scale_fac); /* We need to clamp this within sensible values. */ /* NOTE: these should be fine for now, but should get sanitized in future. */ @@ -436,56 +588,56 @@ static void splineik_evaluate_bone( scale = 1.0f; } - /* apply the scaling */ - mul_v3_fl(poseMat[0], scale); - mul_v3_fl(poseMat[2], scale); + /* Apply the scaling. */ + mul_v3_fl(pose_mat[0], scale); + mul_v3_fl(pose_mat[2], scale); break; } case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: { - /* improved volume preservation based on the Stretch To constraint */ + /* Improved volume preservation based on the Stretch To constraint. */ float final_scale; - /* as the basis for volume preservation, we use the inverse scale factor... */ - if (fabsf(scaleFac) != 0.0f) { - /* NOTE: The method here is taken wholesale from the Stretch To constraint */ - float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge); + /* As the basis for volume preservation, we use the inverse scale factor... */ + if (fabsf(scale_fac) != 0.0f) { + /* NOTE: The method here is taken wholesale from the Stretch To constraint. */ + float bulge = powf(1.0f / fabsf(scale_fac), ik_data->bulge); if (bulge > 1.0f) { - if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) { - float bulge_max = max_ff(ikData->bulge_max, 1.0f); + if (ik_data->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) { + float bulge_max = max_ff(ik_data->bulge_max, 1.0f); float hard = min_ff(bulge, bulge_max); float range = bulge_max - 1.0f; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2; - bulge = interpf(soft, hard, ikData->bulge_smooth); + bulge = interpf(soft, hard, ik_data->bulge_smooth); } } if (bulge < 1.0f) { - if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) { - float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f); + if (ik_data->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) { + float bulge_min = CLAMPIS(ik_data->bulge_min, 0.0f, 1.0f); float hard = max_ff(bulge, bulge_min); float range = 1.0f - bulge_min; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2; - bulge = interpf(soft, hard, ikData->bulge_smooth); + bulge = interpf(soft, hard, ik_data->bulge_smooth); } } - /* compute scale factor for xz axes from this value */ + /* Compute scale factor for xz axes from this value. */ final_scale = sqrtf(bulge); } else { - /* no scaling, so scale factor is simple */ + /* No scaling, so scale factor is simple. */ final_scale = 1.0f; } /* Apply the scaling (assuming normalized scale). */ - mul_v3_fl(poseMat[0], final_scale); - mul_v3_fl(poseMat[2], final_scale); + mul_v3_fl(pose_mat[0], final_scale); + mul_v3_fl(pose_mat[2], final_scale); break; } } @@ -494,49 +646,49 @@ static void splineik_evaluate_bone( /* Finally, multiply the x and z scaling by the radius of the curve too, * to allow automatic scales to get tweaked still. */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { - mul_v3_fl(poseMat[0], radius); - mul_v3_fl(poseMat[2], radius); + if ((ik_data->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { + mul_v3_fl(pose_mat[0], radius); + mul_v3_fl(pose_mat[2], radius); } /* Blend the scaling of the matrix according to the influence. */ - sub_m3_m3m3(poseMat, poseMat, basePoseMat); - madd_m3_m3m3fl(poseMat, basePoseMat, poseMat, tree->con->enforce * tailBlendFac); + sub_m3_m3m3(pose_mat, pose_mat, base_pose_mat); + madd_m3_m3m3fl(pose_mat, base_pose_mat, pose_mat, tree->con->enforce * tail_blend_fac); - /* step 5: set the location of the bone in the matrix */ - if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { - /* when the 'no-root' option is affected, the chain can retain - * the shape but be moved elsewhere + /* Step 5: Set the location of the bone in the matrix. */ + if (ik_data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { + /* When the 'no-root' option is affected, the chain can retain + * the shape but be moved elsewhere. */ - copy_v3_v3(poseHead, origHead); + copy_v3_v3(pose_head, orig_head); } else if (tree->con->enforce < 1.0f) { - /* when the influence is too low - * - blend the positions for the 'root' bone - * - stick to the parent for any other + /* When the influence is too low: + * - Blend the positions for the 'root' bone. + * - Stick to the parent for any other. */ if (index < tree->chainlen - 1) { - copy_v3_v3(poseHead, origHead); + copy_v3_v3(pose_head, orig_head); } else { - interp_v3_v3v3(poseHead, origHead, poseHead, tree->con->enforce); + interp_v3_v3v3(pose_head, orig_head, pose_head, tree->con->enforce); } } - /* finally, store the new transform */ - copy_m4_m3(pchan->pose_mat, poseMat); - copy_v3_v3(pchan->pose_mat[3], poseHead); - copy_v3_v3(pchan->pose_head, poseHead); + /* Finally, store the new transform. */ + copy_m4_m3(pchan->pose_mat, pose_mat); + copy_v3_v3(pchan->pose_mat[3], pose_head); + copy_v3_v3(pchan->pose_head, pose_head); - mul_v3_mat3_m4v3(origTail, state->locrot_offset, pchan->pose_tail); + mul_v3_mat3_m4v3(orig_tail, state->locrot_offset, pchan->pose_tail); - /* recalculate tail, as it's now outdated after the head gets adjusted above! */ + /* Recalculate tail, as it's now outdated after the head gets adjusted above! */ BKE_pose_where_is_bone_tail(pchan); - /* update the offset in the accumulated parent transform */ - sub_v3_v3v3(state->locrot_offset[3], pchan->pose_tail, origTail); + /* Update the offset in the accumulated parent transform. */ + sub_v3_v3v3(state->locrot_offset[3], pchan->pose_tail, orig_tail); - /* done! */ + /* Done! */ pchan->flag |= POSE_DONE; } @@ -559,8 +711,8 @@ static void splineik_execute_tree( if (splineik_evaluate_init(tree, &state)) { /* Walk over each bone in the chain, calculating the effects of spline IK - * - the chain is traversed in the opposite order to storage order (i.e. parent to children) - * so that dependencies are correct + * - the chain is traversed in the opposite order to storage order + * (i.e. parent to children) so that dependencies are correct */ for (int i = tree->chainlen - 1; i >= 0; i--) { bPoseChannel *pchan = tree->chain[i]; |