Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_normals.cc')
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc242
1 files changed, 149 insertions, 93 deletions
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index 47ea55be871..08a17060549 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -38,7 +38,9 @@
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
+#include "BLI_math_vec_types.hh"
#include "BLI_memarena.h"
+#include "BLI_span.hh"
#include "BLI_stack.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
@@ -50,6 +52,8 @@
#include "atomic_ops.h"
+using blender::Span;
+
// #define DEBUG_TIME
#ifdef DEBUG_TIME
@@ -109,6 +113,52 @@ void BKE_mesh_normals_tag_dirty(Mesh *mesh)
mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
}
+float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
+{
+ CustomData_duplicate_referenced_layer(&mesh->vdata, CD_NORMAL, mesh->totvert);
+ return (float(*)[3])CustomData_add_layer(
+ &mesh->vdata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totvert);
+}
+
+float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
+{
+ CustomData_duplicate_referenced_layer(&mesh->pdata, CD_NORMAL, mesh->totpoly);
+ return (float(*)[3])CustomData_add_layer(
+ &mesh->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totpoly);
+}
+
+void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
+{
+ mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
+ BKE_mesh_assert_normals_dirty_or_calculated(mesh);
+}
+
+void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
+{
+ mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL;
+ BKE_mesh_assert_normals_dirty_or_calculated(mesh);
+}
+
+bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
+{
+ return mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL;
+}
+
+bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
+{
+ return mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL;
+}
+
+void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
+{
+ if (!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)) {
+ BLI_assert(CustomData_has_layer(&mesh->vdata, CD_NORMAL) || mesh->totvert == 0);
+ }
+ if (!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL)) {
+ BLI_assert(CustomData_has_layer(&mesh->pdata, CD_NORMAL) || mesh->totpoly == 0);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -161,8 +211,6 @@ void BKE_mesh_calc_normals_poly(const MVert *mvert,
/* -------------------------------------------------------------------- */
/** \name Mesh Normal Calculation (Polygons & Vertices)
*
- * Implement #BKE_mesh_calc_normals_poly_and_vertex,
- *
* Take care making optimizations to this function as improvements to low-poly
* meshes can slow down high-poly meshes. For details on performance, see D11993.
* \{ */
@@ -253,18 +301,16 @@ static void mesh_calc_normals_poly_and_vertex_finalize_fn(
/* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
normalize_v3_v3(no, mv->co);
}
-
- normal_float_to_short_v3(mv->no, no);
}
-void BKE_mesh_calc_normals_poly_and_vertex(MVert *mvert,
- const int mvert_len,
- const MLoop *mloop,
- const int UNUSED(mloop_len),
- const MPoly *mpoly,
- const int mpoly_len,
- float (*r_poly_normals)[3],
- float (*r_vert_normals)[3])
+static void mesh_calc_normals_poly_and_vertex(MVert *mvert,
+ const int mvert_len,
+ const MLoop *mloop,
+ const int UNUSED(mloop_len),
+ const MPoly *mpoly,
+ const int mpoly_len,
+ float (*r_poly_normals)[3],
+ float (*r_vert_normals)[3])
{
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@@ -308,12 +354,81 @@ void BKE_mesh_calc_normals_poly_and_vertex(MVert *mvert,
/** \name Mesh Normal Calculation
* \{ */
-void BKE_mesh_ensure_normals(Mesh *mesh)
+const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
{
- if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
- BKE_mesh_calc_normals(mesh);
+ if (!(BKE_mesh_vertex_normals_are_dirty(mesh) || BKE_mesh_poly_normals_are_dirty(mesh))) {
+ BLI_assert(CustomData_has_layer(&mesh->vdata, CD_NORMAL) || mesh->totvert == 0);
+ return (const float(*)[3])CustomData_get_layer(&mesh->vdata, CD_NORMAL);
+ }
+
+ if (mesh->totvert == 0) {
+ return nullptr;
+ }
+
+ ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
+ BLI_mutex_lock(normals_mutex);
+ if (!(BKE_mesh_vertex_normals_are_dirty(mesh) || BKE_mesh_poly_normals_are_dirty(mesh))) {
+ BLI_assert(CustomData_has_layer(&mesh->vdata, CD_NORMAL));
+ BLI_mutex_unlock(normals_mutex);
+ return (const float(*)[3])CustomData_get_layer(&mesh->vdata, CD_NORMAL);
}
- BLI_assert((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) == 0);
+
+ Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
+
+ float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh_mutable);
+ float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable);
+
+ mesh_calc_normals_poly_and_vertex(mesh_mutable.mvert,
+ mesh_mutable.totvert,
+ mesh_mutable.mloop,
+ mesh_mutable.totloop,
+ mesh_mutable.mpoly,
+ mesh_mutable.totpoly,
+ poly_normals,
+ vert_normals);
+
+ BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable);
+ BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
+
+ BLI_mutex_unlock(normals_mutex);
+ return vert_normals;
+}
+
+const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
+{
+ if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
+ BLI_assert(CustomData_has_layer(&mesh->pdata, CD_NORMAL) || mesh->totpoly == 0);
+ return (const float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ }
+
+ if (mesh->totpoly == 0) {
+ return nullptr;
+ }
+
+ ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
+ BLI_mutex_lock(normals_mutex);
+ if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
+ BLI_assert(CustomData_has_layer(&mesh->pdata, CD_NORMAL));
+ BLI_mutex_unlock(normals_mutex);
+ return (const float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ }
+
+ Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
+
+ float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable);
+
+ BKE_mesh_calc_normals_poly(mesh_mutable.mvert,
+ mesh_mutable.totvert,
+ mesh_mutable.mloop,
+ mesh_mutable.totloop,
+ mesh_mutable.mpoly,
+ mesh_mutable.totpoly,
+ poly_normals);
+
+ BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
+
+ BLI_mutex_unlock(normals_mutex);
+ return poly_normals;
}
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
@@ -321,7 +436,8 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
- /* Run code below. */
+ BKE_mesh_vertex_normals_ensure(mesh);
+ BKE_mesh_poly_normals_ensure(mesh);
break;
case ME_WRAPPER_TYPE_BMESH: {
struct BMEditMesh *em = mesh->edit_mesh;
@@ -333,47 +449,6 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
return;
}
}
-
- float(*poly_nors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
- const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0;
- const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL ||
- poly_nors == nullptr);
-
- if (do_vert_normals || do_poly_normals) {
- const bool do_add_poly_nors_cddata = (poly_nors == nullptr);
- if (do_add_poly_nors_cddata) {
- poly_nors = (float(*)[3])MEM_malloc_arrayN(
- (size_t)mesh->totpoly, sizeof(*poly_nors), __func__);
- }
-
- /* Calculate poly/vert normals. */
- if (do_vert_normals) {
- BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
- mesh->totvert,
- mesh->mloop,
- mesh->totloop,
- mesh->mpoly,
- mesh->totpoly,
- poly_nors,
- nullptr);
- }
- else {
- BKE_mesh_calc_normals_poly(mesh->mvert,
- mesh->totvert,
- mesh->mloop,
- mesh->totloop,
- mesh->mpoly,
- mesh->totpoly,
- poly_nors);
- }
-
- if (do_add_poly_nors_cddata) {
- CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, poly_nors, mesh->totpoly);
- }
-
- mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
- mesh->runtime.cd_dirty_poly &= ~CD_MASK_NORMAL;
- }
}
void BKE_mesh_calc_normals(Mesh *mesh)
@@ -381,18 +456,10 @@ void BKE_mesh_calc_normals(Mesh *mesh)
#ifdef DEBUG_TIME
TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
#endif
- BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
- mesh->totvert,
- mesh->mloop,
- mesh->totloop,
- mesh->mpoly,
- mesh->totpoly,
- nullptr,
- nullptr);
+ BKE_mesh_vertex_normals_ensure(mesh);
#ifdef DEBUG_TIME
TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
#endif
- mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
}
void BKE_mesh_calc_normals_looptri(MVert *mverts,
@@ -439,8 +506,6 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts,
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
normalize_v3_v3(no, mv->co);
}
-
- normal_float_to_short_v3(mv->no, no);
}
cleanup:
@@ -753,6 +818,7 @@ struct LoopSplitTaskDataCommon {
int (*edge_to_loops)[2];
int *loop_to_poly;
const float (*polynors)[3];
+ const float (*vert_normals)[3];
int numEdges;
int numLoops;
@@ -769,7 +835,6 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
const float split_angle,
const bool do_sharp_edges_tag)
{
- const MVert *mverts = data->mverts;
const MEdge *medges = data->medges;
const MLoop *mloops = data->mloops;
@@ -808,7 +873,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
* this way we don't have to compute those later!
*/
if (loopnors) {
- normal_short_to_float_v3(loopnors[ml_curr_index], mverts[ml_curr->v].no);
+ copy_v3_v3(loopnors[ml_curr_index], data->vert_normals[ml_curr->v]);
}
/* Check whether current edge might be smooth or sharp */
@@ -1533,6 +1598,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
}
void BKE_mesh_normals_loop_split(const MVert *mverts,
+ const float (*vert_normals)[3],
const int UNUSED(numVerts),
MEdge *medges,
const int numEdges,
@@ -1575,7 +1641,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]);
}
else {
- normal_short_to_float_v3(r_loopnors[ml_index], mverts[mloops[ml_index].v].no);
+ copy_v3_v3(r_loopnors[ml_index], vert_normals[mloops[ml_index].v]);
}
}
}
@@ -1633,6 +1699,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
common_data.edge_to_loops = edge_to_loops;
common_data.loop_to_poly = loop_to_poly;
common_data.polynors = polynors;
+ common_data.vert_normals = vert_normals;
common_data.numEdges = numEdges;
common_data.numLoops = numLoops;
common_data.numPolys = numPolys;
@@ -1684,6 +1751,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
* in which case they will be replaced by default loop/vertex normal.
*/
static void mesh_normals_loop_custom_set(const MVert *mverts,
+ const float (*vert_normals)[3],
const int numVerts,
MEdge *medges,
const int numEdges,
@@ -1715,6 +1783,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
/* Compute current lnor spacearr. */
BKE_mesh_normals_loop_split(mverts,
+ vert_normals,
numVerts,
medges,
numEdges,
@@ -1734,7 +1803,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
if (use_vertices) {
for (int i = 0; i < numVerts; i++) {
if (is_zero_v3(r_custom_loopnors[i])) {
- normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no);
+ copy_v3_v3(r_custom_loopnors[i], vert_normals[i]);
}
}
}
@@ -1837,6 +1906,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
/* And now, recompute our new auto lnors and lnor spacearr! */
BKE_lnor_spacearr_clear(&lnors_spacearr);
BKE_mesh_normals_loop_split(mverts,
+ vert_normals,
numVerts,
medges,
numEdges,
@@ -1918,6 +1988,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
}
void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
+ const float (*vert_normals)[3],
const int numVerts,
MEdge *medges,
const int numEdges,
@@ -1930,6 +2001,7 @@ void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
short (*r_clnors_data)[2])
{
mesh_normals_loop_custom_set(mverts,
+ vert_normals,
numVerts,
medges,
numEdges,
@@ -1944,6 +2016,7 @@ void BKE_mesh_normals_loop_custom_set(const MVert *mverts,
}
void BKE_mesh_normals_loop_custom_from_vertices_set(const MVert *mverts,
+ const float (*vert_normals)[3],
float (*r_custom_vertnors)[3],
const int numVerts,
MEdge *medges,
@@ -1956,6 +2029,7 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(const MVert *mverts,
short (*r_clnors_data)[2])
{
mesh_normals_loop_custom_set(mverts,
+ vert_normals,
numVerts,
medges,
numEdges,
@@ -1983,22 +2057,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, nullptr, numloops);
}
- float(*polynors)[3] = (float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
- bool free_polynors = false;
- if (polynors == nullptr) {
- polynors = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__);
- BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
- mesh->totvert,
- mesh->mloop,
- mesh->totloop,
- mesh->mpoly,
- mesh->totpoly,
- polynors,
- nullptr);
- free_polynors = true;
- }
-
mesh_normals_loop_custom_set(mesh->mvert,
+ BKE_mesh_vertex_normals_ensure(mesh),
mesh->totvert,
mesh->medge,
mesh->totedge,
@@ -2006,14 +2066,10 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
r_custom_nors,
mesh->totloop,
mesh->mpoly,
- polynors,
+ BKE_mesh_poly_normals_ensure(mesh),
mesh->totpoly,
clnors,
use_vertices);
-
- if (free_polynors) {
- MEM_freeN(polynors);
- }
}
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3])