Revision: 43450
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=43450
Author:   mont29
Date:     2012-01-17 13:30:20 +0000 (Tue, 17 Jan 2012)
Log Message:
-----------
New pchan to pose matrices computes. Fixes [#27898] Bone snap to cursor fails 
and [#29461] Selection-to-Cursor works strange with bones with TrackTo 
constraint. Also fixes some inconsistant behavior of no Inherit Rotation/Scale 
options.

WARNING: This commits modifies how translated unconnected child bones with *no 
Inherit Rotation option* are positionned. This means that if you open a 
posed/animated armature using such (corner-case) setup, you'll have to adjust 
manually the locations of such bones: now, disabling Inherit Rotation/Scale 
will no more move the bone, only affecting its rotation/scale.

Many thanks to Bassam Kurdali (slikdigit) for his advices and tests of the 
patch!

-----

Dev notes?\194?\160: the pchan_to_pose_mat() func was added to BKE_armature.h, 
which computes two matrices to get the pose transformations (pchan) of the bone 
directly in pose (i.e. armature object) space. The first matrix is the 
rotation/scaling parts, the second one is for location.

That new function is used by (hence deduplicating and simplifying their code):
* The pose evaluation code (where_is_pose_bone()).
* The interactive transformation code (add_pose_transdata(), in 
transform_conversion.c).
* The snap to cursor/grid code (through 
armature_loc_pose_to_bone()/armature_mat_pose_to_bone()).

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_armature.h
    trunk/blender/source/blender/blenkernel/intern/armature.c
    trunk/blender/source/blender/editors/space_view3d/view3d_snap.c
    trunk/blender/source/blender/editors/transform/transform_conversions.c

Modified: trunk/blender/source/blender/blenkernel/BKE_armature.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_armature.h      2012-01-17 
13:26:59 UTC (rev 43449)
+++ trunk/blender/source/blender/blenkernel/BKE_armature.h      2012-01-17 
13:30:20 UTC (rev 43450)
@@ -114,6 +114,10 @@
 void pchan_to_mat4(struct bPoseChannel *pchan, float chan_mat[4][4]);
 void pchan_calc_mat(struct bPoseChannel *pchan);
 
+/* Get the "pchan to pose" transform matrix. These matrices apply the effects 
of
+ * HINGE/NO_SCALE/NO_LOCAL_LOCATION options over the pchan loc/rot/scale 
transformations. */
+void pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[][4], 
float loc_mat[][4]);
+
 /* Rotation Mode Conversions - Used for PoseChannels + Objects... */
 void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], 
float *angle, short oldMode, short newMode);
 

Modified: trunk/blender/source/blender/blenkernel/intern/armature.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/armature.c   2012-01-17 
13:26:59 UTC (rev 43449)
+++ trunk/blender/source/blender/blenkernel/intern/armature.c   2012-01-17 
13:30:20 UTC (rev 43450)
@@ -590,7 +590,7 @@
 /* ************ Armature Deform ******************* */
 
 typedef struct bPoseChanDeform {
-       Mat4            *b_bone_mats;   
+       Mat4            *b_bone_mats;
        DualQuat        *dual_quat;
        DualQuat        *b_bone_dual_quats;
 } bPoseChanDeform;
@@ -1123,66 +1123,183 @@
        copy_v3_v3(outloc, nLocMat[3]);
 }
 
-/* Convert Pose-Space Matrix to Bone-Space Matrix 
- * NOTE: this cannot be used to convert to pose-space transforms of the 
supplied
- *             pose-channel into its local space (i.e. 'visual'-keyframing)
+/* Construct the matrices (rot/scale and loc) to apply the PoseChannels into 
the armature (object) space.
+ * I.e. (roughly) the "pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b)" 
in the
+ *     pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * 
chan_mat(b)
+ * ...function.
+ *
+ * This allows to get the transformations of a bone in its object space, 
*before* constraints (and IK)
+ * get applied (used by pose evaluation code).
+ * And reverse: to find pchan transformations needed to place a bone at a 
given loc/rot/scale
+ * in object space (used by interactive transform, and snapping code).
+ *
+ * Note that, with the HINGE/NO_SCALE/NO_LOCAL_LOCATION options, the location 
matrix
+ * will differ from the rotation/scale matrix...
+ *
+ * NOTE: This cannot be used to convert to pose-space transforms of the 
supplied
+ *       pose-channel into its local space (i.e. 'visual'-keyframing).
+ *       (note: I don't understand that, so I keep it :p --mont29).
  */
-void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float 
outmat[][4])
+void pchan_to_pose_mat(bPoseChannel *pchan, float rotscale_mat[][4], float 
loc_mat[][4])
 {
-       float pc_trans[4][4], inv_trans[4][4];
-       float pc_posemat[4][4], inv_posemat[4][4];
-       float pose_mat[4][4];
+       Bone *bone, *parbone;
+       bPoseChannel *parchan;
 
-       /* paranoia: prevent crashes with no pose-channel supplied */
-       if (pchan==NULL) return;
+       /* set up variables for quicker access below */
+       bone= pchan->bone;
+       parbone= bone->parent;
+       parchan= pchan->parent;
 
-       /* default flag */
-       if((pchan->bone->flag & BONE_NO_LOCAL_LOCATION)==0) {
-               /* get the inverse matrix of the pchan's transforms */
-               switch(pchan->rotmode) {
-               case ROT_MODE_QUAT:
-                       loc_quat_size_to_mat4(pc_trans, pchan->loc, 
pchan->quat, pchan->size);
-                       break;
-               case ROT_MODE_AXISANGLE:
-                       loc_axisangle_size_to_mat4(pc_trans, pchan->loc, 
pchan->rotAxis, pchan->rotAngle, pchan->size);
-                       break;
-               default: /* euler */
-                       loc_eul_size_to_mat4(pc_trans, pchan->loc, pchan->eul, 
pchan->size);
+       if(parchan) {
+               float offs_bone[4][4]; /* yoffs(b-1) + root(b) + bonemat(b). */
+
+               /* Bone transform itself. */
+               copy_m4_m3(offs_bone, bone->bone_mat);
+
+               /* The bone's root offset (is in the parent's coordinate 
system). */
+               copy_v3_v3(offs_bone[3], bone->head);
+
+               /* Get the length translation of parent (length along y axis). 
*/
+               offs_bone[3][1]+= parbone->length;
+
+               /* Compose the rotscale matrix for this bone. */
+               if((bone->flag & BONE_HINGE) && (bone->flag & BONE_NO_SCALE)) {
+                       /* Parent rest rotation and scale. */
+                       mult_m4_m4m4(rotscale_mat, parbone->arm_mat, offs_bone);
                }
+               else if(bone->flag & BONE_HINGE) {
+                       /* Parent rest rotation and pose scale. */
+                       float tmat[4][4], tscale[3];
 
-               copy_m4_m4(pose_mat, pchan->pose_mat);
+                       /* Extract the scale of the parent pose matrix. */
+                       mat4_to_size(tscale, parchan->pose_mat);
+                       size_to_mat4(tmat, tscale);
+
+                       /* Applies the parent pose scale to the rest matrix. */
+                       mult_m4_m4m4(tmat, tmat, parbone->arm_mat);
+
+                       mult_m4_m4m4(rotscale_mat, tmat, offs_bone);
+               }
+               else if(bone->flag & BONE_NO_SCALE) {
+                       /* Parent pose rotation and rest scale (i.e. no 
scaling). */
+                       float tmat[4][4];
+                       copy_m4_m4(tmat, parchan->pose_mat);
+                       normalize_m4(tmat);
+                       mult_m4_m4m4(rotscale_mat, tmat, offs_bone);
+               }
+               else
+                       mult_m4_m4m4(rotscale_mat, parchan->pose_mat, 
offs_bone);
+
+# if 1
+               /* Compose the loc matrix for this bone. */
+               /* NOTE: That version deos not modify bone's loc when 
HINGE/NO_SCALE options are set. */
+
+               /* In this case, use the object's space *orientation*. */
+               if(bone->flag & BONE_NO_LOCAL_LOCATION) {
+                       /* XXX I'm sure that code can be simplified! */
+                       float bone_loc[4][4], bone_rotscale[3][3], tmat4[4][4], 
tmat3[3][3];
+                       unit_m4(bone_loc);
+                       unit_m4(loc_mat);
+                       unit_m4(tmat4);
+
+                       mul_v3_m4v3(bone_loc[3], parchan->pose_mat, 
offs_bone[3]);
+
+                       unit_m3(bone_rotscale);
+                       copy_m3_m4(tmat3, parchan->pose_mat);
+                       mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale);
+
+                       copy_m4_m3(tmat4, bone_rotscale);
+                       mult_m4_m4m4(loc_mat, bone_loc, tmat4);
+               }
+               /* Those flags do not affect position, use plain parent 
transform space! */
+               else if(bone->flag & (BONE_HINGE|BONE_NO_SCALE)) {
+                       mult_m4_m4m4(loc_mat, parchan->pose_mat, offs_bone);
+               }
+               /* Else (i.e. default, usual case), just use the same matrix 
for rotation/scaling, and location. */
+               else
+                       copy_m4_m4(loc_mat, rotscale_mat);
+# endif
+# if 0
+               /* Compose the loc matrix for this bone. */
+               /* NOTE: That version modifies bone's loc when HINGE/NO_SCALE 
options are set. */
+
+               /* In these cases we need to compute location separately */
+               if(bone->flag & 
(BONE_HINGE|BONE_NO_SCALE|BONE_NO_LOCAL_LOCATION)) {
+                       float bone_loc[4][4], bone_rotscale[3][3], tmat4[4][4], 
tmat3[3][3];
+                       unit_m4(bone_loc);
+                       unit_m4(loc_mat);
+                       unit_m4(tmat4);
+
+                       mul_v3_m4v3(bone_loc[3], parchan->pose_mat, 
offs_bone[3]);
+
+                       /* "No local location" is not transformed by bone 
matrix. */
+                       /* This only affects orientations (rotations), as scale 
is always 1.0 here. */
+                       if(bone->flag & BONE_NO_LOCAL_LOCATION)
+                               unit_m3(bone_rotscale);
+                       else
+                               /* We could also use bone->bone_mat directly, 
here... */
+                               copy_m3_m4(bone_rotscale, offs_bone);
+
+                       if(bone->flag & BONE_HINGE) {
+                               copy_m3_m4(tmat3, parbone->arm_mat);
+                               /* for hinge-only, we use armature *rotation*, 
but pose mat *scale*! */
+                               if(!(bone->flag & BONE_NO_SCALE)) {
+                                       float size[3], tsmat[3][3];
+                                       mat4_to_size(size, parchan->pose_mat);
+                                       size_to_mat3(tsmat, size);
+                                       mul_m3_m3m3(tmat3, tsmat, tmat3);
+                               }
+                               mul_m3_m3m3(bone_rotscale, tmat3, 
bone_rotscale);
+                       }
+                       else if(bone->flag & BONE_NO_SCALE) {
+                               /* For no-scale only, normalized parent pose 
mat is enough! */
+                               copy_m3_m4(tmat3, parchan->pose_mat);
+                               normalize_m3(tmat3);
+                               mul_m3_m3m3(bone_rotscale, tmat3, 
bone_rotscale);
+                       }
+                       /* NO_LOCAL_LOCATION only. */
+                       else {
+                               copy_m3_m4(tmat3, parchan->pose_mat);
+                               mul_m3_m3m3(bone_rotscale, tmat3, 
bone_rotscale);
+                       }
+
+                       copy_m4_m3(tmat4, bone_rotscale);
+                       mult_m4_m4m4(loc_mat, bone_loc, tmat4);
+               }
+               /* Else, just use the same matrix for rotation/scaling, and 
location. */
+               else
+                       copy_m4_m4(loc_mat, rotscale_mat);
+# endif
        }
+       /* Root bones. */
        else {
-               /* local location, this is not default, different calculation
-                * note: only tested for location with pose bone snapping.
-                * If this is not useful in other cases the 
BONE_NO_LOCAL_LOCATION
-                * case may have to be split into its own function. */
-               unit_m4(pc_trans);
-               copy_v3_v3(pc_trans[3], pchan->loc);
+               /* Rotation/scaling. */
+               copy_m4_m4(rotscale_mat, pchan->bone->arm_mat);
+               /* Translation. */
+               if(pchan->bone->flag & BONE_NO_LOCAL_LOCATION) {
+                       /* Translation of arm_mat, without the rotation. */
+                       unit_m4(loc_mat);
+                       copy_v3_v3(loc_mat[3], pchan->bone->arm_mat[3]);
+               }
+               else
+                       copy_m4_m4(loc_mat, rotscale_mat);
+       }
+}
 
-               /* use parents rotation/scale space + own absolute position */
-               if(pchan->parent)       copy_m4_m4(pose_mat, 
pchan->parent->pose_mat);
-               else                            unit_m4(pose_mat);
+/* Convert Pose-Space Matrix to Bone-Space Matrix.
+ * NOTE: this cannot be used to convert to pose-space transforms of the 
supplied
+ *       pose-channel into its local space (i.e. 'visual'-keyframing)
+ */
+void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float 
outmat[][4])
+{
+       float rotscale_mat[4][4], loc_mat[4][4];
 
-               copy_v3_v3(pose_mat[3], pchan->pose_mat[3]);
-       }
+       pchan_to_pose_mat(pchan, rotscale_mat, loc_mat);
+       invert_m4(rotscale_mat);
+       invert_m4(loc_mat);
 
-
-       invert_m4_m4(inv_trans, pc_trans);
-       
-       /* Remove the pchan's transforms from it's pose_mat.
-        * This should leave behind the effects of restpose + 
-        * parenting + constraints
-        */
-       mult_m4_m4m4(pc_posemat, pose_mat, inv_trans);
-       
-       /* get the inverse of the leftovers so that we can remove 
-        * that component from the supplied matrix
-        */
-       invert_m4_m4(inv_posemat, pc_posemat);
-       
-       /* get the new matrix */
-       mult_m4_m4m4(outmat, inv_posemat, inmat);
+       mult_m4_m4m4(outmat, rotscale_mat, inmat);
+       mul_v3_m4v3(outmat[3], loc_mat, inmat[3]);
 }
 
 /* Convert Pose-Space Location to Bone-Space Location
@@ -2263,98 +2380,30 @@
  */
 void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float 
ctime, int do_extra)
 {
-       Bone *bone, *parbone;
-       bPoseChannel *parchan;
-       float vec[3];
-       
-       /* set up variables for quicker access below */
-       bone= pchan->bone;
-       parbone= bone->parent;
-       parchan= pchan->parent;
-       
-       /* this gives a chan_mat with actions (ipos) results */

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to