BKE: bvhutils: Port bvhtree_from_mesh_get to take a Mesh param instead of a DerivedMesh.
authorGermano <germano.costa@ig.com.br>
Tue, 8 May 2018 23:00:51 +0000 (20:00 -0300)
committerGermano <germano.costa@ig.com.br>
Tue, 8 May 2018 23:00:51 +0000 (20:00 -0300)
Differential Revision: https://developer.blender.org/D3227

source/blender/blenkernel/BKE_bvhutils.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/bvhutils.c
source/blender/blenkernel/intern/mesh.c

index 1157e20d6ac3270852c290f788918e764f485fc7..24f4765bd9e110ad4eac76e1a45949c1ba7895b2 100644 (file)
@@ -157,6 +157,10 @@ BVHTree *bvhtree_from_mesh_get(
         struct BVHTreeFromMesh *data, struct DerivedMesh *mesh,
         const int type, const int tree_type);
 
+BVHTree *BKE_bvhtree_from_mesh_get(
+        struct BVHTreeFromMesh *data, struct Mesh *mesh,
+        const int type, const int tree_type);
+
 /**
  * Frees data allocated by a call to bvhtree_from_mesh_*.
  */
@@ -192,7 +196,6 @@ enum {
 BVHTree *bvhcache_find(BVHCache *cache, int type);
 bool     bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree);
 void     bvhcache_insert(BVHCache **cache_p, BVHTree *tree, int type);
-void     bvhcache_init(BVHCache **cache_p);
 void     bvhcache_free(BVHCache **cache_p);
 
 
index dacc0c35e0ff59db6e99d93db53828689fb90a90..003d80c29cc34e0aa207ac751851389eaab25443 100644 (file)
@@ -322,7 +322,7 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->getPolyDataArray = DM_get_poly_data_layer;
        dm->getLoopDataArray = DM_get_loop_data_layer;
 
-       bvhcache_init(&dm->bvhCache);
+       dm->bvhCache = NULL;
 }
 
 /**
index 5c2d81f5841be75f2a8c5af38951984faf1b2988..4731b444221d92b005f072e00de3c326deb727bd 100644 (file)
@@ -1227,6 +1227,192 @@ BVHTree *BKE_bvhtree_from_mesh_looptri(
        return tree;
 }
 
+/**
+ * Builds or queries a bvhcache for the cache bvhtree of the request type.
+ */
+BVHTree *BKE_bvhtree_from_mesh_get(
+        struct BVHTreeFromMesh *data, struct Mesh *mesh,
+        const int type, const int tree_type)
+{
+       BVHTree *tree = NULL;
+
+       BVHTree_NearestPointCallback nearest_callback = NULL;
+       BVHTree_RayCastCallback raycast_callback = NULL;
+
+       MVert *mvert = NULL;
+       MEdge *medge = NULL;
+       MFace *mface = NULL;
+       MLoop *mloop = NULL;
+       const MLoopTri *looptri = NULL;
+       bool vert_allocated = false;
+       bool edge_allocated = false;
+       bool face_allocated = false;
+       bool loop_allocated = false;
+       bool looptri_allocated = false;
+
+       BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+       tree = bvhcache_find(mesh->runtime.bvh_cache, type);
+       BLI_rw_mutex_unlock(&cache_rwlock);
+
+       switch (type) {
+               case BVHTREE_FROM_VERTS:
+                       raycast_callback = mesh_verts_spherecast;
+
+                       mvert = mesh->mvert;
+
+                       if (tree == NULL) {
+                               /* Not in cache */
+                               BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+                               tree = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_VERTS);
+                               if (tree == NULL) {
+                                       tree = bvhtree_from_mesh_verts_create_tree(
+                                               0.0, tree_type, 6, mvert, mesh->totvert, NULL, -1);
+
+                                       if (tree) {
+                                               /* Save on cache for later use */
+                                               /* printf("BVHTree built and saved on cache\n"); */
+                                               bvhcache_insert(&mesh->runtime.bvh_cache, tree, BVHTREE_FROM_VERTS);
+                                       }
+                               }
+                               BLI_rw_mutex_unlock(&cache_rwlock);
+                       }
+                       break;
+
+               case BVHTREE_FROM_EDGES:
+                       nearest_callback = mesh_edges_nearest_point;
+                       raycast_callback = mesh_edges_spherecast;
+
+                       mvert = mesh->mvert;
+                       medge = mesh->medge;
+
+                       if (tree == NULL) {
+                               /* Not in cache */
+                               BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+                               tree = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_EDGES);
+                               if (tree == NULL) {
+                                       tree = bvhtree_from_mesh_edges_create_tree(
+                                               mvert, medge, mesh->totedge,
+                                               NULL, -1, 0.0, tree_type, 6);
+
+                                       if (tree) {
+                                               /* Save on cache for later use */
+                                               /* printf("BVHTree built and saved on cache\n"); */
+                                               bvhcache_insert(&mesh->runtime.bvh_cache, tree, BVHTREE_FROM_EDGES);
+                                       }
+                               }
+                               BLI_rw_mutex_unlock(&cache_rwlock);
+                       }
+                       break;
+
+               case BVHTREE_FROM_FACES:
+                       nearest_callback = mesh_faces_nearest_point;
+                       raycast_callback = mesh_faces_spherecast;
+
+                       mvert = mesh->mvert;
+                       mface = mesh->mface;
+
+                       if (tree == NULL) {
+                               /* Not in cache */
+                               BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+                               tree = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_FACES);
+                               if (tree == NULL) {
+                                       int num_faces = mesh->totface;
+                                       BLI_assert(!(num_faces == 0 && mesh->totpoly != 0));
+
+                                       tree = bvhtree_from_mesh_faces_create_tree(
+                                               0.0, tree_type, 6, mvert, mface, num_faces, NULL, -1);
+
+                                       if (tree) {
+                                               /* Save on cache for later use */
+                                               /* printf("BVHTree built and saved on cache\n"); */
+                                               bvhcache_insert(&mesh->runtime.bvh_cache, tree, BVHTREE_FROM_FACES);
+                                       }
+                               }
+                               BLI_rw_mutex_unlock(&cache_rwlock);
+                       }
+                       break;
+
+               case BVHTREE_FROM_LOOPTRI:
+                       nearest_callback = mesh_looptri_nearest_point;
+                       raycast_callback = mesh_looptri_spherecast;
+
+                       mvert = mesh->mvert;
+                       mloop = mesh->mloop;
+
+                       /* TODO: store looptris somewhere? */
+                       looptri = BKE_mesh_runtime_looptri_ensure(mesh);
+
+                       if (tree == NULL) {
+                               /* Not in cache */
+                               BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+                               tree = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_LOOPTRI);
+                               if (tree == NULL) {
+                                       int looptri_num = BKE_mesh_runtime_looptri_len(mesh);
+                                       /* this assert checks we have looptris,
+                                       * if not caller should use DM_ensure_looptri() */
+                                       BLI_assert(!(looptri_num == 0 && mesh->totpoly != 0));
+
+                                       tree = bvhtree_from_mesh_looptri_create_tree(
+                                               0.0, tree_type, 6,
+                                               mvert, mloop, looptri, looptri_num, NULL, -1);
+                                       if (tree) {
+                                               /* Save on cache for later use */
+                                               /* printf("BVHTree built and saved on cache\n"); */
+                                               bvhcache_insert(&mesh->runtime.bvh_cache, tree, BVHTREE_FROM_LOOPTRI);
+                                       }
+                               }
+                               BLI_rw_mutex_unlock(&cache_rwlock);
+                       }
+                       break;
+       }
+
+       if (tree != NULL) {
+#ifdef DEBUG
+               if (BLI_bvhtree_get_tree_type(tree) != tree_type) {
+                       printf("tree_type %d obtained instead of %d\n", BLI_bvhtree_get_tree_type(tree), tree_type);
+               }
+#endif
+               data->tree = tree;
+
+               data->nearest_callback = nearest_callback;
+               data->raycast_callback = raycast_callback;
+
+               data->vert = mvert;
+               data->edge = medge;
+               data->face = mface;
+               data->loop = mloop;
+               data->looptri = looptri;
+               data->vert_allocated = vert_allocated;
+               data->edge_allocated = edge_allocated;
+               data->edge_allocated = edge_allocated;
+               data->loop_allocated = loop_allocated;
+               data->looptri_allocated = looptri_allocated;
+
+               data->cached = true;
+       }
+       else {
+               if (vert_allocated) {
+                       MEM_freeN(mvert);
+               }
+               if (edge_allocated) {
+                       MEM_freeN(medge);
+               }
+               if (face_allocated) {
+                       MEM_freeN(mface);
+               }
+               if (loop_allocated) {
+                       MEM_freeN(mloop);
+               }
+               if (looptri_allocated) {
+                       MEM_freeN((void*)looptri);
+               }
+
+               memset(data, 0, sizeof(*data));
+       }
+
+       return tree;
+}
+
 /** \} */
 
 
@@ -1330,13 +1516,8 @@ void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, int type)
 }
 
 /**
- * inits and frees a bvhcache
+ * frees a bvhcache
  */
-void bvhcache_init(BVHCache **cache_p)
-{
-       *cache_p = NULL;
-}
-
 static void bvhcacheitem_free(void *_item)
 {
        BVHCacheItem *item = (BVHCacheItem *)_item;
index b0fb9b735ff70904a4fe41e3eb9572f613bdf44a..aa64ed181e49f13581b9d95b7dba14f0250c3e98 100644 (file)
@@ -505,6 +505,9 @@ void BKE_mesh_free(Mesh *me)
        MEM_SAFE_FREE(me->bb);
        MEM_SAFE_FREE(me->mselect);
        MEM_SAFE_FREE(me->edit_btmesh);
+
+       MEM_SAFE_FREE(me->runtime.looptris.array);
+       bvhcache_free(&me->runtime.bvh_cache);
 }
 
 static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
@@ -541,6 +544,8 @@ void BKE_mesh_init(Mesh *me)
        CustomData_reset(&me->fdata);
        CustomData_reset(&me->pdata);
        CustomData_reset(&me->ldata);
+
+       me->runtime.bvh_cache = NULL;
 }
 
 Mesh *BKE_mesh_add(Main *bmain, const char *name)
@@ -583,6 +588,7 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int
 
        me_dst->edit_btmesh = NULL;
        me_dst->runtime.batch_cache = NULL;
+       me_dst->runtime.bvh_cache = NULL;
 
        me_dst->mselect = MEM_dupallocN(me_dst->mselect);
        me_dst->bb = MEM_dupallocN(me_dst->bb);