Added shrinkwrap as a constraint.
authorAndre Susano Pinto <andresusanopinto@gmail.com>
Sun, 3 Aug 2008 02:02:15 +0000 (02:02 +0000)
committerAndre Susano Pinto <andresusanopinto@gmail.com>
Sun, 3 Aug 2008 02:02:15 +0000 (02:02 +0000)
All modes are available:
nearest surface
nearest vertex
normal projection (along X,Y or Z axis)

source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/src/buttons_object.c

index 93ba30f8c9b9fb694cb406a02085fe47b4d307c4..fdb272171bf7cde17222cf1484ce6f20e82d357f 100644 (file)
@@ -3253,6 +3253,7 @@ static int shrinkwrap_get_tars (bConstraint *con, ListBase *list)
        return 0;
 }
 
+
 static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocopy)
 {
        if (con && list) {
@@ -3263,21 +3264,18 @@ static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocop
        }
 }
 
-static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
-{
-       if (ct)
-               Mat4One(ct->matrix);
-}
 
-static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
 {
        bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
-       bConstraintTarget *ct = targets->first;
        
+       if (ct)
+               Mat4CpyMat4(ct->matrix, cob->startmat);
+
        if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) )
        {
                float co[3] = {0.0f, 0.0f, 0.0f};
-               float no[3] = {0.0f, 0.0f, 1.0f};
+               float no[3] = {0.0f, 0.0f, 0.0f};
                float dist;
 
                SpaceTransform transform;
@@ -3292,23 +3290,35 @@ static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
                memset( &treeData, 0, sizeof(treeData) );
 
                nearest.index = -1;
-               nearest.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it
+               nearest.dist = FLT_MAX;
 
-               if(target != NULL)
+               hit.index = -1;
+               hit.dist = 100000.0f;  //TODO should use FLT_MAX.. but normal projection doenst yet supports it
+
+               switch(scon->normalAxis)
                {
+                       case UP_X: no[0] = 1.0f; break;
+                       case UP_Y: no[1] = 1.0f; break;
+                       case UP_Z: no[2] = 1.0f; break;
+               }
 
-                       space_transform_from_matrixs(&transform, cob->matrix, ct->matrix);
+               if(target != NULL)
+               {
 
-                       space_transform_apply(&transform, co);
-                       space_transform_apply_normal(&transform, no);
+                       space_transform_from_matrixs(&transform, cob->startmat, ct->tar->obmat);
 
+                       //Normal projection applies the transform later
+                       if(scon->shrinkType != MOD_SHRINKWRAP_NORMAL)
+                       {
+                               space_transform_apply(&transform, co);
+                               space_transform_apply_normal(&transform, no);
+                       }
 
                        switch(scon->shrinkType)
                        {
                                case MOD_SHRINKWRAP_NEAREST_SURFACE:
                                        if(bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6) == NULL) return;
                                        BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
-                                       VECCOPY(co, nearest.co);
                                        
                                        dist = VecLenf(co, nearest.co);
                                        VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
@@ -3317,7 +3327,6 @@ static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
                                case MOD_SHRINKWRAP_NEAREST_VERTEX:
                                        if(bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6) == NULL) return;
                                        BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
-                                       VECCOPY(co, nearest.co);
 
                                        dist = VecLenf(co, nearest.co);
                                        VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
@@ -3325,27 +3334,43 @@ static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
 
                                case MOD_SHRINKWRAP_NORMAL:
                                        if(bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6) == NULL) return;
+
                                        if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
-                                               return;
+                                       {
+                                               if(treeData.tree)
+                                                       BLI_bvhtree_free(treeData.tree);
 
+                                               target->release(target);
+
+                                               return;
+                                       }
                                        VECCOPY(co, hit.co);
                                break;
                        }
 
-                       space_transform_invert(&transform, co);
-                       VECADD(cob->matrix[3], cob->matrix[3], co);
-
-
                        if(treeData.tree)
                                BLI_bvhtree_free(treeData.tree);
 
                        target->release(target);
-               }
-               
 
+                       if(scon->shrinkType != MOD_SHRINKWRAP_NORMAL)
+                       {
+                               space_transform_invert(&transform, co);
+                       }
+                       VECADD(ct->matrix[3], ct->matrix[3], co);
+               }
        }
 }
 
+static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct))
+               Mat4CpyMat4(cob->matrix, ct->matrix);
+}
+
 static bConstraintTypeInfo CTI_SHRINKWRAP = {
        CONSTRAINT_TYPE_SHRINKWRAP, /* type */
        sizeof(bShrinkwrapConstraint), /* size */
index ad19cde3c9ba963ad5700bd4cdb848b396056286..70ead610cc3649c94a80e534e50be9025089eab9 100644 (file)
@@ -1819,6 +1819,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data->tar = newlibadr(fd, id->lib, data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_SHRINKWRAP:
+                       {
+                               bShrinkwrapConstraint *data;
+                               data= ((bShrinkwrapConstraint*)con->data);
+                               data->target = newlibadr(fd, id->lib, data->target);
+                       }
+                       break;
                case CONSTRAINT_TYPE_NULL:
                        break;
                }
@@ -8351,6 +8358,11 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                                expand_doit(fd, mainvar, data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_SHRINKWRAP:
+                       {
+                               bShrinkwrapConstraint *data = (bShrinkwrapConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->target);
+                       }
                default:
                        break;
                }
index e78855b8de69065df36c7c3cd06fc4d1ef88dc47..7b686106ae5751684aebeb66c9830cfe04d5182a 100644 (file)
@@ -321,9 +321,12 @@ typedef struct bShrinkwrapConstraint {
        Object          *target;
        float           dist;                   /* distance to kept from target */
        short           shrinkType;             /* shrink type (look on MOD shrinkwrap for values) */
-       short           pad[5];
+       char            normalAxis;             /* axis to project over UP_X, UP_Y, UP_Z */
+       char            pad[9];
 } bShrinkwrapConstraint;
 
+#define SHRINKWRAP
+
 /* ------------------------------------------ */
 
 /* bConstraint->type 
index c2643aa479b9437e2e53b7ada0f855bdf6b6fc42..efa82e03d5fc076af62afc25b02e42cc80de2e9e 100644 (file)
@@ -1743,10 +1743,32 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                case CONSTRAINT_TYPE_SHRINKWRAP:
                        {
                                bShrinkwrapConstraint *data = con->data;
+                               char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|normal projection %x1|nearest vertex %x2";
 
-                               height = 44;
-                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->target, "Target Object");
-                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "dist", *xco+120, *yco-44, 135, 18, &data->dist, 0.0f, 100.0f, 1.0f, 0.0f, "Distance to target"); 
+                               height = 60;
+                               if(data->shrinkType == MOD_SHRINKWRAP_NORMAL)
+                                       height += 18;
+
+                               uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
+
+                               /* Draw parameters */
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->target, "Target Object");
+
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Dist:", *xco + 75, *yco-42, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+120, *yco-42, 135, 18, &data->dist, 0.0f, 100.0f, 1.0f, 0.0f, "Distance to target");
+
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Type:", *xco + 70, *yco-60, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, *xco+120, *yco-60, 135, 18, &data->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
+
+                               if(data->shrinkType == MOD_SHRINKWRAP_NORMAL)
+                               {
+                                       /* Draw XYZ toggles */
+                                       uiDefBut(block, LABEL,B_CONSTRAINT_TEST, "Axis:", *xco+ 75, *yco-78, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                                       uiDefButC(block, ROW, B_CONSTRAINT_TEST, "X"    , *xco+120, *yco-78, 45, 18, &data->normalAxis, 18.0, UP_X, 0, 0, "Direction of normal projection is x-axis");
+                                       uiDefButC(block, ROW, B_CONSTRAINT_TEST, "Y"    , *xco+165, *yco-78, 45, 18, &data->normalAxis, 18.0, UP_Y, 0, 0, "Direction of normal projection is y-axis");
+                                       uiDefButC(block, ROW, B_CONSTRAINT_TEST, "Z"    , *xco+210, *yco-78, 45, 18, &data->normalAxis, 18.0, UP_Z, 0, 0, "Direction of normal projection is z-axis");
+                               }
                        }
                        break;
                default: