[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