Fix bones moving when changing between editmode and posemode.

Patch #25901 by Tobias Oelgarte.

Bone transformations would be converted back and forth between different
representations when changing modes, which due to numerical errors could
lead to bone transformations slowly changing as you edit the armature.

Now the editmode head, tail and roll values are stored in bones and used
directly when entering edit mode. Head and tail were already there but
now we ensure they are the exact same value, roll was not yet there, so
we have a version patch for it.

The sub version was incremented to 1 for the version patch.
This commit is contained in:
Brecht Van Lommel 2011-02-05 13:19:14 +00:00
parent fe99f35210
commit 90cf78eb54
5 changed files with 58 additions and 37 deletions

@ -45,7 +45,7 @@ struct Scene;
struct Main;
#define BLENDER_VERSION 256
#define BLENDER_SUBVERSION 0
#define BLENDER_SUBVERSION 1
#define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0

@ -1401,13 +1401,6 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone)
VECCOPY(bone->arm_mat[3], bone->head);
}
/* head */
VECCOPY(bone->arm_head, bone->arm_mat[3]);
/* tail is in current local coord system */
VECCOPY(vec, bone->arm_mat[1]);
mul_v3_fl(vec, bone->length);
add_v3_v3v3(bone->arm_tail, bone->arm_head, vec);
/* and the kiddies */
prevbone= bone;
for(bone= bone->childbase.first; bone; bone= bone->next) {

@ -5746,6 +5746,23 @@ static int map_223_keybd_code_to_224_keybd_code(int code)
}
}
static void do_version_bone_head_tail_237(Bone *bone)
{
Bone *child;
float vec[3];
/* head */
copy_v3_v3(bone->arm_head, bone->arm_mat[3]);
/* tail is in current local coord system */
copy_v3_v3(vec, bone->arm_mat[1]);
mul_v3_fl(vec, bone->length);
add_v3_v3v3(bone->arm_tail, bone->arm_head, vec);
for(child= bone->childbase.first; child; child= child->next)
do_version_bone_head_tail_237(child);
}
static void bone_version_238(ListBase *lb)
{
Bone *bone;
@ -6655,6 +6672,19 @@ static void do_versions_seq_unique_name_all_strips(
}
}
static void do_version_bone_roll_256(Bone *bone)
{
Bone *child;
float submat[3][3];
copy_m3_m4(submat, bone->arm_mat);
mat3_to_vec_roll(submat, 0, &bone->arm_roll);
for(child = bone->childbase.first; child; child = child->next)
do_version_bone_roll_256(child);
}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@ -7964,10 +7994,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
bArmature *arm;
bConstraint *con;
Object *ob;
Bone *bone;
// armature recode checks
for(arm= main->armature.first; arm; arm= arm->id.next) {
where_is_armature(arm);
for(bone= arm->bonebase.first; bone; bone= bone->next)
do_version_bone_head_tail_237(bone);
}
for(ob= main->object.first; ob; ob= ob->id.next) {
if(ob->parent) {
@ -11285,6 +11319,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 1)) {
/* fix for bones that didn't have arm_roll before */
bArmature* arm;
Bone* bone;
for (arm = main->armature.first; arm; arm = arm->id.next)
for (bone = arm->bonebase.first; bone; bone = bone->next)
do_version_bone_roll_256(bone);
}
/* put compatibility code here until next subversion bump */
{

@ -246,11 +246,6 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
EditBone *eBoneAct= NULL;
EditBone *eBoneTest= NULL;
Bone *curBone;
float delta[3];
float premat[3][3];
float postmat[3][3];
float imat[3][3];
float difmat[3][3];
for (curBone=bones->first; curBone; curBone=curBone->next) {
eBone= MEM_callocN(sizeof(EditBone), "make_editbone");
@ -291,20 +286,8 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
}
copy_v3_v3(eBone->head, curBone->arm_head);
copy_v3_v3(eBone->tail, curBone->arm_tail);
eBone->roll= 0.0f;
/* roll fixing */
sub_v3_v3v3(delta, eBone->tail, eBone->head);
vec_roll_to_mat3(delta, 0.0f, postmat);
copy_m3_m4(premat, curBone->arm_mat);
invert_m3_m3(imat, postmat);
mul_m3_m3m3(difmat, imat, premat);
eBone->roll = (float)atan2(difmat[2][0], difmat[2][2]);
copy_v3_v3(eBone->tail, curBone->arm_tail);
eBone->roll = curBone->arm_roll;
/* rest of stuff copy */
eBone->length= curBone->length;
@ -420,8 +403,10 @@ void ED_armature_from_edit(Object *obedit)
eBone->temp= newBone; /* Associate the real Bones with the EditBones */
BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
memcpy(newBone->head, eBone->head, sizeof(newBone->head));
memcpy(newBone->tail, eBone->tail, sizeof(newBone->tail));
copy_v3_v3(newBone->arm_head, eBone->head);
copy_v3_v3(newBone->arm_tail, eBone->tail);
newBone->arm_roll = eBone->roll;
newBone->flag= eBone->flag;
if (eBone == arm->act_edbone) {
@ -456,7 +441,6 @@ void ED_armature_from_edit(Object *obedit)
BLI_addtail(&newBone->parent->childbase, newBone);
{
float M_boneRest[3][3];
float M_parentRest[3][3];
float iM_parentRest[3][3];
float delta[3];
@ -465,10 +449,6 @@ void ED_armature_from_edit(Object *obedit)
sub_v3_v3v3(delta, eBone->parent->tail, eBone->parent->head);
vec_roll_to_mat3(delta, eBone->parent->roll, M_parentRest);
/* Get this bone's matrix (rotation only) */
sub_v3_v3v3(delta, eBone->tail, eBone->head);
vec_roll_to_mat3(delta, eBone->roll, M_boneRest);
/* Invert the parent matrix */
invert_m3_m3(iM_parentRest, M_parentRest);
@ -481,8 +461,11 @@ void ED_armature_from_edit(Object *obedit)
}
}
/* ...otherwise add this bone to the armature's bonebase */
else
else {
copy_v3_v3(newBone->head, eBone->head);
copy_v3_v3(newBone->tail, eBone->tail);
BLI_addtail(&arm->bonebase, newBone);
}
}
/* Make a pass through the new armature to fix rolling */

@ -57,8 +57,9 @@ typedef struct Bone {
int flag;
float arm_head[3];
float arm_tail[3]; /* head/tail and roll in Armature Space (rest pos) */
float arm_tail[3]; /* head/tail in Armature Space (rest pos) */
float arm_mat[4][4]; /* matrix: (bonemat(b)+head(b))*arm_mat(b-1), rest pos*/
float arm_roll; /* roll in Armature Space (rest pos) */
float dist, weight; /* dist, weight: for non-deformgroup deforms */
float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */
@ -68,7 +69,7 @@ typedef struct Bone {
float size[3]; /* patch for upward compat, UNUSED! */
int layer; /* layers that bone appears on */
short segments; /* for B-bones */
short pad[3];
short pad[1];
} Bone;
typedef struct bArmature {