diff options
-rw-r--r-- | source/blender/blenkernel/BKE_bvhutils.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/bvhutils.c | 66 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_runtime.c | 130 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_mesh_types.h | 19 |
6 files changed, 223 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 1b4bb08756b..1157e20d6ac 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -40,6 +40,7 @@ struct DerivedMesh; struct BMEditMesh; +struct Mesh; struct MVert; struct MFace; @@ -142,6 +143,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex( const BLI_bitmap *mask, int looptri_num_active, float epsilon, int tree_type, int axis, BVHCache **bvhCache); +BVHTree *BKE_bvhtree_from_mesh_looptri( + struct BVHTreeFromMesh *data, struct Mesh *mesh, float epsilon, int tree_type, int axis); BVHTree *bvhtree_from_mesh_looptri_ex( struct BVHTreeFromMesh *data, const struct MVert *vert, const bool vert_allocated, diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 485132bfa6d..2adc1dbb6e3 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -182,7 +182,11 @@ int BKE_mesh_mselect_find(struct Mesh *me, int index, int type); int BKE_mesh_mselect_active_get(struct Mesh *me, int type); void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type); +/* *** mesh_runtime.c *** */ +void BKE_mesh_runtime_recalc_looptri(struct Mesh *mesh); +int BKE_mesh_get_looptri_num(struct Mesh *mesh); +const struct MLoopTri *BKE_mesh_get_looptri_array(struct Mesh *mesh); /* *** mesh_evaluate.c *** */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9e241b7fa81..83241d3c4c7 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -143,6 +143,7 @@ set(SRC intern/mesh_mapping.c intern/mesh_merge.c intern/mesh_remap.c + intern/mesh_runtime.c intern/mesh_tangent.c intern/mesh_validate.c intern/modifier.c diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 0240bb4b624..00aa89b3776 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -34,6 +34,7 @@ #include <math.h> #include <assert.h> +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "BLI_utildefines.h" @@ -43,6 +44,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_editmesh.h" +#include "BKE_mesh.h" #include "MEM_guardedalloc.h" @@ -1161,6 +1163,70 @@ BVHTree *bvhtree_from_mesh_get( return tree; } +/* This is a Mesh-specific copy of bvhtree_from_mesh_looptri() */ +/** + * Builds a bvh tree where nodes are the looptri faces of the given mesh. + * + * \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces + */ +BVHTree *BKE_bvhtree_from_mesh_looptri( + BVHTreeFromMesh *data, Mesh *mesh, + float epsilon, int tree_type, int axis) +{ + BVHTree *tree; + MVert *mvert = NULL; + MLoop *mloop = NULL; + const MLoopTri *looptri = NULL; + + BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); + tree = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_LOOPTRI); + BLI_rw_mutex_unlock(&cache_rwlock); + + mvert = mesh->mvert; + mloop = mesh->mloop; + looptri = BKE_mesh_get_looptri_array(mesh); + + /* Not in cache */ + if (tree == NULL) { + 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_get_looptri_num(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( + epsilon, tree_type, axis, + 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); + } + else { + /* printf("BVHTree is already build, using cached tree\n"); */ + } + + if (tree) { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_looptri_setup_data( + data, tree, true, + mvert, false, + mloop, false, + looptri, false); + } + else { + memset(data, 0, sizeof(*data)); + } + + return tree; +} + /** \} */ diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c new file mode 100644 index 00000000000..02caf454b7e --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -0,0 +1,130 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mesh_runtime.c + * \ingroup bke + */ + +#include "atomic_ops.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_math_geom.h" +#include "BLI_threads.h" + +#include "BKE_mesh.h" + + +static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; + + +/* This is a ported copy of DM_ensure_looptri_data(dm) */ +/** + * Ensure the array is large enough + * + * /note This function must always be thread-protected by caller. It should only be used by internal code. + */ +static void mesh_ensure_looptri_data(Mesh *mesh) +{ + const unsigned int totpoly = mesh->totpoly; + const int looptris_num = poly_to_tri_count(totpoly, mesh->totloop); + + BLI_assert(mesh->runtime.looptris.array_wip == NULL); + + SWAP(MLoopTri *, mesh->runtime.looptris.array, mesh->runtime.looptris.array_wip); + + if ((looptris_num > mesh->runtime.looptris.num_alloc) || + (looptris_num < mesh->runtime.looptris.num_alloc * 2) || + (totpoly == 0)) + { + MEM_SAFE_FREE(mesh->runtime.looptris.array_wip); + mesh->runtime.looptris.num_alloc = 0; + mesh->runtime.looptris.num = 0; + } + + if (totpoly) { + if (mesh->runtime.looptris.array_wip == NULL) { + mesh->runtime.looptris.array_wip = MEM_malloc_arrayN(looptris_num, sizeof(*mesh->runtime.looptris.array_wip), __func__); + mesh->runtime.looptris.num_alloc = looptris_num; + } + + mesh->runtime.looptris.num = looptris_num; + } +} + +/* This is a ported copy of CDDM_recalc_looptri(dm). */ +void BKE_mesh_runtime_recalc_looptri(Mesh *mesh) +{ + mesh_ensure_looptri_data(mesh); + BLI_assert(mesh->totpoly == 0 || mesh->runtime.looptris.array_wip != NULL); + + BKE_mesh_recalc_looptri( + mesh->mloop, mesh->mpoly, + mesh->mvert, + mesh->totloop, mesh->totpoly, + mesh->runtime.looptris.array_wip); + + BLI_assert(mesh->runtime.looptris.array == NULL); + atomic_cas_ptr((void **)&mesh->runtime.looptris.array, mesh->runtime.looptris.array, mesh->runtime.looptris.array_wip); + mesh->runtime.looptris.array_wip = NULL; +} + +/* This is a ported copy of dm_getNumLoopTri(dm). */ +int BKE_mesh_get_looptri_num(Mesh *mesh) +{ + const int numlooptris = poly_to_tri_count(mesh->totpoly, mesh->totloop); + BLI_assert(ELEM(mesh->runtime.looptris.num, 0, numlooptris)); + return numlooptris; +} + +/* This is a ported copy of dm_getLoopTriArray(dm). */ +const MLoopTri *BKE_mesh_get_looptri_array(Mesh *mesh) +{ + MLoopTri *looptri; + + BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ); + looptri = mesh->runtime.looptris.array; + BLI_rw_mutex_unlock(&loops_cache_lock); + + if (looptri != NULL) { + BLI_assert(BKE_mesh_get_looptri_num(mesh) == mesh->runtime.looptris.num); + } + else { + BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE); + /* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already + * recomputed those looptris. */ + if (mesh->runtime.looptris.array == NULL) { + BKE_mesh_runtime_recalc_looptri(mesh); + } + looptri = mesh->runtime.looptris.array; + BLI_rw_mutex_unlock(&loops_cache_lock); + } + return looptri; +} diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index d951f67a7c4..af81ac8423b 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -39,11 +39,13 @@ struct AnimData; struct Ipo; struct Key; +struct LinkNode; struct MCol; struct MEdge; struct MFace; struct MLoop; struct MLoopCol; +struct MLoopTri; struct MLoopUV; struct MPoly; struct MTexPoly; @@ -65,6 +67,18 @@ typedef struct EditMeshData { const float (*polyCos)[3]; } EditMeshData; + +/** + * \warning Typical access is done via #BKE_mesh_get_looptri_array, #BKE_mesh_get_looptri_num. + */ +struct LooptrisData { + /* WARNING! swapping between array (ready-to-be-used data) and array_wip (where data is actually computed) + * shall always be protected by same lock as one used for looptris computing. */ + struct MLoopTri *array, *array_wip; + int num; + int num_alloc; +}; + /* not saved in file! */ typedef struct MeshRuntime { struct EditMeshData *edit_data; @@ -74,6 +88,11 @@ typedef struct MeshRuntime { int64_t cd_dirty_edge; int64_t cd_dirty_loop; int64_t cd_dirty_poly; + + struct LooptrisData looptris; + + /** 'BVHCache', for 'BKE_bvhutil.c' */ + struct LinkNode *bvh_cache; } MeshRuntime; typedef struct Mesh { |