== Snap Bones To Location in PoseMode ==

Now the Snap To Location (Shift S) tools for bones in pose-mode
work correctly. Previously, only one of these tools was implemented,
but it only worked in some cases.


This fixes item #4874 in Todo Tracker. Was patch #5012.
This commit is contained in:
Joshua Leung 2006-12-22 09:05:37 +00:00
parent e7d916b6e6
commit fcd3ea7875
5 changed files with 199 additions and 9 deletions

View File

@ -95,6 +95,11 @@ void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[]
void vec_roll_to_mat3(float *vec, float roll, float mat[][3]);
void mat3_to_vec_roll(float mat[][3], float *vec, float *roll);
/* Common Conversions Between Co-ordinate Spaces */
void armature_mat_world_to_pose(struct Object *ob, float inmat[][4], float outmat[][4]);
void armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], float outmat[][4]);
void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float *outloc);
/* Animation functions */
struct PoseTree *ik_tree_to_posetree(struct Object *ob, struct Bone *bone);
void solve_posetree(PoseTree *tree);

View File

@ -819,6 +819,66 @@ void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[]
Mat4CpyMat4(M_accumulatedMatrix, bone->arm_mat);
}
/* **************** Space to Space API ****************** */
/* Convert World-Space Matrix to Pose-Space Matrix */
void armature_mat_world_to_pose(Object *ob, float inmat[][4], float outmat[][4])
{
float obmat[4][4];
/* prevent crashes */
if (ob==NULL) return;
/* get inverse of (armature) object's matrix */
Mat4Invert(obmat, ob->obmat);
/* multiply given matrix by object's-inverse to find pose-space matrix */
Mat4MulMat4(outmat, obmat, inmat);
}
/* Convert Pose-Space Matrix to Bone-Space Matrix */
void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outmat[][4])
{
float pc_trans[4][4], inv_trans[4][4];
float pc_posemat[4][4], inv_posemat[4][4];
/* paranoia: prevent crashes with no pose-channel supplied */
if (pchan==NULL) return;
/* get the inverse matrix of the pchan's transforms */
LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, pchan->size);
Mat4Invert(inv_trans, pc_trans);
/* Remove the pchan's transforms from it's pose_mat.
* This should leave behind the effects of restpose +
* parenting + constraints
*/
Mat4MulMat4(pc_posemat, inv_trans, pchan->pose_mat);
/* get the inverse of the leftovers so that we can remove
* that component from the supplied matrix
*/
Mat4Invert(inv_posemat, pc_posemat);
/* get the new matrix */
Mat4MulMat4(outmat, inmat, inv_posemat);
}
/* Convert Pose-Space Location to Bone-Space Location */
void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc)
{
float xLocMat[4][4];
float nLocMat[4][4];
/* build matrix for location */
Mat4One(xLocMat);
VECCOPY(xLocMat[3], inloc);
/* get bone-space cursor matrix and extract location */
armature_mat_pose_to_bone(pchan, xLocMat, nLocMat);
VECCOPY(outloc, nLocMat[3]);
}
/* **************** The new & simple (but OK!) armature evaluation ********* */

View File

@ -949,6 +949,7 @@ Normalise2(
);
void LocEulSizeToMat4(float mat[][4], float loc[3], float eul[3], float size[3]);
void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3]);
void tubemap(float x, float y, float z, float *u, float *v);
void spheremap(float x, float y, float z, float *u, float *v);

View File

@ -3266,3 +3266,17 @@ void LocEulSizeToMat4(float mat[][4], float loc[3], float eul[3], float size[3])
mat[3][1] = loc[1];
mat[3][2] = loc[2];
}
/* make a 4x4 matrix out of 3 transform components */
void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3])
{
float eul[3];
/* convert quaternion component to euler
* NOTE: not as good as using quat directly. Todo for later.
*/
QuatToEul(quat, eul);
/* make into matrix using exisiting code */
LocEulSizeToMat4(mat, loc, eul, size);
}

View File

@ -1103,7 +1103,52 @@ void snap_sel_to_grid()
if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
ob= base->object;
if(ob->flag & OB_POSEMODE) {
; // todo
bPoseChannel *pchan;
bArmature *arm= ob->data;
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if(pchan->bone->flag & BONE_SELECTED) {
if(pchan->bone->layer & arm->layer) {
if (pchan->parent==NULL) {
float dLoc[3], oldLoc[3], nLoc[3];
/* get nearest grid point to snap to */
VECCOPY(nLoc, pchan->pose_head);
vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf));
vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf));
vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf));
/* adjust location */
VecSubf(dLoc, vec, nLoc);
VECCOPY(oldLoc, pchan->loc);
VecAddf(pchan->loc, oldLoc, dLoc);
}
else if((pchan->bone->flag & BONE_CONNECTED)==0) {
float vecN[3], nLoc[3];
float dLoc[3], oldLoc[3];
/* get nearest grid point to snap to */
VECCOPY(nLoc, pchan->pose_mat[3]);
vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf));
vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf));
vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf));
/* get bone-space location of grid point */
armature_loc_pose_to_bone(pchan, vec, vecN);
/* adjust location */
VECCOPY(oldLoc, pchan->loc);
VecSubf(dLoc, vecN, oldLoc);
VecAddf(pchan->loc, oldLoc, dLoc);
}
/* if the bone has a parent and is connected to the parent,
* don't do anything - will break chain unless we do auto-ik.
*/
}
}
}
ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
ob->recalc |= OB_RECALC_DATA;
}
else {
ob->recalc |= OB_RECALC_OB;
@ -1196,10 +1241,26 @@ void snap_sel_to_curs()
if(pchan->bone->flag & BONE_SELECTED) {
if(pchan->bone->layer & arm->layer) {
if(pchan->parent==NULL) {
/* this is wrong... lazy! */
VECCOPY(pchan->loc, cursp);
float dLoc[3], oldLoc[3];
VecSubf(dLoc, cursp, pchan->pose_head);
VECCOPY(oldLoc, pchan->loc);
VecAddf(pchan->loc, oldLoc, dLoc);
}
/* else todo... */
else if((pchan->bone->flag & BONE_CONNECTED)==0) {
float curspn[3], dLoc[3], oldLoc[3];
/* get location of cursor in bone-space */
armature_loc_pose_to_bone(pchan, cursp, curspn);
/* calculate new position */
VECCOPY(oldLoc, pchan->loc);
VecSubf(dLoc, curspn, oldLoc);
VecAddf(pchan->loc, oldLoc, dLoc);
}
/* if the bone has a parent and is connected to the parent,
* don't do anything - will break chain unless we do auto-ik.
*/
}
}
}
@ -1459,10 +1520,29 @@ void snap_to_center()
base= (G.scene->base.first);
while(base) {
if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
VECCOPY(vec, base->object->obmat[3]);
VecAddf(centroid, centroid, vec);
DO_MINMAX(vec, min, max);
count++;
ob= base->object;
if(ob->flag & OB_POSEMODE) {
bPoseChannel *pchan;
bArmature *arm= ob->data;
for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
if(pchan->bone->flag & BONE_SELECTED) {
if(pchan->bone->layer & arm->layer) {
VECCOPY(vec, pchan->pose_mat[3]);
VecAddf(centroid, centroid, vec);
DO_MINMAX(vec, min, max);
count++;
}
}
}
}
else {
/* not armature bones (i.e. objects) */
VECCOPY(vec, base->object->obmat[3]);
VecAddf(centroid, centroid, vec);
DO_MINMAX(vec, min, max);
count++;
}
}
base= base->next;
}
@ -1514,7 +1594,37 @@ void snap_to_center()
if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
ob= base->object;
if(ob->flag & OB_POSEMODE) {
; // todo
bPoseChannel *pchan;
bArmature *arm= ob->data;
for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
if(pchan->bone->flag & BONE_SELECTED) {
if(pchan->bone->layer & arm->layer) {
if(pchan->parent==NULL) {
float dLoc[3], oldLoc[3];
VecSubf(dLoc, snaploc, pchan->pose_head);
VECCOPY(oldLoc, pchan->loc);
VecAddf(pchan->loc, oldLoc, dLoc);
}
else if((pchan->bone->flag & BONE_CONNECTED)==0) {
float dLoc[3], oldLoc[3];
/* get location of cursor in bone-space */
armature_loc_pose_to_bone(pchan, snaploc, vec);
/* calculate new position */
VECCOPY(oldLoc, pchan->loc);
VecSubf(dLoc, vec, oldLoc);
VecAddf(pchan->loc, oldLoc, dLoc);
}
/* if the bone has a parent and is connected to the parent,
* don't do anything - will break chain unless we do auto-ik.
*/
}
}
}
ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
ob->recalc |= OB_RECALC_DATA;
}
else {
ob->recalc |= OB_RECALC_OB;