/* also sets restposition in armature (arm_mat) */ static void fix_bonelist_roll(ListBase *bonelist, ListBase *editbonelist) { Bone *curBone; EditBone *ebone; float premat[3][3]; float postmat[3][3]; float difmat[3][3]; float imat[3][3]; for (curBone = bonelist->first; curBone; curBone = curBone->next) { /* sets local matrix and arm_mat (restpos) */ BKE_armature_where_is_bone(curBone, curBone->parent); /* Find the associated editbone */ for (ebone = editbonelist->first; ebone; ebone = ebone->next) if (ebone->temp.bone == curBone) break; if (ebone) { /* Get the ebone premat */ ED_armature_ebone_to_mat3(ebone, premat); /* Get the bone postmat */ copy_m3_m4(postmat, curBone->arm_mat); invert_m3_m3(imat, premat); mul_m3_m3m3(difmat, imat, postmat); #if 0 printf("Bone %s\n", curBone->name); print_m4("premat", premat); print_m4("postmat", postmat); print_m4("difmat", difmat); printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2]))); #endif curBone->roll = -atan2f(difmat[2][0], difmat[2][2]); /* and set restposition again */ BKE_armature_where_is_bone(curBone, curBone->parent); } fix_bonelist_roll(&curBone->childbase, editbonelist); } }
/* This function: * - sets local head/tail rest locations using parent bone's arm_mat. * - calls BKE_armature_where_is_bone() which uses parent's transform (arm_mat) to define this bone's transform. * - fixes (converts) EditBone roll into Bone roll. * - calls again BKE_armature_where_is_bone(), since roll fiddling may have changed things for our bone... * Note that order is crucial here, we can only handle child if all its parents in chain have already been handled * (this is ensured by recursive process). */ static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist) { Bone *curBone; EditBone *ebone; for (curBone = bonelist->first; curBone; curBone = curBone->next) { /* Set bone's local head/tail. * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values * from editbone's matrix (see T46010). */ if (curBone->parent) { float parmat_inv[4][4]; invert_m4_m4(parmat_inv, curBone->parent->arm_mat); /* Get the new head and tail */ sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail); sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail); mul_mat3_m4_v3(parmat_inv, curBone->head); mul_mat3_m4_v3(parmat_inv, curBone->tail); } else { copy_v3_v3(curBone->head, curBone->arm_head); copy_v3_v3(curBone->tail, curBone->arm_tail); } /* Set local matrix and arm_mat (restpose). * Do not recurse into children here, armature_finalize_restpose() is already recursive. */ BKE_armature_where_is_bone(curBone, curBone->parent, false); /* Find the associated editbone */ for (ebone = editbonelist->first; ebone; ebone = ebone->next) { if (ebone->temp.bone == curBone) { float premat[3][3]; float postmat[3][3]; float difmat[3][3]; float imat[3][3]; /* Get the ebone premat and its inverse. */ ED_armature_ebone_to_mat3(ebone, premat); invert_m3_m3(imat, premat); /* Get the bone postmat. */ copy_m3_m4(postmat, curBone->arm_mat); mul_m3_m3m3(difmat, imat, postmat); #if 0 printf("Bone %s\n", curBone->name); print_m4("premat", premat); print_m4("postmat", postmat); print_m4("difmat", difmat); printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2]))); #endif curBone->roll = -atan2f(difmat[2][0], difmat[2][2]); /* and set restposition again */ BKE_armature_where_is_bone(curBone, curBone->parent, false); break; } } /* Recurse into children... */ armature_finalize_restpose(&curBone->childbase, editbonelist); } }