[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [43450] trunk/blender/source/blender: New pchan to pose matrices computes.

Campbell Barton ideasman42 at gmail.com
Tue Jan 17 15:06:23 CET 2012


Nice one! Just confirming this also fixes setting the pose bone matrix
from python.
so you can do...
obj.pose.bones['Bone'].matrix = mat

... which works as it should (not taking that bones constraints into
account of course).

Not being able to set the pose bones matrix was really crummy (though
it did work in most common case).

On Wed, Jan 18, 2012 at 12:30 AM, Bastien Montagne
<montagne29 at wanadoo.fr> wrote:
> 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 at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs



-- 
- Campbell


More information about the Bf-committers mailing list