Sketch Retargetting:
authorMartin Poirier <theeth@yahoo.com>
Sun, 2 Nov 2008 17:43:55 +0000 (17:43 +0000)
committerMartin Poirier <theeth@yahoo.com>
Sun, 2 Nov 2008 17:43:55 +0000 (17:43 +0000)
Use stroke normal to align roll of the retargetted bones.

Unlike stroke conversion, the final roll is not forced to point exactly to the normal. Rather, It tries to align the X or Z axis of the bones (whichever is closest) to the stroke normal. Forcing the roll can invert knees while this rightly only makes one of the joints rotation axis perpendicular.

source/blender/include/reeb.h
source/blender/src/editarmature_retarget.c
source/blender/src/editarmature_sketch.c

index d8146ff8d6deb0552a30c7c562cf09ae9e565943..5dcbad7e80b2188002b2a5e75e3f9010dbf069fa 100644 (file)
@@ -63,6 +63,7 @@ typedef struct EmbedBucket {
        float val;
        int       nv;
        float p[3];
+       float *no; /* if present, normal of the bucket */
 } EmbedBucket;
 
 typedef struct ReebNode {
index eef8c74382330cf41a8eb1e2726a302d75fb79be..34c5064e5f3f79d7dd9034d31f894b66b18083b4 100644 (file)
@@ -64,6 +64,7 @@
 #include "BIF_editarmature.h"
 #include "BIF_retarget.h"
 #include "BIF_space.h"
+#include "BIF_toolbox.h"
 
 #include "PIL_time.h"
 
@@ -161,30 +162,52 @@ void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3])
        VECCOPY(up_axis, mat[2]);
 }
 
-float getNewBoneRoll(EditBone *bone, float old_up_axis[3], float quat[4])
+float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float quat[4], float qroll[4], float aligned_axis[3])
 {
-       float mat[3][3];
-       float nor[3], up_axis[3], new_up_axis[3], vec[3];
-       float roll;
+       float nor[3], new_up_axis[3], x_axis[3], z_axis[3];
        
        VECCOPY(new_up_axis, old_up_axis);
        QuatMulVecf(quat, new_up_axis);
-
+       
        VecSubf(nor, bone->tail, bone->head);
        
-       vec_roll_to_mat3(nor, 0, mat);
-       VECCOPY(up_axis, mat[2]);
+       Crossf(x_axis, nor, aligned_axis);
+       Crossf(z_axis, x_axis, nor);
        
-       roll = NormalizedVecAngle2(new_up_axis, up_axis);
+       Normalize(new_up_axis);
+       Normalize(x_axis);
+       Normalize(z_axis);
        
-       Crossf(vec, up_axis, new_up_axis);
+       if (Inpf(new_up_axis, x_axis) < 0)
+       {
+               VecMulf(x_axis, -1);
+       }
        
-       if (Inpf(vec, nor) < 0)
+       if (Inpf(new_up_axis, z_axis) < 0)
+       {
+               VecMulf(z_axis, -1);
+       }
+       
+       if (NormalizedVecAngle2(x_axis, new_up_axis) < NormalizedVecAngle2(z_axis, new_up_axis))
+       {
+               RotationBetweenVectorsToQuat(qroll, new_up_axis, x_axis); /* set roll rotation quat */
+               return rollBoneToVector(bone, x_axis);
+       }
+       else
        {
-               roll = -roll;
+               RotationBetweenVectorsToQuat(qroll, new_up_axis, z_axis); /* set roll rotation quat */
+               return rollBoneToVector(bone, z_axis);
        }
+}
+
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float quat[4])
+{
+       float new_up_axis[3];
        
-       return roll;
+       VECCOPY(new_up_axis, old_up_axis);
+       QuatMulVecf(quat, new_up_axis);
+       
+       return rollBoneToVector(bone, new_up_axis);
 }
 
 /************************************ DESTRUCTORS ******************************************************/
@@ -1617,7 +1640,7 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f
        
        VecAddf(ctrl->bone->head, head, parent_offset); 
        VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset);
-       ctrl->bone->roll = getNewBoneRoll(ctrl->bone, ctrl->up_axis, qrot);
+       ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, qrot);
        
        ctrl->flag |= RIG_CTRL_DONE;
 
@@ -1632,7 +1655,7 @@ static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], f
 
 }
 
-static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3])
+static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float *up_axis)
 {
        EditBone *bone;
        RigControl *ctrl;
@@ -1652,6 +1675,22 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v
        
        RotationBetweenVectorsToQuat(qrot, v1, v2);
        
+       VECCOPY(bone->head, vec0);
+       VECCOPY(bone->tail, vec1);
+       
+       if (up_axis != NULL)
+       {
+               float qroll[4];
+
+               bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis);
+               
+               QuatMul(qrot, qrot, qroll);
+       }
+       else
+       {
+               bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot);
+       }
+
        for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next)
        {
                if (ctrl->link == bone)
@@ -1659,10 +1698,6 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v
                        repositionControl(rigg, ctrl, vec0, vec1, qrot, resize);
                }
        }
-       
-       VECCOPY(bone->head, vec0);
-       VECCOPY(bone->tail, vec1);
-       bone->roll = getNewBoneRoll(bone, edge->up_axis, qrot);
 }
 
 static RetargetMode detectArcRetargetMode(RigArc *arc);
@@ -2219,10 +2254,12 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                 edge;
                 edge = edge->next, i++)
        {
+               float *no = NULL;
                if (i < nb_joints)
                {
                        bucket = peekBucket(&iter, best_positions[i]);
                        vec1 = bucket->p;
+                       no = bucket->no;
                }
                else
                {
@@ -2231,7 +2268,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                
                if (edge->bone)
                {
-                       repositionBone(rigg, edge, vec0, vec1);
+                       repositionBone(rigg, edge, vec0, vec1, no);
                }
                
                vec0 = vec1;
@@ -2297,7 +2334,7 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
        for (edge = iarc->edges.first; edge; edge = edge->next)
        {
                float new_bone_length = edge->length / iarc->length * embedding_length;
-
+               float *no = NULL;
                float length = 0;
 
                while (bucket && new_bone_length > length)
@@ -2306,17 +2343,19 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
                        bucket = nextBucket(&iter);
                        previous_vec = vec1;
                        vec1 = bucket->p;
+                       no = bucket->no;
                }
                
                if (bucket == NULL)
                {
                        vec1 = node_end->p;
+                       no = NULL;
                }
 
                /* no need to move virtual edges (space between unconnected bones) */           
                if (edge->bone)
                {
-                       repositionBone(rigg, edge, vec0, vec1);
+                       repositionBone(rigg, edge, vec0, vec1, no);
                }
                
                vec0 = vec1;
@@ -2359,11 +2398,11 @@ void *exec_retargetArctoArc(void *param)
 
                if (testFlipArc(iarc, inode_start))
                {
-                       repositionBone(rigg, edge, earc->tail->p, earc->head->p);
+                       repositionBone(rigg, edge, earc->tail->p, earc->head->p, NULL);
                }
                else
                {
-                       repositionBone(rigg, edge, earc->head->p, earc->tail->p);
+                       repositionBone(rigg, edge, earc->head->p, earc->tail->p, NULL);
                }
        }
        else
@@ -2774,6 +2813,12 @@ void BIF_retargetArc(ReebArc *earc)
        
        template = armatureSelectedToGraph(ob, arm);
        
+       if (template->arcs.first == NULL)
+       {
+               error("No deforming bones selected");
+               return;
+       }
+       
        rigg = cloneRigGraph(template);
        
        iarc = rigg->arcs.first;
index 22173e469cfcd07432defa40d4517c0deabffc5f..f1ca1bd03878f8ee1613702c91a1b16039e17fb3 100644 (file)
@@ -380,6 +380,7 @@ ReebArc *strokeToArc(SK_Stroke *stk)
        for (i = 0; i < arc->bcount; i++)
        {
                VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
+               arc->buckets[i].no = stk->points[i + 1].no;
        }
        
        return arc;