Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/constraint.c
| Show First 20 Lines • Show All 586 Lines • ▼ Show 20 Lines | if (pchan) { | ||||
| /* skip length interpolation if set to head */ | /* skip length interpolation if set to head */ | ||||
| mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); | mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); | ||||
| } | } | ||||
| else if (is_bbone && pchan->bone->segments == pchan->runtime.bbone_segments) { | else if (is_bbone && pchan->bone->segments == pchan->runtime.bbone_segments) { | ||||
| /* use point along bbone */ | /* use point along bbone */ | ||||
| Mat4 *bbone = pchan->runtime.bbone_pose_mats; | Mat4 *bbone = pchan->runtime.bbone_pose_mats; | ||||
| float tempmat[4][4]; | float tempmat[4][4]; | ||||
| float loc[3], fac; | float loc[3], fac; | ||||
| /* figure out which segment(s) the headtail value falls in */ | |||||
| fac = (float)pchan->bone->segments * headtail; | |||||
| if (fac >= pchan->bone->segments - 1) { | |||||
| /* special case: end segment doesn't get created properly... */ | |||||
| float pt[3], sfac; | |||||
| int index; | int index; | ||||
| /* bbone points are in bonespace, so need to move to posespace first */ | /* figure out which segment(s) the headtail value falls in */ | ||||
| index = pchan->bone->segments - 1; | BKE_pchan_bbone_deform_segment_index(pchan, headtail, &index, &fac); | ||||
| mul_v3_m4v3(pt, pchan->pose_mat, bbone[index].mat[3]); | |||||
| /* interpolate between last segment point and the endpoint */ | |||||
| sfac = fac - (float)(pchan->bone->segments - 1); /* fac is just the "leftover" between penultimate and last points */ | |||||
| interp_v3_v3v3(loc, pt, pchan->pose_tail, sfac); | |||||
| } | |||||
| else { | |||||
| /* get indices for finding interpolating between points along the bbone */ | |||||
| float pt_a[3], pt_b[3], pt[3]; | |||||
| int index_a, index_b; | |||||
| index_a = floorf(fac); | |||||
| CLAMP(index_a, 0, MAX_BBONE_SUBDIV - 1); | |||||
| index_b = ceilf(fac); | |||||
| CLAMP(index_b, 0, MAX_BBONE_SUBDIV - 1); | |||||
| /* interpolate between these points */ | |||||
| copy_v3_v3(pt_a, bbone[index_a].mat[3]); | |||||
| copy_v3_v3(pt_b, bbone[index_b].mat[3]); | |||||
| interp_v3_v3v3(pt, pt_a, pt_b, fac - floorf(fac)); | |||||
| /* move the point from bone local space to pose space... */ | |||||
| mul_v3_m4v3(loc, pchan->pose_mat, pt); | |||||
| } | |||||
| /* apply full transformation of the segment if requested */ | /* apply full transformation of the segment if requested */ | ||||
| if (full_bbone) { | if (full_bbone) { | ||||
| int index = floorf(fac); | interp_m4_m4m4(tempmat, bbone[index].mat, bbone[index + 1].mat, fac); | ||||
| CLAMP(index, 0, pchan->bone->segments - 1); | |||||
| mul_m4_m4m4(tempmat, pchan->pose_mat, bbone[index].mat); | mul_m4_m4m4(tempmat, pchan->pose_mat, tempmat); | ||||
| } | } | ||||
| /* only interpolate location */ | |||||
| else { | else { | ||||
| interp_v3_v3v3(loc, bbone[index].mat[3], bbone[index + 1].mat[3], fac); | |||||
| copy_m4_m4(tempmat, pchan->pose_mat); | copy_m4_m4(tempmat, pchan->pose_mat); | ||||
| mul_v3_m4v3(tempmat[3], pchan->pose_mat, loc); | |||||
| } | } | ||||
| /* use interpolated distance for subtarget */ | |||||
| copy_v3_v3(tempmat[3], loc); | |||||
| mul_m4_m4m4(mat, ob->obmat, tempmat); | mul_m4_m4m4(mat, ob->obmat, tempmat); | ||||
| } | } | ||||
| else { | else { | ||||
| float tempmat[4][4], loc[3]; | float tempmat[4][4], loc[3]; | ||||
| /* interpolate along length of bone */ | /* interpolate along length of bone */ | ||||
| interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail); | interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail); | ||||
| ▲ Show 20 Lines • Show All 1,495 Lines • ▼ Show 20 Lines | if (ct->tar && ct->tar->type == OB_ARMATURE) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| unit_m4(ct->matrix); | unit_m4(ct->matrix); | ||||
| } | } | ||||
| } | } | ||||
| static void armdef_accumulate_matrix(float obmat[4][4], float iobmat[4][4], float basemat[4][4], float bonemat[4][4], float weight, float r_sum_mat[4][4], DualQuat *r_sum_dq) | |||||
| { | |||||
| if (weight == 0.0f) | |||||
| return; | |||||
| /* Convert the selected matrix into object space. */ | |||||
| float mat[4][4]; | |||||
| mul_m4_series(mat, obmat, bonemat, iobmat); | |||||
| /* Accumulate the transformation. */ | |||||
| if (r_sum_dq != NULL) { | |||||
| DualQuat tmpdq; | |||||
| mat4_to_dquat(&tmpdq, basemat, mat); | |||||
| add_weighted_dq_dq(r_sum_dq, &tmpdq, weight); | |||||
| } | |||||
| else { | |||||
| madd_m4_m4m4fl(r_sum_mat, r_sum_mat, mat, weight); | |||||
| } | |||||
| } | |||||
| /* Compute and accumulate transformation for a single target bone. */ | /* Compute and accumulate transformation for a single target bone. */ | ||||
| static void armdef_accumulate_bone(bConstraintTarget *ct, bPoseChannel *pchan, const float wco[3], bool force_envelope, float *r_totweight, float r_sum_mat[4][4], DualQuat *r_sum_dq) | static void armdef_accumulate_bone(bConstraintTarget *ct, bPoseChannel *pchan, const float wco[3], bool force_envelope, float *r_totweight, float r_sum_mat[4][4], DualQuat *r_sum_dq) | ||||
| { | { | ||||
| float mat[4][4], iobmat[4][4], basemat[4][4], co[3]; | float iobmat[4][4], basemat[4][4], co[3]; | ||||
| Bone *bone = pchan->bone; | Bone *bone = pchan->bone; | ||||
| float weight = ct->weight; | float weight = ct->weight; | ||||
| /* Our object's location in target pose space. */ | /* Our object's location in target pose space. */ | ||||
| invert_m4_m4(iobmat, ct->tar->obmat); | invert_m4_m4(iobmat, ct->tar->obmat); | ||||
| mul_v3_m4v3(co, iobmat, wco); | mul_v3_m4v3(co, iobmat, wco); | ||||
| /* Multiply by the envelope weight when appropriate. */ | /* Multiply by the envelope weight when appropriate. */ | ||||
| if (force_envelope || (bone->flag & BONE_MULT_VG_ENV)) { | if (force_envelope || (bone->flag & BONE_MULT_VG_ENV)) { | ||||
| weight *= distfactor_to_bone(co, bone->arm_head, bone->arm_tail, | weight *= distfactor_to_bone(co, bone->arm_head, bone->arm_tail, | ||||
| bone->rad_head, bone->rad_tail, bone->dist); | bone->rad_head, bone->rad_tail, bone->dist); | ||||
| } | } | ||||
| /* Compute the quaternion base matrix. */ | |||||
| if (r_sum_dq != NULL) { | |||||
| mul_m4_series(basemat, ct->tar->obmat, bone->arm_mat, iobmat); | |||||
| } | |||||
| /* Find the correct bone transform matrix in world space. */ | /* Find the correct bone transform matrix in world space. */ | ||||
| if (bone->segments > 1 && bone->segments == pchan->runtime.bbone_segments) { | if (bone->segments > 1 && bone->segments == pchan->runtime.bbone_segments) { | ||||
| Mat4 *b_bone_mats = pchan->runtime.bbone_deform_mats; | Mat4 *b_bone_mats = pchan->runtime.bbone_deform_mats; | ||||
| float (*iamat)[4] = b_bone_mats[0].mat; | float (*iamat)[4] = b_bone_mats[0].mat; | ||||
| /* The target is a B-Bone: | /* The target is a B-Bone: | ||||
| * FIRST: find the segment (see b_bone_deform in armature.c) | * FIRST: find the segment (see b_bone_deform in armature.c) | ||||
| * Need to transform co back to bonespace, only need y. */ | * Need to transform co back to bonespace, only need y. */ | ||||
| float y = iamat[0][1] * co[0] + iamat[1][1] * co[1] + iamat[2][1] * co[2] + iamat[3][1]; | float y = iamat[0][1] * co[0] + iamat[1][1] * co[1] + iamat[2][1] * co[2] + iamat[3][1]; | ||||
| float segment = bone->length / ((float)bone->segments); | /* Blend the matrix. */ | ||||
| int a = (int)(y / segment); | int index; | ||||
| float blend; | |||||
| CLAMP(a, 0, bone->segments - 1); | BKE_pchan_bbone_deform_segment_index(pchan, y / bone->length, &index, &blend); | ||||
| /* Convert the selected matrix into object space. */ | armdef_accumulate_matrix(ct->tar->obmat, iobmat, basemat, b_bone_mats[index + 1].mat, weight * (1.0f - blend), r_sum_mat, r_sum_dq); | ||||
| mul_m4_series(mat, ct->tar->obmat, b_bone_mats[a + 1].mat, iobmat); | armdef_accumulate_matrix(ct->tar->obmat, iobmat, basemat, b_bone_mats[index + 2].mat, weight * blend, r_sum_mat, r_sum_dq); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Simple bone. This requires DEG_OPCODE_BONE_DONE dependency due to chan_mat. */ | /* Simple bone. This requires DEG_OPCODE_BONE_DONE dependency due to chan_mat. */ | ||||
| mul_m4_series(mat, ct->tar->obmat, pchan->chan_mat, iobmat); | armdef_accumulate_matrix(ct->tar->obmat, iobmat, basemat, pchan->chan_mat, weight, r_sum_mat, r_sum_dq); | ||||
| } | } | ||||
| /* Accumulate the transformation. */ | /* Accumulate the weight. */ | ||||
| *r_totweight += weight; | *r_totweight += weight; | ||||
| if (r_sum_dq != NULL) { | |||||
| DualQuat tmpdq; | |||||
| mul_m4_series(basemat, ct->tar->obmat, bone->arm_mat, iobmat); | |||||
| mat4_to_dquat(&tmpdq, basemat, mat); | |||||
| add_weighted_dq_dq(r_sum_dq, &tmpdq, weight); | |||||
| } | |||||
| else { | |||||
| mul_m4_fl(mat, weight); | |||||
| add_m4_m4m4(r_sum_mat, r_sum_mat, mat); | |||||
| } | |||||
| } | } | ||||
| static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets) | static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets) | ||||
| { | { | ||||
| bArmatureConstraint *data = con->data; | bArmatureConstraint *data = con->data; | ||||
| float sum_mat[4][4], input_co[3]; | float sum_mat[4][4], input_co[3]; | ||||
| DualQuat sum_dq; | DualQuat sum_dq; | ||||
| ▲ Show 20 Lines • Show All 3,161 Lines • Show Last 20 Lines | |||||