*Added documentation mainly at shrinkwrap.c
authorAndre Susano Pinto <andresusanopinto@gmail.com>
Tue, 12 Aug 2008 20:43:10 +0000 (20:43 +0000)
committerAndre Susano Pinto <andresusanopinto@gmail.com>
Tue, 12 Aug 2008 20:43:10 +0000 (20:43 +0000)
*removed commented code about the dropped shrinkwrap options
*Removed references to "cut plane", "limitMesh".. its now called "auxiliar target"

*Added option to shrinkwrap over an selected axis
*"Normal projection" mode is now called "projection" since it can now project over "normal, and any combination X, Y, Z"

source/blender/blenkernel/BKE_shrinkwrap.h
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/shrinkwrap.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_modifier_types.h
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c

index dec9635f14cc3c13a46ecdb0225eba088d6c355d..4fa52f125661fc13f8a783c4d068adc27612a6d4 100644 (file)
 #define BKE_SHRINKWRAP_H
 
 /* mesh util */
-//TODO move this somewhere else
+//TODO: move this somewhere else
 #include "BKE_customdata.h"
 struct DerivedMesh;
 struct Object;
 struct DerivedMesh *object_get_derived_final(struct Object *ob, CustomDataMask dataMask);
 
-/* bitset stuff */
-//TODO: should move this to other generic lib files?
-typedef char* BitSet;
-#define bitset_memsize(size)           (sizeof(char)*((size+7)>>3))
-
-#define bitset_new(size,name)          ((BitSet)MEM_callocN( bitset_memsize(size) , name))
-#define bitset_free(set)                       (MEM_freeN((void*)set))
-
-#define bitset_get(set,index)  ((set)[(index)>>3] & (1 << ((index)&0x7)))
-#define bitset_set(set,index)  ((set)[(index)>>3] |= (1 << ((index)&0x7)))
-#define bitset_unset(set,index)        ((set)[(index)>>3] &= ~(1 << ((index)&0x7)))
-
 
 /* SpaceTransform stuff */
-//TODO: should move to other generic space?
+/*
+ * TODO: move this somewhere else
+ *
+ * this structs encapsulates all needed data to convert between 2 coordinate spaces
+ * (where conversion can be represented by a matrix multiplication)
+ *
+ * This is used to reduce the number of arguments to pass to functions that need to perform
+ * this kind of operation and make it easier for the coder, as he/she doenst needs to recode
+ * the matrix calculation.
+ *
+ * A SpaceTransform is initialized using:
+ *   space_transform_setup( &data,  ob1, ob2 )
+ *
+ * After that the following calls can be used:
+ *   space_transform_apply (&data, co); //converts a coordinate in ob1 coords space to the corresponding ob2 coords
+ *   space_transform_invert(&data, co); //converts a coordinate in ob2 coords space to the corresponding ob1 coords
+ *
+ *     //Same Concept as space_transform_apply and space_transform_invert, but no is normalized after conversion
+ *   space_transform_apply_normal (&data, &no);
+ *   space_transform_invert_normal(&data, &no);
+ *
+ */
 struct Object;
 
 typedef struct SpaceTransform
@@ -66,20 +75,29 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[][4], float
 void space_transform_apply (const SpaceTransform *data, float *co);
 void space_transform_invert(const SpaceTransform *data, float *co);
 
-void space_transform_apply_normal (const SpaceTransform *data, float *co);
-void space_transform_invert_normal(const SpaceTransform *data, float *co);
+void space_transform_apply_normal (const SpaceTransform *data, float *no);
+void space_transform_invert_normal(const SpaceTransform *data, float *no);
 
 /* Shrinkwrap stuff */
 #include "BKE_bvhutils.h"
 
+/*
+ * Shrinkwrap is composed by a set of functions and options that define the type of shrink.
+ *
+ * 3 modes are available:
+ *    - Nearest vertex
+ *       - Nearest surface
+ *    - Normal projection
+ *
+ * ShrinkwrapCalcData encapsulates all needed data for shrinkwrap functions.
+ * (So that you dont have to pass an enormous ammount of arguments to functions)
+ */
+
 struct Object;
 struct DerivedMesh;
 struct ShrinkwrapModifierData;
 struct BVHTree;
 
-/* maybe move to bvh util */
-int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata);
-
 
 typedef struct ShrinkwrapCalcData
 {
@@ -95,7 +113,6 @@ typedef struct ShrinkwrapCalcData
        SpaceTransform local2target;    //transform to move bettwem local and target space
 
        float keptDist;                                 //Distance to kept from target (units are in local space)
-       BitSet moved;                                   //BitSet indicating if vertex has moved
 
 } ShrinkwrapCalcData;
 
@@ -103,15 +120,27 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *data);
 void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *data);
 void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *data);
 
-struct DerivedMesh *shrinkwrapModifier_do(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc);
 void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts);
 
+/*
+ * This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is:
+ *
+ * if transf was configured with "space_transform_setup( &transf,  ob1, ob2 )"
+ * then the input (vert, dir, BVHTreeRayHit) must be defined in ob1 coordinates space
+ * and the BVHTree must be built in ob2 coordinate space.
+ *
+ * Thus it provides an easy way to cast the same ray across several trees (where each tree was built on its own coords space)
+ */
+int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata);
+
+/*
+ * NULL initializers to local data
+ */
 #define NULL_ShrinkwrapCalcData        {NULL, }
 #define NULL_BVHTreeFromMesh   {NULL, }
 #define NULL_BVHTreeRayHit             {NULL, }
-#define NULL_BVHTreeNearest            {NULL, }
+#define NULL_BVHTreeNearest            {0, }
 
 
 #endif
 
-
index 2456472d94a3d5cabf6a8f0fe59699b3e1bf94fd..1d7d4d1fda0a20e0be60a861227eb4006486ce21 100644 (file)
@@ -3274,6 +3274,7 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
 
        if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) )
        {
+               int fail = FALSE;
                float co[3] = {0.0f, 0.0f, 0.0f};
                float no[3] = {0.0f, 0.0f, 0.0f};
                float dist;
@@ -3295,58 +3296,72 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
                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;
-               }
-
                if(target != NULL)
                {
 
                        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:
                                        bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6);
-                                       if(treeData.tree == NULL) return;
+                                       if(treeData.tree == NULL)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       space_transform_apply(&transform, co);
 
                                        BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
                                        
                                        dist = VecLenf(co, nearest.co);
                                        VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
+                                       space_transform_invert(&transform, co);
                                break;
 
                                case MOD_SHRINKWRAP_NEAREST_VERTEX:
                                        bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6);
-                                       if(treeData.tree == NULL) return;
+                                       if(treeData.tree == NULL)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       space_transform_apply_normal(&transform, no);
 
                                        BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
 
                                        dist = VecLenf(co, nearest.co);
                                        VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
+                                       space_transform_invert(&transform, co);
                                break;
 
-                               case MOD_SHRINKWRAP_NORMAL:
-                                       bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6);
-                                       if(treeData.tree == NULL) return;
+                               case MOD_SHRINKWRAP_PROJECT:
+                                       if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f;
+                                       if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f;
+                                       if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f;
 
-                                       if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
+                                       if(INPR(no,no) < FLT_EPSILON)
                                        {
-                                               free_bvhtree_from_mesh(&treeData);
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       Normalize(no);
 
-                                               target->release(target);
 
-                                               return;
+                                       bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6);
+                                       if(treeData.tree == NULL)
+                                       {
+                                               fail = TRUE;
+                                               break;
+                                       }
+
+                                       if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
+                                       {
+                                               fail = TRUE;
+                                               break;
                                        }
                                        VECCOPY(co, hit.co);
                                break;
@@ -3356,11 +3371,8 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
 
                        target->release(target);
 
-                       if(scon->shrinkType != MOD_SHRINKWRAP_NORMAL)
-                       {
-                               space_transform_invert(&transform, co);
-                       }
-                       VECADD(ct->matrix[3], ct->matrix[3], co);
+                       if(fail == FALSE)
+                               VECADD(ct->matrix[3], ct->matrix[3], co);
                }
        }
 }
index 0eb01e823aa52e7dcad949844b4e8fcd01509763..75e6b69a3d9399b0dc8d8650cd1027321d375796 100644 (file)
@@ -7230,11 +7230,11 @@ static void shrinkwrapModifier_initData(ModifierData *md)
 {
        ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
        smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
-       smd->shrinkOpts = MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL;
+       smd->shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR;
        smd->keptDist   = 0.0f;
 
-       smd->target = 0;
-       smd->cutPlane = 0;
+       smd->target             = NULL;
+       smd->auxTarget  = NULL;
 }
 
 static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)
@@ -7242,12 +7242,14 @@ static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)
        ShrinkwrapModifierData *smd  = (ShrinkwrapModifierData*)md;
        ShrinkwrapModifierData *tsmd = (ShrinkwrapModifierData*)target;
 
-       tsmd->target = smd->target;
-       tsmd->cutPlane = smd->cutPlane;
+       tsmd->target    = smd->target;
+       tsmd->auxTarget = smd->auxTarget;
+
        strcpy(tsmd->vgroup_name, smd->vgroup_name);
-       tsmd->keptDist = smd->keptDist;
-       tsmd->shrinkType = smd->shrinkType;
-       tsmd->shrinkOpts = smd->shrinkOpts;
+
+       tsmd->keptDist  = smd->keptDist;
+       tsmd->shrinkType= smd->shrinkType;
+       tsmd->shrinkOpts= smd->shrinkOpts;
 }
 
 CustomDataMask shrinkwrapModifier_requiredDataMask(ModifierData *md)
@@ -7273,19 +7275,9 @@ static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, O
        ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
 
        walk(userData, ob, &smd->target);
-       walk(userData, ob, &smd->cutPlane);
-}
-/*
-static DerivedMesh *shrinkwrapModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
-{
-       return shrinkwrapModifier_do((ShrinkwrapModifierData*)md,ob,derivedData,useRenderParams,isFinalCalc);
+       walk(userData, ob, &smd->auxTarget);
 }
 
-static DerivedMesh *shrinkwrapModifier_applyModifierEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData)
-{
-       return shrinkwrapModifier_do((ShrinkwrapModifierData*)md,ob,derivedData,0,0);
-}
-*/
 static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 {
        shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, derivedData, vertexCos, numVerts);
@@ -7313,8 +7305,8 @@ static void shrinkwrapModifier_updateDepgraph(ModifierData *md, DagForest *fores
        if (smd->target)
                dag_add_relation(forest, dag_get_node(forest, smd->target),   obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
 
-       if (smd->cutPlane)
-               dag_add_relation(forest, dag_get_node(forest, smd->cutPlane), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
+       if (smd->auxTarget)
+               dag_add_relation(forest, dag_get_node(forest, smd->auxTarget), obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
 }
 
 /* SimpleDeform */
index 2744212848361e4f66480f2b0ea23cf4bb876290..d8ed67855c71e68c30450150a10448dc2a565686 100644 (file)
@@ -62,7 +62,6 @@
 /* Benchmark macros */
 #if 1
 
-
 #include <sys/time.h>
 
 #define BENCH(a)       \
                printf("%s: %fs (real) %fs (cpu)\n", #a, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\
        } while(0)
 
-#define BENCH_VAR(name)                clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0
-#define BENCH_BEGIN(name)      JOIN(_bench_step, name) = clock()
-#define BENCH_END(name)                JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name)
-#define BENCH_RESET(name)      JOIN(_bench_total, name) = 0
-#define BENCH_REPORT(name)     printf("%s: %fms (cpu) \n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC)
-
 #else
 
 #define BENCH(a)       (a)
-#define BENCH_VAR(name)
-#define BENCH_BEGIN(name)
-#define BENCH_END(name)
-#define BENCH_RESET(name)
-#define BENCH_REPORT(name)
 
 #endif
 
@@ -115,7 +103,7 @@ DerivedMesh *object_get_derived_final(Object *ob, CustomDataMask dataMask)
 void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4])
 {
        float itarget[4][4];
-       Mat4Invert(itarget, target); //Invserse might be outdated
+       Mat4Invert(itarget, target);
        Mat4MulSerie(data->local2target, itarget, local, 0, 0, 0, 0, 0, 0);
        Mat4Invert(data->target2local, data->local2target);
 }
@@ -152,443 +140,24 @@ static float squared_dist(const float *a, const float *b)
        return INPR(tmp, tmp);
 }
 
-/*
- *
- */
-static void derivedmesh_mergeNearestPoints(DerivedMesh *dm, float mdist, BitSet skipVert)
-{
-       if(mdist > 0.0f)
-       {
-               int i, j, merged;
-               int     numVerts = dm->getNumVerts(dm);
-               int *translate_vert = MEM_mallocN( sizeof(int)*numVerts, "merge points array");
-
-               MVert *vert = dm->getVertDataArray(dm, CD_MVERT);
-
-               if(!translate_vert) return;
-
-               merged = 0;
-               for(i=0; i<numVerts; i++)
-               {
-                       translate_vert[i] = i;
-
-                       if(skipVert && bitset_get(skipVert, i)) continue;
-
-                       for(j = 0; j<i; j++)
-                       {
-                               if(skipVert && bitset_get(skipVert, j)) continue;
-                               if(squared_dist(vert[i].co, vert[j].co) < mdist)
-                               {
-                                       translate_vert[i] = j;
-                                       merged++;
-                                       break;
-                               }
-                       }
-               }
-
-               //some vertexs were merged.. recalculate structure (edges and faces)
-               if(merged > 0)
-               {
-                       int     numFaces = dm->getNumFaces(dm);
-                       int freeVert;
-                       MFace *face = dm->getFaceDataArray(dm, CD_MFACE);
-
-
-                       //Adjust vertexs using the translation_table.. only translations to back indexs are allowed
-                       //which means t[i] <= i must always verify
-                       for(i=0, freeVert = 0; i<numVerts; i++)
-                       {
-                               if(translate_vert[i] == i)
-                               {
-                                       memcpy(&vert[freeVert], &vert[i], sizeof(*vert));
-                                       translate_vert[i] = freeVert++;
-                               }
-                               else translate_vert[i] = translate_vert[ translate_vert[i] ];
-                       }
-
-                       CDDM_lower_num_verts(dm, numVerts - merged);
-
-                       for(i=0; i<numFaces; i++)
-                       {
-                               MFace *f = face+i;
-                               f->v1 = translate_vert[f->v1];
-                               f->v2 = translate_vert[f->v2];
-                               f->v3 = translate_vert[f->v3];
-                               //TODO be carefull with vertexs v4 being translated to 0
-                               f->v4 = translate_vert[f->v4];
-                       }
-
-                       //TODO: maybe update edges could be done outside this function
-                       CDDM_calc_edges(dm);
-                       //CDDM_calc_normals(dm);
-               }
-
-               if(translate_vert) MEM_freeN( translate_vert );
-       }
-}
-
-
-/*
- * This function removes Unused faces, vertexs and edges from calc->target
- *
- * This function may modify calc->final. As so no data retrieved from
- * it before the call to this function  can be considered valid
- * In case it creates a new DerivedMesh, the old calc->final is freed
- */
-//TODO memory checks on allocs
-/*
-static void shrinkwrap_removeUnused(ShrinkwrapCalcData *calc)
-{
-       int i, t;
-
-       DerivedMesh *old = calc->final, *new = NULL;
-       MFace *new_face = NULL;
-       MVert *new_vert  = NULL;
-
-       int numVerts= old->getNumVerts(old);
-       MVert *vert = old->getVertDataArray(old, CD_MVERT);
-
-       int     numFaces= old->getNumFaces(old);
-       MFace *face = old->getFaceDataArray(old, CD_MFACE);
-
-       BitSet moved_verts = calc->moved;
-
-       //Arrays to translate to new vertexs indexs
-       int *vert_index = (int*)MEM_callocN(sizeof(int)*(numVerts), "shrinkwrap used verts");
-       BitSet used_faces = bitset_new(numFaces, "shrinkwrap used faces");
-       int numUsedFaces = 0;
-
-
-       //calculate which vertexs need to be used
-       //even unmoved vertices might need to be used if theres a face that needs it
-       //calc real number of faces, and vertices
-       //Count used faces
-       for(i=0; i<numFaces; i++)
-       {
-               char res = 0;
-               if(bitset_get(moved_verts, face[i].v1)) res++;
-               if(bitset_get(moved_verts, face[i].v2)) res++;
-               if(bitset_get(moved_verts, face[i].v3)) res++;
-               if(face[i].v4 && bitset_get(moved_verts, face[i].v4)) res++;
-
-               //Ignore a face were not a single vertice moved
-               if(res == 0) continue;
-
-
-               //Only 1 vertice moved.. (if its a quad.. remove the vertice oposite to it)
-               if(res == 1 && face[i].v4)
-               {
-                       if(bitset_get(moved_verts, face[i].v1))
-                       {
-                               //remove vertex 3
-                               face[i].v3 = face[i].v4;
-                       }
-                       else if(bitset_get(moved_verts, face[i].v2))
-                       {
-                               //remove vertex 4
-                       }
-                       else if(bitset_get(moved_verts, face[i].v3))
-                       {
-                               //remove vertex 1
-                               face[i].v1 = face[i].v4;
-                       }
-                       else if(bitset_get(moved_verts, face[i].v4))
-                       {
-                               //remove vertex 2
-                               face[i].v2 = face[i].v3;
-                               face[i].v3 = face[i].v4;
-                       }
-
-                       face[i].v4 = 0; //this quad turned on a tri
-               }
-               
-#if 0
-               if(face[i].v4 && res == 3)
-               {
-                       if(!bitset_get(moved_verts, face[i].v1))
-                       {
-                               face[i].v1 = face[i].v4;
-                       }
-                       else if(!bitset_get(moved_verts, face[i].v2))
-                       {
-                               face[i].v2 = face[i].v3;
-                               face[i].v3 = face[i].v4;
-                       }
-                       else if(!bitset_get(moved_verts, face[i].v3))
-                       {
-                               face[i].v3 = face[i].v4;
-                       }
-
-                       face[i].v4 = 0; //this quad turned on a tri
-               }
-#endif
-
-               bitset_set(used_faces, i);      //Mark face to maintain
-               numUsedFaces++;
-
-               //Mark vertices are needed
-               vert_index[face[i].v1] = 1;
-               vert_index[face[i].v2] = 1;
-               vert_index[face[i].v3] = 1;
-               if(face[i].v4) vert_index[face[i].v4] = 1;
-       }
-
-       //DP: Accumulate vertexs indexs.. (will calculate the new vertex index with a 1 offset)
-       for(i=1; i<numVerts; i++)
-               vert_index[i] += vert_index[i-1];
-               
-       
-       //Start creating the clean mesh
-       new = CDDM_new(vert_index[numVerts-1], 0, numUsedFaces);
-
-       //Copy vertexs (unused are are removed)
-       new_vert  = new->getVertDataArray(new, CD_MVERT);
-       for(i=0, t=0; i<numVerts; i++)
-       {
-               
-               if(vert_index[i] != t)
-               {
-                       t = vert_index[i];
-                       memcpy(new_vert++, vert+i, sizeof(MVert));
-
-                       if(bitset_get(moved_verts, i))
-                               bitset_set(moved_verts, t-1);
-                       else
-                               bitset_unset(moved_verts, t-1);
-               }
-       }
-
-       //Copy faces
-       new_face = new->getFaceDataArray(new, CD_MFACE);
-       for(i=0, t=0; i<numFaces; i++)
-       {
-               if(bitset_get(used_faces, i))
-               {
-                       memcpy(new_face, face+i, sizeof(MFace));
-                       //update vertices indexs
-                       new_face->v1 = vert_index[new_face->v1]-1;
-                       new_face->v2 = vert_index[new_face->v2]-1;
-                       new_face->v3 = vert_index[new_face->v3]-1;
-                       if(new_face->v4)
-                       {
-                               new_face->v4 = vert_index[new_face->v4]-1;
-
-                               //Ups translated vertex ended on 0 .. TODO fix this
-                               if(new_face->v4 == 0)
-                               {
-                               }
-                       }                       
-                       new_face++;
-               }
-       }
-
-       //Free memory
-       bitset_free(used_faces);
-       MEM_freeN(vert_index);
-       old->release(old);
-
-       //Update edges
-       CDDM_calc_edges(new);
-       CDDM_calc_normals(new);
-
-       calc->final = new;
-}
-
-
-void shrinkwrap_projectToCutPlane(ShrinkwrapCalcData *calc_data)
-{
-       if(calc_data->smd->cutPlane && calc_data->moved)
-       {
-               int i;
-               int unmoved = 0;
-               int numVerts= 0;
-               MVert *vert = NULL;
-               MVert *vert_unmoved = NULL;
-
-               ShrinkwrapCalcData calc;
-               memcpy(&calc, calc_data, sizeof(calc));
-
-               calc.moved = 0;
-
-               if(calc.smd->cutPlane)
-               {
-                       //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
-                       calc.target = CDDM_copy( object_get_derived_final(calc.smd->cutPlane, CD_MASK_BAREMESH) );
-
-                       if(!calc.target)
-                       {
-                               return;
-                       }
-
-                       space_transform_setup(&calc.local2target, calc.ob, calc.smd->cutPlane);
-                       calc.keptDist = 0;
-               }
-
-
-               //Make a mesh with the points we want to project
-               numVerts = calc_data->final->getNumVerts(calc_data->final);
-
-               unmoved = 0;
-               for(i=0; i<numVerts; i++)
-                       if(!bitset_get(calc_data->moved, i))
-                               unmoved++;
-
-               calc.final = CDDM_new(unmoved, 0, 0);
-               if(!calc.final) return;
-
-
-               vert = calc_data->final->getVertDataArray(calc_data->final, CD_MVERT);
-               vert_unmoved = calc.final->getVertDataArray(calc.final, CD_MVERT);
-
-               for(i=0; i<numVerts; i++)
-                       if(!bitset_get(calc_data->moved, i))
-                               memcpy(vert_unmoved++, vert+i, sizeof(*vert_unmoved));
-
-               //use shrinkwrap projection
-               shrinkwrap_calc_normal_projection(&calc);
-
-               //Copy the points back to the mesh
-               vert = calc_data->final->getVertDataArray(calc_data->final, CD_MVERT);
-               vert_unmoved = calc.final->getVertDataArray(calc.final, CD_MVERT);
-               for(i=0; i<numVerts; i++)
-                       if(!bitset_get(calc_data->moved, i))
-                               memcpy(vert+i, vert_unmoved++, sizeof(*vert_unmoved) );
-
-               //free memory
-               calc.final->release(calc.final);
-               calc.target->release(calc.target);
-       }       
-
-}
-*/
-
 /* Main shrinkwrap function */
-/*
-DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
 {
 
-       ShrinkwrapCalcData calc;
-       memset(&calc, 0, sizeof(calc));
-
-       //Init Shrinkwrap calc data
-       calc.smd = smd;
-
-       calc.ob = ob;
-       calc.original = dm;
-       calc.final = CDDM_copy(calc.original);
-
-       if(!calc.final)
-       {
-               OUT_OF_MEMORY();
-               return dm;
-       }
-
-       CDDM_calc_normals(calc.final);  //Normals maybe not be calculated yet
+       ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
 
        //remove loop dependencies on derived meshs (TODO should this be done elsewhere?)
        if(smd->target == ob) smd->target = NULL;
-       if(smd->cutPlane == ob) smd->cutPlane = NULL;
-
-
-       if(smd->target)
-       {
-               //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
-               calc.target = CDDM_copy( object_get_derived_final(smd->target, CD_MASK_BAREMESH) );
-
-               if(!calc.target)
-               {
-                       printf("Target derived mesh is null! :S\n");
-               }
-
-               //TODO there might be several "bugs" on non-uniform scales matrixs.. because it will no longer be nearest surface, not sphere projection
-               //because space has been deformed
-               space_transform_setup(&calc.local2target, ob, smd->target);
-
-               calc.keptDist = smd->keptDist;  //TODO: smd->keptDist is in global units.. must change to local
-       }
-
-       //Projecting target defined - lets work!
-       if(calc.target)
-       {
-
-               printf("Shrinkwrap (%s)%d over (%s)%d\n",
-                       calc.ob->id.name,                       calc.final->getNumVerts(calc.final),
-                       calc.smd->target->id.name,      calc.target->getNumVerts(calc.target)
-               );
-
-
-               switch(smd->shrinkType)
-               {
-                       case MOD_SHRINKWRAP_NEAREST_SURFACE:
-                               BENCH(shrinkwrap_calc_nearest_surface_point(&calc));
-//                             BENCH(shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_surface_point));
-                       break;
-
-                       case MOD_SHRINKWRAP_NORMAL:
-
-                               if(calc.smd->shrinkOpts & MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES)
-                               calc.moved = bitset_new( calc.final->getNumVerts(calc.final), "shrinkwrap bitset data");
+       if(smd->auxTarget == ob) smd->auxTarget = NULL;
 
 
-//                             BENCH(shrinkwrap_calc_normal_projection_raytree(&calc));
-//                             calc.final->release( calc.final );
-//                             calc.final = CDDM_copy(calc.original);
-
-                               BENCH(shrinkwrap_calc_normal_projection(&calc));
-//                             BENCH(shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_normal_projection));
-
-                               if(calc.moved)
-                               {
-                                       //Adjust vertxs that didn't moved (project to cut plane)
-                                       shrinkwrap_projectToCutPlane(&calc);
-
-                                       //Destroy faces, edges and stuff
-                                       shrinkwrap_removeUnused(&calc);
-
-                                       //Merge points that didn't moved
-                                       derivedmesh_mergeNearestPoints(calc.final, calc.smd->mergeDist, calc.moved);
-                                       bitset_free(calc.moved);
-                               }
-                       break;
-
-                       case MOD_SHRINKWRAP_NEAREST_VERTEX:
-
-                               BENCH(shrinkwrap_calc_nearest_vertex(&calc));
-//                             BENCH(shrinkwrap_calc_foreach_vertex(&calc, bruteforce_shrinkwrap_calc_nearest_vertex));
-                       break;
-               }
-
-               //free derived mesh
-               calc.target->release( calc.target );
-               calc.target = NULL;
-       }
-
-       CDDM_calc_normals(calc.final);
-
-       return calc.final;
-}
-*/
-
-/* Main shrinkwrap function */
-void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
-{
-
-       ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
-
-       //Init Shrinkwrap calc data
+       //Configure Shrinkwrap calc data
        calc.smd = smd;
-
        calc.ob = ob;
        calc.original = dm;
-
        calc.numVerts = numVerts;
        calc.vertexCos = vertexCos;
 
-       //remove loop dependencies on derived meshs (TODO should this be done elsewhere?)
-       if(smd->target == ob) smd->target = NULL;
-       if(smd->cutPlane == ob) smd->cutPlane = NULL;
-
-
        if(smd->target)
        {
                //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
@@ -606,6 +175,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
                calc.keptDist = smd->keptDist;  //TODO: smd->keptDist is in global units.. must change to local
        }
 
+
        //Projecting target defined - lets work!
        if(calc.target)
        {
@@ -615,14 +185,13 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
                        calc.smd->target->id.name,      calc.target->getNumVerts(calc.target)
                );
 
-
                switch(smd->shrinkType)
                {
                        case MOD_SHRINKWRAP_NEAREST_SURFACE:
                                BENCH(shrinkwrap_calc_nearest_surface_point(&calc));
                        break;
 
-                       case MOD_SHRINKWRAP_NORMAL:
+                       case MOD_SHRINKWRAP_PROJECT:
                                BENCH(shrinkwrap_calc_normal_projection(&calc));
                        break;
 
@@ -630,18 +199,18 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
                                BENCH(shrinkwrap_calc_nearest_vertex(&calc));
                        break;
                }
+       }
 
-               //free derived mesh
+       //free memory
+       if(calc.target)
                calc.target->release( calc.target );
-               calc.target = NULL;
-       }
 }
 
 /*
  * Shrinkwrap to the nearest vertex
  *
  * it builds a kdtree of vertexs we can attach to and then
- * for each vertex on performs a nearest vertex search on the tree
+ * for each vertex performs a nearest vertex search on the tree
  */
 void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
 {
@@ -653,7 +222,6 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
 
        MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
 
-
        BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6));
        if(treeData.tree == NULL) return OUT_OF_MEMORY();
 
@@ -665,29 +233,37 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
        for(i = 0; i<calc->numVerts; ++i)
        {
                float *co = calc->vertexCos[i];
-               int index;
                float tmp_co[3];
                float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
                if(weight == 0.0f) continue;
 
                VECCOPY(tmp_co, co);
-               space_transform_apply(&calc->local2target, tmp_co);
+               space_transform_apply(&calc->local2target, tmp_co); //Convert the coordinates to the tree coordinates
 
                //Use local proximity heuristics (to reduce the nearest search)
+               //
+               //If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex
+               //so we can initiate the "nearest.dist" with the expected value to that last hit.
+               //This will lead in prunning of the search tree.
                if(nearest.index != -1)
                        nearest.dist = squared_dist(tmp_co, nearest.co);
                else
                        nearest.dist = FLT_MAX;
 
-               index = BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData);
+               BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData);
 
-               if(index != -1)
+
+               //Found the nearest vertex
+               if(nearest.index != -1)
                {
-                       float dist = nearest.dist;
-                       if(dist > 1e-5) weight *= (dist - calc->keptDist)/dist;
+                       //Adjusting the vertex weight, so that after interpolating it kepts a certain distance from the nearest position
+                       float dist = sasqrt(nearest.dist);
+                       if(dist > FLT_EPSILON) weight *= (dist - calc->keptDist)/dist;
 
+                       //Convert the coordinates back to mesh coordinates
                        VECCOPY(tmp_co, nearest.co);
                        space_transform_invert(&calc->local2target, tmp_co);
+
                        VecLerpf(co, co, tmp_co, weight);       //linear interpolation
                }
        }
@@ -763,104 +339,132 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
 void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
 {
        int i;
-       int vgroup              = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
-       char use_normal = calc->smd->shrinkOpts;
-
-       //setup raytracing
-       BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
-       BVHTreeRayHit   hit      = NULL_BVHTreeRayHit;
 
-       //cutTree
-       DerivedMesh * limit_mesh = NULL;
-       BVHTreeFromMesh limitData= NULL_BVHTreeFromMesh;
-       SpaceTransform local2cut;
+       //Options about projection direction
+       char use_normal    = calc->smd->shrinkOpts;
+       float proj_axis[3] = {0.0f, 0.0f, 0.0f};
+       MVert *vert  = NULL; //Needed in case of vertex normal
 
-       MVert        *vert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MVERT) : NULL;                //Needed because of vertex normal
+       //Vertex group data
+       int vgroup                 = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
        MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
 
-       if(vert == NULL)
+
+       //Raycast and tree stuff
+       BVHTreeRayHit hit;
+       BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;        //target
+
+       //auxiliar target
+       DerivedMesh * aux_mesh = NULL;
+       BVHTreeFromMesh auxData= NULL_BVHTreeFromMesh;
+       SpaceTransform local2aux;
+
+
+       //Prepare data to retrieve the direction in which we should project each vertex
+       if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
        {
-               printf("Shrinkwrap cant normal project witouth normal information");
+               vert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MVERT) : NULL;
+               if(vert) CDDM_calc_normals(calc->original);     //Maybe normals aren't yet calculated
+       }
+       else
+       {
+               //The code supports any axis that is a combination of X,Y,Z.. altought currently UI only allows to set the 3 diferent axis
+               if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) proj_axis[0] = 1.0f;
+               if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) proj_axis[1] = 1.0f;
+               if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) proj_axis[2] = 1.0f;
+
+               Normalize(proj_axis);
+       }
+
+       if(vert == NULL && (INPR(proj_axis, proj_axis) < FLT_EPSILON))
+       {
+               printf("Shrinkwrap can't project witouth normal information");
                return;
        }
-       if((use_normal & (MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL | MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)) == 0)
-               return; //Nothing todo
 
-       CDDM_calc_normals(calc->original);      //Normals maybe arent yet calculated
+       //If the user doesn't allows to project in any direction of projection axis... then theres nothing todo.
+       if((use_normal & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0)
+               return;
+
 
+       //Build target tree
        BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, calc->keptDist, 4, 6));
        if(treeData.tree == NULL) return OUT_OF_MEMORY();
 
-
-       if(calc->smd->cutPlane)
+       //Build auxiliar target
+       if(calc->smd->auxTarget)
        {
-               space_transform_setup( &local2cut, calc->ob, calc->smd->cutPlane);
+               space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget);
 
-               //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
-               limit_mesh = CDDM_copy( object_get_derived_final(calc->smd->cutPlane, CD_MASK_BAREMESH) );
-               if(limit_mesh)
-                       BENCH(bvhtree_from_mesh_faces(&limitData, limit_mesh, 0.0, 4, 6));
+               aux_mesh = CDDM_copy( object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH) );               //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array
+               if(aux_mesh)
+                       BENCH(bvhtree_from_mesh_faces(&auxData, aux_mesh, 0.0, 4, 6));
                else
-                       printf("CutPlane finalDerived mesh is null\n");
+                       printf("Auxiliar target finalDerived mesh is null\n");
        }
 
+
+       //Now, everything is ready to project the vertexs!
+
 //#pragma omp parallel for private(i) private(hit) schedule(static)
        for(i = 0; i<calc->numVerts; ++i)
        {
                float *co = calc->vertexCos[i];
                float tmp_co[3], tmp_no[3];
-               float lim = 1000;               //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
+               float lim = 1000; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
                float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
-               char moved = FALSE;
 
                if(weight == 0.0f) continue;
 
                VECCOPY(tmp_co, co);
-               NormalShortToFloat(tmp_no, vert[i].no);
+
+               if(vert)
+                       NormalShortToFloat(tmp_no, vert[i].no);
+               else
+                       VECCOPY( tmp_no, proj_axis );
 
 
                hit.index = -1;
                hit.dist = lim;
 
 
-               if(use_normal & MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL)
+               //Project over positive direction of axis
+               if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR)
                {
 
-                       if(limitData.tree)
-                               normal_projection_project_vertex(0, tmp_co, tmp_no, &local2cut, limitData.tree, &hit, limitData.raycast_callback, &limitData);
+                       if(auxData.tree)
+                               normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
 
-                       if(normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData))
-                               moved = TRUE;
+                       normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
                }
 
-
-               if(use_normal & MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL)
+               //Project over negative direction of axis
+               if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)
                {
                        float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] };
 
 
-                       if(limitData.tree)
-                               normal_projection_project_vertex(0, tmp_co, inv_no, &local2cut, limitData.tree, &hit, limitData.raycast_callback, &limitData);
+                       if(auxData.tree)
+                               normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
 
-                       if(normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData))
-                               moved = TRUE;
+                       normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
                }
 
 
                if(hit.index != -1)
                {
                        VecLerpf(co, co, hit.co, weight);
-
-                       if(moved && calc->moved)
-                               bitset_set(calc->moved, i);
                }
        }
 
+
+       //free data structures
+
        free_bvhtree_from_mesh(&treeData);
-       free_bvhtree_from_mesh(&limitData);
+       free_bvhtree_from_mesh(&auxData);
 
-       if(limit_mesh)
-               limit_mesh->release(limit_mesh);
+       if(aux_mesh)
+               aux_mesh->release(aux_mesh);
 }
 
 /*
@@ -920,7 +524,14 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
                        else
                        {
                                float dist = sasqrt( nearest.dist );
-                               VecLerpf(tmp_co, tmp_co, nearest.co, (dist - calc->keptDist)/dist);     //linear interpolation
+                               if(dist > FLT_EPSILON)
+                               {
+                                       VecLerpf(tmp_co, tmp_co, nearest.co, (dist - calc->keptDist)/dist);     //linear interpolation
+                               }
+                               else
+                               {
+                                       VECCOPY( tmp_co, nearest.co );
+                               }
                        }
                        space_transform_invert(&calc->local2target, tmp_co);
                        VecLerpf(co, co, tmp_co, weight);       //linear interpolation
index cc7bdeef0de61a5620f1f8dd666c7b789a6a319a..48bacdefcf6fae6c1e3eb6ae11dd967ffaabaf04 100644 (file)
@@ -321,7 +321,7 @@ typedef struct bShrinkwrapConstraint {
        Object          *target;
        float           dist;                   /* distance to kept from target */
        short           shrinkType;             /* shrink type (look on MOD shrinkwrap for values) */
-       char            normalAxis;             /* axis to project over UP_X, UP_Y, UP_Z */
+       char            projAxis;               /* axis to project over UP_X, UP_Y, UP_Z */
        char            pad[9];
 } bShrinkwrapConstraint;
 
index b3d80f2e554fee5512bb5e5522d76b9bdaf88b68..c8db1164dc95c4b6198891a60335764fd77d3a64 100644 (file)
@@ -496,28 +496,35 @@ typedef struct ShrinkwrapModifierData {
        ModifierData modifier;
 
        struct Object *target;  /* shrink target */
-       struct Object *cutPlane;/* shrink target */
+       struct Object *auxTarget; /* additional shrink target */
        char vgroup_name[32];   /* optional vertexgroup name */
        float keptDist;                 /* distance offset from mesh/projection point */
        short shrinkType;               /* shrink type projection */
        short shrinkOpts;               /* shrink options */
+       char projAxis;                  /* axis to project over */
+       char pad[7];
 
 } ShrinkwrapModifierData;
 
 /* Shrinkwrap->shrinkType */
 #define MOD_SHRINKWRAP_NEAREST_SURFACE 0
-#define MOD_SHRINKWRAP_NORMAL                  1
+#define MOD_SHRINKWRAP_PROJECT                 1
 #define MOD_SHRINKWRAP_NEAREST_VERTEX  2
 
 /* Shrinkwrap->shrinkOpts */
-#define MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL            (1<<0)
-#define MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL   (1<<1)
-/* #define MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES     (1<<2) / * Currently dropped to make shrinkwrap a deform only modifier */
+#define MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR   (1<<0)  /* allow shrinkwrap to move the vertex in the positive direction of axis */
+#define MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR   (1<<1)  /* allow shrinkwrap to move the vertex in the negative direction of axis */
 
-#define MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE   (1<<3)
-#define MOD_SHRINKWRAP_CULL_TARGET_BACKFACE            (1<<4)
+#define MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE   (1<<3)  /* ignore vertex moves if a vertex ends projected on a front face of the target */
+#define MOD_SHRINKWRAP_CULL_TARGET_BACKFACE            (1<<4)  /* ignore vertex moves if a vertex ends projected on a back face of the target */
+
+#define MOD_SHRINKWRAP_KEPT_ABOVE_SURFACE              (1<<5)  /* distance is measure to the front face of the target */
+
+#define MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS             (1<<0)
+#define MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS             (1<<1)
+#define MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS             (1<<2)
+#define MOD_SHRINKWRAP_PROJECT_OVER_NORMAL                     0       /* projection over normal is used if no axis is selected */
 
-#define MOD_SHRINKWRAP_KEPT_ABOVE_SURFACE              (1<<5)
 
 typedef struct SimpleDeformModifierData {
        ModifierData modifier;
index bfdd4f0c9a0b70eb2c637273c1d3f6554945a116..583532b6ec8446a8c714b92a4f76ab971fb22034 100644 (file)
@@ -1902,8 +1902,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                } else if (md->type==eModifierType_Shrinkwrap) {
                        ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
                        height = 86 + 3;
-                       if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
-                               height += 19*3;
+                       if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
+                               height += 19*5;
                        else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
                                height += 19;
 
@@ -2538,7 +2538,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                } else if (md->type==eModifierType_Shrinkwrap) {
                        ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
 
-                       char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|normal projection %x1|nearest vertex %x2";
+                       char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
 
                        uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
 
@@ -2549,18 +2549,25 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 
                        cy -= 3;
                        uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
-                       if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL){
 
-                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL, B_MODIFIER_RECALC, "Default normal",      lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows vertices to move in the normal direction");
-                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL, B_MODIFIER_RECALC, "Invert normal",      lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows vertices to move in the inverse direction of their normal");
+                       if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
 
-/*                             uiDefButBitS(block, TOG, MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES, B_MODIFIER_RECALC, "Remove faces",    lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Remove faces where all vertices haven't been projected"); */
+
+                               /* UI for projection axis */
+                               uiBlockBeginAlign(block);
+                               uiDefButC(block, ROW, B_MODIFIER_RECALC, "Normal"    , lx,(cy-=19),buttonWidth,19, &smd->projAxis, 18.0, MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, 0, 0, "Projection over X axis");
+                               uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_MODIFIER_RECALC, "X",    lx+buttonWidth/3*0,(cy-=19),buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over X axis");
+                               uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_MODIFIER_RECALC, "Y",    lx+buttonWidth/3*1,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Y axis");
+                               uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS, B_MODIFIER_RECALC, "Z",    lx+buttonWidth/3*2,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Z axis");
+
+
+                               /* allowed directions of projection axis */
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR, B_MODIFIER_RECALC, "Negative",   lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the negative direction of axis");
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR, B_MODIFIER_RECALC, "Positive",   lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the positive direction of axis");
 
                                uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, B_MODIFIER_RECALC, "Cull frontfaces",lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a front face on target");
                                uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_BACKFACE,  B_MODIFIER_RECALC, "Cull backfaces",     lx+buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a back face on target");
-
-/*                             uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Dist:", lx,(cy-=19),buttonWidth,19, &smd->mergeDist, 0.0f, 0.01f, 0.01f, 0.01f, "Specify merge distance"); */
-                               uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->cutPlane, "Aditional mesh to project over");
+                               uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
                        }
                        else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
                                uiDefButBitS(block, TOG, MOD_SHRINKWRAP_KEPT_ABOVE_SURFACE, B_MODIFIER_RECALC, "Above surface", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Vertices are kept on the front side of faces");
index 524a18a9f3d1ee721c5d304e0128e6c3ce262d20..370f6999dfce38c175d01b0f0f204b5b335b2ecb 100644 (file)
@@ -1744,10 +1744,10 @@ 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";
+                               char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
 
                                height = 60;
-                               if(data->shrinkType == MOD_SHRINKWRAP_NORMAL)
+                               if(data->shrinkType == MOD_SHRINKWRAP_PROJECT)
                                        height += 18;
 
                                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
@@ -1762,13 +1762,13 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                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)
+                               if(data->shrinkType == MOD_SHRINKWRAP_PROJECT)
                                {
                                        /* 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");
+                                       uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_CONSTRAINT_TEST, "X",*xco+120, *yco-78, 45, 18, &data->projAxis, 0, 0, 0, 0, "Projection over X axis");
+                                       uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_CONSTRAINT_TEST, "Y",*xco+165, *yco-78, 45, 18, &data->projAxis, 0, 0, 0, 0, "Projection over Y axis");
+                                       uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS, B_CONSTRAINT_TEST, "Z",*xco+210, *yco-78, 45, 18, &data->projAxis, 0, 0, 0, 0, "Projection over Z axis");
                                }
                        }
                        break;