Example #1
0
/* 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);
	}
}
Example #2
0
/* 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);
	}
}