Added SSLevels options to all shrinkwrap modes (before it was only available to proje...
authorAndre Susano Pinto <andresusanopinto@gmail.com>
Tue, 16 Sep 2008 15:41:13 +0000 (15:41 +0000)
committerAndre Susano Pinto <andresusanopinto@gmail.com>
Tue, 16 Sep 2008 15:41:13 +0000 (15:41 +0000)
Added BVHTree cache at derivedMesh level

source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_bvhutils.h
source/blender/blenkernel/BKE_shrinkwrap.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/bvhutils.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/shrinkwrap.c
source/blender/src/buttons_editing.c

index 171a73f72c45fa3d2fc4625e7924659f30e392d4..fe25ada3962d0bd8d325394e252c9be746f13788 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "DNA_customdata_types.h"
 #include "BKE_customdata.h"
+#include "BKE_bvhutils.h"
 
 struct MVert;
 struct MEdge;
@@ -69,6 +70,7 @@ struct DerivedMesh {
        int numVertData, numEdgeData, numFaceData;
        int needsFree; /* checked on ->release, is set to 0 for cached results */
        int deformedOnly; /* set by modifier stack if only deformed from original */
+       BVHCache bvhCache;
 
        /* Misc. Queries */
 
index dd9ea61f24b0b539d69aab085b7eb12533583268..66c8d99959a896d7ef3c908830659f880f51b0ad 100644 (file)
@@ -31,6 +31,7 @@
 #define BKE_BVHUTILS_H
 
 #include "BLI_kdopbvh.h"
+#include "BLI_linklist.h"
 
 /*
  * This header encapsulates necessary code to buld a BVH
@@ -52,7 +53,7 @@ typedef struct BVHTreeFromMesh
        BVHTree_RayCastCallback      raycast_callback;
 
        /* Mesh represented on this BVHTree */
-       struct DerivedMesh *mesh; 
+       struct DerivedMesh *mesh;
 
        /* Vertex array, so that callbacks have instante access to data */
        struct MVert *vert;
@@ -61,6 +62,9 @@ typedef struct BVHTreeFromMesh
        /* radius for raycast */
        float sphere_radius;
 
+       /* Private data */
+       int cached;
+
 } BVHTreeFromMesh;
 
 /*
@@ -74,7 +78,7 @@ typedef struct BVHTreeFromMesh
  * 
  * free_bvhtree_from_mesh should be called when the tree is no longer needed.
  */
-void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
 
 /*
  * Builds a bvh tree where nodes are the faces of the given mesh.
@@ -84,15 +88,50 @@ void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *m
  * so that the coordinates and rays are first translated on the mesh local coordinates.
  * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse
  * a BVHTree.
+ *
+ * The returned value is the same as in data->tree, its only returned to make it easier to test
+ * the success 
  * 
  * free_bvhtree_from_mesh should be called when the tree is no longer needed.
  */
-void bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
+BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
 
 /*
  * Frees data allocated by a call to bvhtree_from_mesh_*.
  */
 void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
 
+
+/*
+ * BVHCache
+ */
+
+//Using local coordinates
+#define BVHTREE_FROM_FACES             0
+#define BVHTREE_FROM_VERTICES  1
+
+typedef LinkNode* BVHCache;
+
+
+/*
+ * Queries a bvhcache for the chache bvhtree of the request type
+ */
+BVHTree *bvhcache_find(BVHCache *cache, int type);
+
+/*
+ * Inserts a BVHTree of the given type under the cache
+ * After that the caller no longer needs to worry when to free the BVHTree
+ * as that will be done when the cache is freed.
+ *
+ * A call to this assumes that there was no previous cached tree of the given type
+ */
+void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type);
+
+/*
+ * inits and frees a bvhcache
+ */
+void bvhcache_init(BVHCache *cache);
+void bvhcache_free(BVHCache *cache);
+
 #endif
 
index e8276238ff220213cbdacb262ad9afb99adb847f..795da6ff88493cd87ac0d18fc3cb510bdd6c0501 100644 (file)
@@ -95,6 +95,8 @@ void space_transform_invert_normal(const SpaceTransform *data, float *no);
 
 struct Object;
 struct DerivedMesh;
+struct MVert;
+struct MDeformVert;
 struct ShrinkwrapModifierData;
 struct BVHTree;
 
@@ -104,8 +106,10 @@ typedef struct ShrinkwrapCalcData
        ShrinkwrapModifierData *smd;    //shrinkwrap modifier data
 
        struct Object *ob;                              //object we are applying shrinkwrap to
-       struct DerivedMesh *original;   //mesh before shrinkwrap
 
+       MVert *vert;                                    //Array of verts being projected (to fetch normals or other data) 
+       MDeformVert *dvert;                             //Array to get vertexs weights
+       int vgroup;
        float (*vertexCos)[3];                  //vertexs being shrinkwraped
        int numVerts;
 
index 328dcada01a94764dcab111c81004cc9b939ab25..a5eb1f258f187d1e5ffef382bd2bcaaacf37741f 100644 (file)
@@ -78,6 +78,7 @@
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 #include "BKE_particle.h"
+#include "BKE_bvhutils.h"
 
 #include "BLO_sys_types.h" // for intptr_t support
 
@@ -188,6 +189,8 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->getVertDataArray = DM_get_vert_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getFaceDataArray = DM_get_face_data_layer;
+
+       bvhcache_init(&dm->bvhCache);
 }
 
 void DM_init(DerivedMesh *dm,
@@ -224,6 +227,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
 int DM_release(DerivedMesh *dm)
 {
        if (dm->needsFree) {
+               bvhcache_free(&dm->bvhCache);
+
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
                CustomData_free(&dm->faceData, dm->numFaceData);
@@ -2735,6 +2740,7 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask)
        Mesh *me = ob->data;
        float min[3], max[3];
 
+       printf("Building DerivedMesh for %s\n", ob->id.name);
        clear_mesh_caches(ob);
 
        if(ob!=G.obedit) {
index ae449843d2a7f668660e46a2e1ee07c48cf59099..a8aea621502fed995c27bb2df6b78f3eb9b5182b 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
+#include <assert.h>
 
 #include "BKE_bvhutils.h"
 
@@ -45,6 +46,8 @@
 #include "BKE_global.h"
 
 #include "BLI_arithb.h"
+#include "BLI_linklist.h"
+#include "MEM_guardedalloc.h"
 
 /* Math stuff for ray casting on mesh faces and for nearest surface */
 
@@ -480,30 +483,47 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
  * BVH builders
  */
 // Builds a bvh tree.. where nodes are the vertexs of the given mesh
-void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
 {
-       int i;
-       int numVerts= mesh->getNumVerts(mesh);
-       MVert *vert     = mesh->getVertDataArray(mesh, CD_MVERT);
-       BVHTree *tree = NULL;
+       BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_VERTICES);
 
-       memset(data, 0, sizeof(*data));
+       //Not in cache
+       if(tree == NULL)
+       {
+               int i;
+               int numVerts= mesh->getNumVerts(mesh);
+               MVert *vert     = mesh->getVertDataArray(mesh, CD_MVERT);
 
-       if(vert == NULL)
+               if(vert != NULL)
+               {
+                       tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
+
+                       if(tree != NULL)
+                       {
+                               for(i = 0; i < numVerts; i++)
+                                       BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+
+                               BLI_bvhtree_balance(tree);
+
+                               //Save on cache for later use
+                               printf("BVHTree built and saved on cache\n");
+                               bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_VERTICES);
+                       }
+               }
+       }
+       else
        {
-               printf("bvhtree cant be build: cant get a vertex array");
-               return;
+               printf("BVHTree is already build, using cached tree\n");
        }
 
-       tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis);
-       if(tree != NULL)
-       {
-               for(i = 0; i < numVerts; i++)
-                       BLI_bvhtree_insert(tree, i, vert[i].co, 1);
 
-               BLI_bvhtree_balance(tree);
+       //Setup BVHTreeFromMesh
+       memset(data, 0, sizeof(*data));
+       data->tree = tree;
 
-               data->tree = tree;
+       if(data->tree)
+       {
+               data->cached = TRUE;
 
                //a NULL nearest callback works fine
                //remeber the min distance to point is the same as the min distance to BV of point
@@ -516,43 +536,62 @@ void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float eps
 
                data->sphere_radius = epsilon;
        }
+
+       return data->tree;
 }
 
 // Builds a bvh tree.. where nodes are the faces of the given mesh.
-void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
+BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
 {
-       int i;
-       int numFaces= mesh->getNumFaces(mesh);
-       MVert *vert     = mesh->getVertDataArray(mesh, CD_MVERT);
-       MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
-       BVHTree *tree = NULL;
-
-       memset(data, 0, sizeof(*data));
+       BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES);
 
-       if(vert == NULL && face == NULL)
+       //Not in cache
+       if(tree == NULL)
        {
-               printf("bvhtree cant be build: cant get a vertex/face array");
-               return;
-       }
+               int i;
+               int numFaces= mesh->getNumFaces(mesh);
+               MVert *vert     = mesh->getVertDataArray(mesh, CD_MVERT);
+               MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
 
-       /* Create a bvh-tree of the given target */
-       tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
-       if(tree != NULL)
-       {
-               for(i = 0; i < numFaces; i++)
+               if(vert != NULL && face != NULL)
                {
-                       float co[4][3];
-                       VECCOPY(co[0], vert[ face[i].v1 ].co);
-                       VECCOPY(co[1], vert[ face[i].v2 ].co);
-                       VECCOPY(co[2], vert[ face[i].v3 ].co);
-                       if(face[i].v4)
-                               VECCOPY(co[3], vert[ face[i].v4 ].co);
+                       /* Create a bvh-tree of the given target */
+                       tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
+                       if(tree != NULL)
+                       {
+                               for(i = 0; i < numFaces; i++)
+                               {
+                                       float co[4][3];
+                                       VECCOPY(co[0], vert[ face[i].v1 ].co);
+                                       VECCOPY(co[1], vert[ face[i].v2 ].co);
+                                       VECCOPY(co[2], vert[ face[i].v3 ].co);
+                                       if(face[i].v4)
+                                               VECCOPY(co[3], vert[ face[i].v4 ].co);
                        
-                       BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+                                       BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
+                               }
+                               BLI_bvhtree_balance(tree);
+
+                               //Save on cache for later use
+                               printf("BVHTree built and saved on cache\n");
+                               bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_FACES);
+                       }
                }
-               BLI_bvhtree_balance(tree);
+       }
+       else
+       {
+               printf("BVHTree is already build, using cached tree\n");
+       }
+
+
+       //Setup BVHTreeFromMesh
+       memset(data, 0, sizeof(*data));
+       data->tree = tree;
+
+       if(data->tree)
+       {
+               data->cached = TRUE;
 
-               data->tree = tree;
                data->nearest_callback = mesh_faces_nearest_point;
                data->raycast_callback = mesh_faces_spherecast;
 
@@ -562,6 +601,8 @@ void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float eps
 
                data->sphere_radius = epsilon;
        }
+       return data->tree;
+
 }
 
 // Frees data allocated by a call to bvhtree_from_mesh_*.
@@ -569,9 +610,78 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
 {
        if(data->tree)
        {
-               BLI_bvhtree_free(data->tree);
+               if(!data->cached)
+                       BLI_bvhtree_free(data->tree);
+
                memset( data, 0, sizeof(data) );
        }
 }
 
 
+/* BVHCache */
+typedef struct BVHCacheItem
+{
+       int type;
+       BVHTree *tree;
+
+} BVHCacheItem;
+
+static void bvhcacheitem_set_if_match(void *_cached, void *_search)
+{
+       BVHCacheItem * cached = (BVHCacheItem *)_cached;
+       BVHCacheItem * search = (BVHCacheItem *)_search;
+
+       if(search->type == cached->type)
+       {
+               search->tree = cached->tree;            
+       }
+} 
+
+BVHTree *bvhcache_find(BVHCache *cache, int type)
+{
+       BVHCacheItem item;
+       item.type = type;
+       item.tree = NULL;
+
+       BLI_linklist_apply(*cache, bvhcacheitem_set_if_match, &item);
+       return item.tree;
+}
+
+void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type)
+{
+       BVHCacheItem *item = NULL;
+
+       assert( tree != NULL );
+       assert( bvhcache_find(cache, type) == NULL );
+
+       item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
+       assert( item != NULL );
+
+       item->type = type;
+       item->tree = tree;
+
+       BLI_linklist_prepend( cache, item );
+}
+
+
+void bvhcache_init(BVHCache *cache)
+{
+       *cache = NULL;
+}
+
+static void bvhcacheitem_free(void *_item)
+{
+       BVHCacheItem *item = (BVHCacheItem *)_item;
+
+       BLI_bvhtree_free(item->tree);
+       MEM_freeN(item);
+}
+
+
+void bvhcache_free(BVHCache *cache)
+{
+       BLI_linklist_free(*cache, (LinkNodeFreeFP)bvhcacheitem_free);
+       *cache = NULL;
+}
+
+
index 97e3bc9e9bd4a518ad2a643ddc083b145085a11f..16287d360b5fb392618355d9a54ca31201ca38f0 100644 (file)
@@ -7300,7 +7300,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived
        CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md);
 
        /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */
-       if(shrinkwrapModifier_requiredDataMask(md))
+       if(dataMask)
        {
                if(derivedData) dm = CDDM_copy(derivedData);
                else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
index 76af9a763eee1aabbe3c6fb9f7aa297308dac0b3..931519a1b4a5757f0bf120c90c21337087dafaab 100644 (file)
@@ -147,6 +147,7 @@ static float squared_dist(const float *a, const float *b)
 void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
 {
 
+       DerivedMesh *ss_mesh    = NULL;
        ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
 
        //remove loop dependencies on derived meshs (TODO should this be done elsewhere?)
@@ -157,23 +158,59 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
        //Configure Shrinkwrap calc data
        calc.smd = smd;
        calc.ob = ob;
-       calc.original = dm;
        calc.numVerts = numVerts;
        calc.vertexCos = vertexCos;
 
        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) );
+               calc.target = object_get_derived_final(smd->target, CD_MASK_BAREMESH);
 
-               //TODO there might be several "bugs" on non-uniform scales matrixs.. because it will no longer be nearest surface, not sphere projection
+               //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.keepDist = smd->keepDist;  //TODO: smd->keepDist is in global units.. must change to local
+               //TODO: smd->keepDist is in global units.. must change to local
+               calc.keepDist = smd->keepDist;
        }
 
 
+
+       calc.vgroup = get_named_vertexgroup_num(calc.ob, smd->vgroup_name);
+
+       if(dm != NULL)
+       {
+               //Setup arrays to get vertexs positions, normals and deform weights
+               calc.vert   = dm->getVertDataArray(dm, CD_MVERT);
+               calc.dvert  = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+               //Using vertexs positions/normals as if a subsurface was applied 
+               if(smd->subsurfLevels)
+               {
+                       SubsurfModifierData ssmd;
+                       memset(&ssmd, 0, sizeof(ssmd));
+                       ssmd.subdivType = ME_CC_SUBSURF;                //catmull clark
+                       ssmd.levels             = smd->subsurfLevels;   //levels
+
+                       ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, FALSE, NULL, 0, 0);
+
+                       if(ss_mesh)
+                       {
+                               calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT);
+                               if(calc.vert)
+                               {
+                                       //TRICKY: this code assumes subsurface will have the transformed original vertices
+                                       //in their original order at the end of the vert array.
+                                       calc.vert = calc.vert + ss_mesh->getNumVerts(ss_mesh) - dm->getNumVerts(dm);
+                               }
+                       }
+
+                       //Just to make sure we are not letting any memory behind
+                       assert(ssmd.emCache == NULL);
+                       assert(ssmd.mCache == NULL);
+               }
+       }
+
        //Projecting target defined - lets work!
        if(calc.target)
        {
@@ -194,8 +231,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
        }
 
        //free memory
-       if(calc.target)
-               calc.target->release( calc.target );
+       if(ss_mesh)
+               ss_mesh->release(ss_mesh);
 }
 
 /*
@@ -207,8 +244,6 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
 void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
 {
        int i;
-       const int vgroup                 = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
-       MDeformVert *const dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
 
        BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
        BVHTreeNearest  nearest  = NULL_BVHTreeNearest;
@@ -226,11 +261,20 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
        {
                float *co = calc->vertexCos[i];
                float tmp_co[3];
-               float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
+               float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup);
                if(weight == 0.0f) continue;
 
-               VECCOPY(tmp_co, co);
-               space_transform_apply(&calc->local2target, tmp_co); //Convert the coordinates to the tree coordinates
+
+               //Convert the vertex to tree coordinates
+               if(calc->vert)
+               {
+                       VECCOPY(tmp_co, calc->vert[i].co);
+               }
+               else
+               {
+                       VECCOPY(tmp_co, co);
+               }
+               space_transform_apply(&calc->local2target, tmp_co);
 
                //Use local proximity heuristics (to reduce the nearest search)
                //
@@ -333,177 +377,116 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
        int i;
 
        //Options about projection direction
-       const 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
-       DerivedMesh* ss_mesh = NULL;
-
-       //Vertex group data
-       const int vgroup                   = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
-       const MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
-
+       const char use_normal   = calc->smd->shrinkOpts;
+       float proj_axis[3]              = {0.0f, 0.0f, 0.0f};
 
        //Raycast and tree stuff
        BVHTreeRayHit hit;
-       BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;        //target
+       BVHTreeFromMesh treeData= NULL_BVHTreeFromMesh;
 
        //auxiliar target
-       DerivedMesh * aux_mesh = NULL;
-       BVHTreeFromMesh auxData= NULL_BVHTreeFromMesh;
+       DerivedMesh *auxMesh    = NULL;
+       BVHTreeFromMesh auxData = NULL_BVHTreeFromMesh;
        SpaceTransform local2aux;
 
-do
-{
+       //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;
+
 
        //Prepare data to retrieve the direction in which we should project each vertex
        if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
        {
-               //No Mvert information: jump to "free memory and return" part
-               if(calc->original == NULL) break;
-
-               if(calc->smd->subsurfLevels)
-               {
-                       SubsurfModifierData smd;
-                       memset(&smd, 0, sizeof(smd));
-                       smd.subdivType = ME_CC_SUBSURF;                 //catmull clark
-                       smd.levels = calc->smd->subsurfLevels;  //levels
-
-                       ss_mesh = subsurf_make_derived_from_derived(calc->original, &smd, FALSE, NULL, 0, 0);
-
-                       if(ss_mesh)
-                       {
-                               vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT);
-                               if(vert)
-                               {
-                                       //TRICKY: this code assumes subsurface will have the transformed original vertices
-                                       //in their original order at the end of the vert array.
-                                       vert = vert
-                                                + ss_mesh->getNumVerts(ss_mesh)
-                                                - calc->original->getNumVerts(calc->original);
-                               }
-                       }
-
-                       //To make sure we are not letting any memory behind
-                       assert(smd.emCache == NULL);
-                       assert(smd.mCache == NULL);
-               }
-               else
-                       vert = calc->original->getVertDataArray(calc->original, CD_MVERT);
-
-               //Not able to get vert information: jump to "free memory and return" part
-               if(vert == NULL) break;
+               if(calc->vert == NULL) return;
        }
        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
+               //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);
 
-               //Invalid projection direction: jump to "free memory and return" part
-               if(INPR(proj_axis, proj_axis) < FLT_EPSILON) break; 
+               //Invalid projection direction
+               if(INPR(proj_axis, proj_axis) < FLT_EPSILON)
+                       return; 
        }
 
-       //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)
-               break; //jump to "free memory and return" part
-
-
-       //Build target tree
-       BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6));
-       if(treeData.tree == NULL)
-               break; //jump to "free memory and return" part
-
-
-       //Build auxiliar target
        if(calc->smd->auxTarget)
        {
+               auxMesh = object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH);
                space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget);
-
-               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("Auxiliar target finalDerived mesh is null\n");
        }
 
-
-       //Now, everything is ready to project the vertexs!
-#pragma omp parallel for private(i,hit) schedule(static)
-       for(i = 0; i<calc->numVerts; ++i)
+       //After sucessufuly build the trees, start projection vertexs
+       if( bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6)
+       &&  (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6)))
        {
-               float *co = calc->vertexCos[i];
-               float tmp_co[3], tmp_no[3];
-               float lim = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
-               float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
 
-               if(weight == 0.0f) continue;
 
-               if(ss_mesh)
-               {
-                       VECCOPY(tmp_co, vert[i].co);
-               }
-               else
+#pragma omp parallel for private(i,hit) schedule(static)
+               for(i = 0; i<calc->numVerts; ++i)
                {
-                       VECCOPY(tmp_co, co);
-               }
+                       float *co = calc->vertexCos[i];
+                       float tmp_co[3], tmp_no[3];
+                       float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup);
 
+                       if(weight == 0.0f) continue;
 
-               if(vert)
-                       NormalShortToFloat(tmp_no, vert[i].no);
-               else
-                       VECCOPY( tmp_no, proj_axis );
-
+                       if(calc->vert)
+                       {
+                               VECCOPY(tmp_co, calc->vert[i].co);
+                               if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)
+                                       NormalShortToFloat(tmp_no, calc->vert[i].no);
+                               else
+                                       VECCOPY(tmp_no, proj_axis);
+                       }
+                       else
+                       {
+                               VECCOPY(tmp_co, co);
+                               VECCOPY(tmp_no, proj_axis);
+                       }
 
-               hit.index = -1;
-               hit.dist = lim;
 
+                       hit.index = -1;
+                       hit.dist = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that
 
-               //Project over positive direction of axis
-               if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR)
-               {
+                       //Project over positive direction of axis
+                       if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR)
+                       {
 
-                       if(auxData.tree)
-                               normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
+                               if(auxData.tree)
+                                       normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
 
-                       normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
-               }
+                               normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
+                       }
 
-               //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] };
+                       //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(auxData.tree)
-                               normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
+                               if(auxData.tree)
+                                       normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData);
 
-                       normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData);
-               }
+                               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(hit.index != -1)
+                       {
+                               VecLerpf(co, co, hit.co, weight);
+                       }
                }
        }
 
-
-//Simple do{} while(0) structure to allow to easily jump to the "free memory and return" part
-} while(0);
-
        //free data structures
-
        free_bvhtree_from_mesh(&treeData);
        free_bvhtree_from_mesh(&auxData);
-
-       if(aux_mesh)
-               aux_mesh->release(aux_mesh);
-
-       if(ss_mesh)
-               ss_mesh->release(ss_mesh);
 }
 
 /*
@@ -516,14 +499,9 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
 {
        int i;
 
-       const int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name);
-       const MDeformVert *const dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL;
-
        BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
        BVHTreeNearest  nearest  = NULL_BVHTreeNearest;
 
-
-
        //Create a bvh-tree of the given target
        BENCH(bvhtree_from_mesh_faces( &treeData, calc->target, 0.0, 2, 6));
        if(treeData.tree == NULL) return OUT_OF_MEMORY();
@@ -539,11 +517,18 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
        {
                float *co = calc->vertexCos[i];
                float tmp_co[3];
-               float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
+               float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup);
                if(weight == 0.0f) continue;
 
                //Convert the vertex to tree coordinates
-               VECCOPY(tmp_co, co);
+               if(calc->vert)
+               {
+                       VECCOPY(tmp_co, calc->vert[i].co);
+               }
+               else
+               {
+                       VECCOPY(tmp_co, co);
+               }
                space_transform_apply(&calc->local2target, tmp_co);
 
                //Use local proximity heuristics (to reduce the nearest search)
@@ -582,7 +567,6 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
                }
        }
 
-
        free_bvhtree_from_mesh(&treeData);
 }
 
index f393139ee3e1a6af5a4b83afd933a8619e0d4513..5aec47965fcc9b82ee041d3d9263ad2bbed91057 100644 (file)
@@ -1887,12 +1887,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        height = 94;
                } else if (md->type==eModifierType_Shrinkwrap) {
                        ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
-                       height = 86 + 3;
+                       height = 105 + 3;
+
                        if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
-                       {
                                height += 19*5;
-                               if(smd->projAxis == 0) height += 19;
-                       }
                        else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
                                height += 19;
 
@@ -2542,16 +2540,14 @@ 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.");
 
+                       uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",          lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
+
                        if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
 
 
                                /* 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");
-                               if(smd->projAxis == 0)
-                               {
-                                       uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",          lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
-                               }
 
                                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");