[Bf-blender-cvs] [f87f8532c3c] master: Cleanup: split bmesh normal calculation into separate files
Campbell Barton
noreply at git.blender.org
Mon Jun 7 16:50:53 CEST 2021
Commit: f87f8532c3c2735b8cbf47cc1e23d20bcfb118e0
Author: Campbell Barton
Date: Tue Jun 8 00:45:54 2021 +1000
Branches: master
https://developer.blender.org/rBf87f8532c3c2735b8cbf47cc1e23d20bcfb118e0
Cleanup: split bmesh normal calculation into separate files
===================================================================
M source/blender/bmesh/CMakeLists.txt
M source/blender/bmesh/bmesh.h
M source/blender/bmesh/intern/bmesh_mesh.c
M source/blender/bmesh/intern/bmesh_mesh.h
A source/blender/bmesh/intern/bmesh_mesh_normals.c
A source/blender/bmesh/intern/bmesh_mesh_normals.h
===================================================================
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 4bd88ae62d7..ec282888ffa 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -102,10 +102,12 @@ set(SRC
intern/bmesh_mesh_convert.h
intern/bmesh_mesh_duplicate.c
intern/bmesh_mesh_duplicate.h
- intern/bmesh_mesh_tessellate.c
- intern/bmesh_mesh_tessellate.h
+ intern/bmesh_mesh_normals.c
+ intern/bmesh_mesh_normals.h
intern/bmesh_mesh_partial_update.c
intern/bmesh_mesh_partial_update.h
+ intern/bmesh_mesh_tessellate.c
+ intern/bmesh_mesh_tessellate.h
intern/bmesh_mesh_validate.c
intern/bmesh_mesh_validate.h
intern/bmesh_mods.c
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index d8c3f4ce556..a5241f6b36d 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -215,6 +215,7 @@ extern "C" {
#include "intern/bmesh_mesh.h"
#include "intern/bmesh_mesh_convert.h"
#include "intern/bmesh_mesh_duplicate.h"
+#include "intern/bmesh_mesh_normals.h"
#include "intern/bmesh_mesh_partial_update.h"
#include "intern/bmesh_mesh_tessellate.h"
#include "intern/bmesh_mesh_validate.h"
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 72ceb49ef19..d0c6bc83088 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -25,22 +25,14 @@
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
-#include "BLI_bitmap.h"
-#include "BLI_linklist_stack.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_stack.h"
-#include "BLI_task.h"
#include "BLI_utildefines.h"
-#include "BKE_editmesh.h"
-#include "BKE_global.h"
+#include "BKE_customdata.h"
#include "BKE_mesh.h"
-#include "BKE_multires.h"
-#include "atomic_ops.h"
-
-#include "intern/bmesh_private.h"
+#include "bmesh.h"
/* used as an extern, defined in bmesh.h */
const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512};
@@ -318,1786 +310,6 @@ void BM_mesh_free(BMesh *bm)
MEM_freeN(bm);
}
-/**
- * Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos
- */
-
-/* We use that existing internal API flag,
- * assuming no other tool using it would run concurrently to clnors editing. */
-#define BM_LNORSPACE_UPDATE _FLAG_MF
-
-typedef struct BMEdgesCalcVectorsData {
- /* Read-only data. */
- const float (*vcos)[3];
-
- /* Read-write data, but no need to protect it, no concurrency to fear here. */
- float (*edgevec)[3];
-} BMEdgesCalcVectorsData;
-
-static void mesh_edges_calc_vectors_cb(void *userdata, MempoolIterData *mp_e)
-{
- BMEdgesCalcVectorsData *data = userdata;
- BMEdge *e = (BMEdge *)mp_e;
-
- if (e->l) {
- const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co;
- const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co;
- sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co);
- normalize_v3(data->edgevec[BM_elem_index_get(e)]);
- }
- else {
- /* the edge vector will not be needed when the edge has no radial */
- }
-}
-
-static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3])
-{
- BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0));
-
- BMEdgesCalcVectorsData data = {
- .vcos = vcos,
- .edgevec = edgevec,
- };
-
- BM_iter_parallel(
- bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT);
-}
-
-typedef struct BMVertsCalcNormalsData {
- /* Read-only data. */
- const float (*fnos)[3];
- const float (*edgevec)[3];
- const float (*vcos)[3];
-
- /* Read-write data, protected by an atomic-based fake spin-lock like system. */
- float (*vnos)[3];
-} BMVertsCalcNormalsData;
-
-static void mesh_verts_calc_normals_accum(
- BMFace *f,
- const float *f_no,
- const float (*edgevec)[3],
-
- /* Read-write data, protected by an atomic-based fake spin-lock like system. */
- float (*vnos)[3])
-{
-#define FLT_EQ_NONAN(_fa, _fb) (*((const uint32_t *)&_fa) == *((const uint32_t *)&_fb))
-
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const float *e1diff, *e2diff;
- float dotprod;
- float fac;
-
- /* calculate the dot product of the two edges that
- * meet at the loop's vertex */
- e1diff = edgevec[BM_elem_index_get(l_iter->prev->e)];
- e2diff = edgevec[BM_elem_index_get(l_iter->e)];
- dotprod = dot_v3v3(e1diff, e2diff);
-
- /* edge vectors are calculated from e->v1 to e->v2, so
- * adjust the dot product if one but not both loops
- * actually runs from from e->v2 to e->v1 */
- if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
- dotprod = -dotprod;
- }
-
- fac = saacos(-dotprod);
-
- if (fac != fac) { /* NAN detection. */
- /* Degenerated case, nothing to do here, just ignore that vertex. */
- continue;
- }
-
- /* accumulate weighted face normal into the vertex's normal */
- float *v_no = vnos ? vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
-
- /* This block is a lockless threadsafe madd_v3_v3fl.
- * It uses the first float of the vector as a sort of cheap spin-lock,
- * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise.
- * It also assumes that collisions between threads are highly unlikely,
- * else performances would be quite bad here. */
- float virtual_lock = v_no[0];
- while (true) {
- /* This loops until following conditions are met:
- * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try).
- * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread.
- */
- const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX);
- if (FLT_EQ_NONAN(vl, virtual_lock) && vl != FLT_MAX) {
- break;
- }
- virtual_lock = vl;
- }
- BLI_assert(v_no[0] == FLT_MAX);
- /* Now we own that normal value, and can change it.
- * But first scalar of the vector must not be changed yet, it's our lock! */
- virtual_lock += f_no[0] * fac;
- v_no[1] += f_no[1] * fac;
- v_no[2] += f_no[2] * fac;
- /* Second atomic operation to 'release'
- * our lock on that vector and set its first scalar value. */
- /* Note that we do not need to loop here, since we 'locked' v_no[0],
- * nobody should have changed it in the mean time. */
- virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock);
- BLI_assert(virtual_lock == FLT_MAX);
-
- } while ((l_iter = l_iter->next) != l_first);
-
-#undef FLT_EQ_NONAN
-}
-
-static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f)
-{
- BMVertsCalcNormalsData *data = userdata;
- BMFace *f = (BMFace *)mp_f;
- const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no;
- mesh_verts_calc_normals_accum(f, f_no, data->edgevec, data->vnos);
-}
-
-static void mesh_verts_calc_normals_normalize_cb(void *userdata, MempoolIterData *mp_v)
-{
- BMVertsCalcNormalsData *data = userdata;
- BMVert *v = (BMVert *)mp_v;
-
- float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no;
- if (UNLIKELY(normalize_v3(v_no) == 0.0f)) {
- const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co;
- normalize_v3_v3(v_no, v_co);
- }
-}
-
-static void bm_mesh_verts_calc_normals(BMesh *bm,
- const float (*edgevec)[3],
- const float (*fnos)[3],
- const float (*vcos)[3],
- float (*vnos)[3])
-{
- BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0));
-
- BMVertsCalcNormalsData data = {
- .fnos = fnos,
- .edgevec = edgevec,
- .vcos = vcos,
- .vnos = vnos,
- };
-
- BM_iter_parallel(
- bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT);
-
- /* normalize the accumulated vertex normals */
- BM_iter_parallel(bm,
- BM_VERTS_OF_MESH,
- mesh_verts_calc_normals_normalize_cb,
- &data,
- bm->totvert >= BM_OMP_LIMIT);
-}
-
-static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *mp_f)
-{
- BMFace *f = (BMFace *)mp_f;
-
- BM_face_normal_update(f);
-}
-
-/**
- * \brief BMesh Compute Normals
- *
- * Updates the normals of a mesh.
- */
-void BM_mesh_normals_update(BMesh *bm)
-{
- float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
-
- /* Parallel mempool iteration does not allow generating indices inline anymore... */
- BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE));
-
- /* calculate all face normals */
- BM_iter_parallel(
- bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT);
-
- /* Zero out vertex normals */
- BMIter viter;
- BMVert *v;
- int i;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_index_set(v, i); /* set_inline */
- zero_v3(v->no);
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- /* Compute normalized direction vectors for each edge.
- * Directions will be used for calculating the weights of the face normals on the vertex normals.
- */
- bm_mesh_edges_calc_vectors(bm, edgevec, NULL);
-
- /* Add weighted face normals to vertices, and normalize vert normals. */
- bm_mesh_verts_calc_normals(bm, edgevec, NULL, NULL, NULL);
- MEM_freeN(edgevec);
-}
-
-static void mesh_faces_parallel_range_calc_normals_cb(
- void *userdata, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
-{
- BMFace *f = ((BMFace **)userdata)[iter];
- BM_face_normal_update(f);
-}
-
-static void mesh_edges_parallel_range_calc_vectors_cb(
- void *userdata, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
-{
- BMEdge *e = ((BMEdge **)((void **)userdata)[0])[iter];
- float *r_edgevec = ((float(*)[3])((void **)userdata)[1])[iter];
- sub_v3_v3v3(r_edgevec, e->v1->co, e->v2->co);
- normalize_v3(r_edgevec);
-}
-
-static void mesh_verts_parallel_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list