diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-11-05 21:44:42 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-11-05 21:44:42 +0300 |
commit | 63c5dbe745c951472cc196b4d7a5e10ad1f84670 (patch) | |
tree | 8fd6660fe0362a156d062269fdd422b27a899f34 | |
parent | 7d70dd98d625e4f08a750877e4242032bac38305 (diff) |
Bugfix:
B-bones didn't work well with non-uniform scaling applied to them.
The code to solve this is not too pretty, but don't know how to do
it simpler, and at least it makes that stretchy spine work.
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index e362bdbd2dd..40f4ae7298e 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -411,12 +411,31 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) Mat4 *result_array= (rest)? bbone_rest_array: bbone_array; bPoseChannel *next, *prev; Bone *bone= pchan->bone; - float h1[3], h2[3], length, hlength1, hlength2, roll1=0.0f, roll2; - float mat3[3][3], imat[4][4]; + float h1[3], h2[3], scale[3], length, hlength1, hlength2, roll1=0.0f, roll2; + float mat3[3][3], imat[4][4], posemat[4][4], scalemat[4][4], iscalemat[4][4]; float data[MAX_BBONE_SUBDIV+1][4], *fp; - int a; - + int a, doscale= 0; + length= bone->length; + + if(!rest) { + /* check if we need to take non-uniform bone scaling into account */ + scale[0]= VecLength(pchan->pose_mat[0]); + scale[1]= VecLength(pchan->pose_mat[1]); + scale[2]= VecLength(pchan->pose_mat[2]); + + if(fabs(scale[0] - scale[1]) > 1e-6f || fabs(scale[1] - scale[2]) > 1e-6f) { + Mat4One(scalemat); + scalemat[0][0]= scale[0]; + scalemat[1][1]= scale[1]; + scalemat[2][2]= scale[2]; + Mat4Invert(iscalemat, scalemat); + + length *= scale[1]; + doscale = 1; + } + } + hlength1= bone->ease1*length*0.390464f; // 0.5*sqrt(2)*kappa, the handle length for near-perfect circles hlength2= bone->ease2*length*0.390464f; @@ -432,8 +451,14 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) first point = (0,0,0) last point = (0, length, 0) */ - if(rest) + if(rest) { Mat4Invert(imat, pchan->bone->arm_mat); + } + else if(doscale) { + Mat4CpyMat4(posemat, pchan->pose_mat); + Mat4Ortho(posemat); + Mat4Invert(imat, posemat); + } else Mat4Invert(imat, pchan->pose_mat); @@ -527,8 +552,15 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) for(a=0, fp= data[0]; a<bone->segments; a++, fp+=4) { VecSubf(h1, fp+4, fp); vec_roll_to_mat3(h1, fp[3], mat3); // fp[3] is roll + Mat4CpyMat3(result_array[a].mat, mat3); VECCOPY(result_array[a].mat[3], fp); + + if(doscale) { + /* correct for scaling when this matrix is used in scaled space */ + Mat4MulSerie(result_array[a].mat, iscalemat, result_array[a].mat, + scalemat, NULL, NULL, NULL, NULL, NULL); + } } return result_array; |