Page MenuHome
Paste P2287

D11993 alternative (loop-weight as float & cache edge-vectors), 501bca9f5b1265e6f336bc7c1878b9b50a70356a
ActivePublic

Authored by Campbell Barton (campbellbarton) on Jul 26 2021, 10:10 AM.
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e3be9cd8ef8..34d4405ef5f 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -307,6 +307,8 @@ void BKE_mesh_calc_normals_mapping_ex(struct MVert *mverts,
void BKE_mesh_calc_normals_poly(struct MVert *mverts,
float (*r_vertnors)[3],
int numVerts,
+ const struct MEdge *medges,
+ int numEdges,
const struct MLoop *mloop,
const struct MPoly *mpolys,
int numLoops,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index ba8cf8debe9..346519818fb 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -819,6 +819,8 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
BKE_mesh_calc_normals_poly(mesh_final->mvert,
nullptr,
mesh_final->totvert,
+ mesh_final->medge,
+ mesh_final->totedge,
mesh_final->mloop,
mesh_final->mpoly,
mesh_final->totloop,
@@ -1539,6 +1541,8 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
BKE_mesh_calc_normals_poly(mesh_final->mvert,
nullptr,
mesh_final->totvert,
+ mesh_final->medge,
+ mesh_final->totedge,
mesh_final->mloop,
mesh_final->mpoly,
mesh_final->totloop,
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 605061570b8..3a57bd5ab4c 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -303,6 +303,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
BKE_mesh_calc_normals_poly(verts_dst,
NULL,
num_verts_dst,
+ NULL, /* FIXME: `medge`. */
+ 0, /* FIXME: `totedege`. */
loops_dst,
polys_dst,
num_loops_dst,
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 0f8c9bad798..1c6a6f99062 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -2284,6 +2284,8 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
BKE_mesh_calc_normals_poly(me.mvert,
r_vertnors,
me.totvert,
+ me.medge,
+ me.totedge,
me.mloop,
me.mpoly,
me.totloop,
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 8d74002ad79..799c3d903db 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1844,6 +1844,8 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
BKE_mesh_calc_normals_poly(mesh->mvert,
NULL,
mesh->totvert,
+ mesh->medge,
+ mesh->totedge,
mesh->mloop,
mesh->mpoly,
mesh->totloop,
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index 9aeaa1ada52..99daaef4a56 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -396,6 +396,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
BKE_mesh_calc_normals_poly(result->mvert,
NULL,
result->totvert,
+ result->medge,
+ result->totedge,
result->mloop,
result->mpoly,
totloop,
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index f496d6eada1..476a440989f 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -52,10 +52,10 @@
// #define DEBUG_TIME
-#ifdef DEBUG_TIME
-# include "PIL_time.h"
-# include "PIL_time_utildefines.h"
-#endif
+// #ifdef DEBUG_TIME
+#include "PIL_time.h"
+#include "PIL_time_utildefines.h"
+// #endif
static CLG_LogRef LOG = {"bke.mesh_normals"};
@@ -164,8 +164,17 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
if (only_face_normals == false) {
/* vertex normals are optional, they require some extra calculations,
* so make them optional */
- BKE_mesh_calc_normals_poly(
- mverts, nullptr, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
+ BKE_mesh_calc_normals_poly(mverts,
+ nullptr,
+ numVerts,
+ NULL, /* FIXME: `medge`. */
+ 0, /* FIXME: `totedege`. */
+ mloop,
+ mpolys,
+ numLoops,
+ numPolys,
+ pnors,
+ false);
}
else {
/* only calc poly normals */
@@ -203,9 +212,17 @@ struct MeshCalcNormalsData {
const MPoly *mpolys;
const MLoop *mloop;
MVert *mverts;
+ const MEdge *medges;
float (*pnors)[3];
- float (*lnors_weighted)[3];
+ float *lnors_weights;
float (*vnors)[3];
+ const float (*edirs)[3];
+};
+
+struct MeshCalcNormalsData_EdgeDir {
+ const MVert *mverts;
+ const MEdge *medges;
+ float (*edirs)[3];
};
static void mesh_calc_normals_poly_cb(void *__restrict userdata,
@@ -218,6 +235,19 @@ static void mesh_calc_normals_poly_cb(void *__restrict userdata,
BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]);
}
+static void mesh_calc_normals_edge_dir_precalc_cb(void *__restrict userdata,
+ const int eidx,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ MeshCalcNormalsData_EdgeDir *data = (MeshCalcNormalsData_EdgeDir *)userdata;
+ const MVert *mverts = data->mverts;
+
+ const MEdge *edge = &data->medges[eidx];
+ float *edir = data->edirs[eidx];
+ sub_v3_v3v3(edir, mverts[edge->v2].co, mverts[edge->v1].co);
+ normalize_v3(edir);
+}
+
static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -226,19 +256,18 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
const MPoly *mp = &data->mpolys[pidx];
const MLoop *ml = &data->mloop[mp->loopstart];
const MVert *mverts = data->mverts;
+ const MEdge *medges = data->medges;
- float pnor_temp[3];
- float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp;
- float(*lnors_weighted)[3] = data->lnors_weighted;
+ const float(*edirs)[3] = data->edirs;
+ float *pnor = data->pnors[pidx];
+ float *lnors_weights = &data->lnors_weights[mp->loopstart];
const int nverts = mp->totloop;
- float(*edgevecbuf)[3] = (float(*)[3])BLI_array_alloca(edgevecbuf, (size_t)nverts);
/* Polygon Normal and edge-vector */
/* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
{
- int i_prev = nverts - 1;
- const float *v_prev = mverts[ml[i_prev].v].co;
+ const float *v_prev = mverts[ml[nverts - 1].v].co;
const float *v_curr;
zero_v3(pnor);
@@ -246,12 +275,6 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
for (int i = 0; i < nverts; i++) {
v_curr = mverts[ml[i].v].co;
add_newell_cross_v3_v3v3(pnor, v_prev, v_curr);
-
- /* Unrelated to normalize, calculate edge-vector */
- sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
- normalize_v3(edgevecbuf[i_prev]);
- i_prev = i;
-
v_prev = v_curr;
}
if (UNLIKELY(normalize_v3(pnor) == 0.0f)) {
@@ -263,20 +286,23 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
/* inline version of #accumulate_vertex_normals_poly_v3,
* split between this threaded callback and #mesh_calc_normals_poly_accum_cb. */
{
- const float *prev_edge = edgevecbuf[nverts - 1];
+ int i_prev = nverts - 1;
+ int eidx_prev = ml[i_prev].e;
- for (int i = 0; i < nverts; i++) {
- const int lidx = mp->loopstart + i;
- const float *cur_edge = edgevecbuf[i];
+ for (int i_curr = 0; i_curr < nverts; i_curr++) {
+ const int eidx_curr = ml[i_curr].e;
+ float dotprod = dot_v3v3(edirs[eidx_curr], edirs[eidx_prev]);
+
+ if ((medges[ml[i_prev].e].v1 == ml[i_prev].v) ^ (medges[ml[i_curr].e].v1 == ml[i_curr].v)) {
+ dotprod = -dotprod;
+ }
/* calculate angle between the two poly edges incident on
* this vertex */
- const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+ lnors_weights[i_curr] = saacos(dotprod);
- /* Store for later accumulation */
- mul_v3_v3fl(lnors_weighted[lidx], pnor, fac);
-
- prev_edge = cur_edge;
+ i_prev = i_curr;
+ eidx_prev = eidx_curr;
}
}
}
@@ -301,6 +327,8 @@ static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata,
void BKE_mesh_calc_normals_poly(MVert *mverts,
float (*r_vertnors)[3],
int numVerts,
+ const MEdge *medges,
+ int numEdges,
const MLoop *mloop,
const MPoly *mpolys,
int numLoops,
@@ -308,6 +336,8 @@ void BKE_mesh_calc_normals_poly(MVert *mverts,
float (*r_polynors)[3],
const bool only_face_normals)
{
+ BLI_assert(medges != nullptr);
+ TIMEIT_START(BKE_mesh_calc_normals_poly);
float(*pnors)[3] = r_polynors;
TaskParallelSettings settings;
@@ -328,10 +358,20 @@ void BKE_mesh_calc_normals_poly(MVert *mverts,
return;
}
+ float(*edirs)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numEdges, sizeof(*edirs), __func__);
+ {
+ MeshCalcNormalsData_EdgeDir data;
+ data.mverts = mverts;
+ data.medges = medges;
+ data.edirs = edirs;
+ BLI_task_parallel_range(0, numEdges, &data, mesh_calc_normals_edge_dir_precalc_cb, &settings);
+ }
+
float(*vnors)[3] = r_vertnors;
- float(*lnors_weighted)[3] = (float(*)[3])MEM_malloc_arrayN(
- (size_t)numLoops, sizeof(*lnors_weighted), __func__);
+ float *lnors_weights = (float *)MEM_malloc_arrayN(
+ (size_t)numLoops, sizeof(*lnors_weights), __func__);
bool free_vnors = false;
+ bool free_pnors = false;
/* first go through and calculate normals for all the polys */
if (vnors == nullptr) {
@@ -342,13 +382,20 @@ void BKE_mesh_calc_normals_poly(MVert *mverts,
memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts);
}
+ if (pnors == nullptr) {
+ pnors = (float(*)[3])MEM_malloc_arrayN((size_t)numPolys, sizeof(*pnors), __func__);
+ free_pnors = true;
+ }
+
MeshCalcNormalsData data;
data.mpolys = mpolys;
data.mloop = mloop;
data.mverts = mverts;
+ data.medges = medges;
data.pnors = pnors;
- data.lnors_weighted = lnors_weighted;
+ data.lnors_weights = lnors_weights;
data.vnors = vnors;
+ data.edirs = edirs;
/* Compute poly normals, and prepare weighted loop normals. */
BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings);
@@ -357,8 +404,13 @@ void BKE_mesh_calc_normals_poly(MVert *mverts,
/* Unfortunately, not possible to thread that
* (not in a reasonable, totally lock- and barrier-free fashion),
* since several loops will point to the same vertex... */
- for (int lidx = 0; lidx < numLoops; lidx++) {
- add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]);
+ for (int pidx = 0; pidx < numPolys; pidx++) {
+ const float *no = pnors[pidx];
+ int lidx = mpolys[pidx].loopstart;
+ int loopterminate = lidx + mpolys[pidx].totloop;
+ for (; lidx < loopterminate; lidx++) {
+ madd_v3_v3fl(vnors[mloop[lidx].v], no, data.lnors_weights[lidx]);
+ }
}
/* Normalize and validate computed vertex normals. */
@@ -367,7 +419,13 @@ void BKE_mesh_calc_normals_poly(MVert *mverts,
if (free_vnors) {
MEM_freeN(vnors);
}
- MEM_freeN(lnors_weighted);
+ if (free_pnors) {
+ MEM_freeN(pnors);
+ }
+ MEM_freeN(lnors_weights);
+ MEM_freeN(edirs);
+
+ TIMEIT_END(BKE_mesh_calc_normals_poly);
}
void BKE_mesh_ensure_normals(Mesh *mesh)
@@ -414,6 +472,8 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
BKE_mesh_calc_normals_poly(mesh->mvert,
nullptr,
mesh->totvert,
+ mesh->medge,
+ mesh->totedge,
mesh->mloop,
mesh->mpoly,
mesh->totloop,
@@ -440,6 +500,8 @@ void BKE_mesh_calc_normals(Mesh *mesh)
BKE_mesh_calc_normals_poly(mesh->mvert,
nullptr,
mesh->totvert,
+ mesh->medge,
+ mesh->totedge,
mesh->mloop,
mesh->mpoly,
mesh->totloop,
@@ -2090,6 +2152,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
BKE_mesh_calc_normals_poly(mesh->mvert,
nullptr,
mesh->totvert,
+ mesh->medge,
+ mesh->totedge,
mesh->mloop,
mesh->mpoly,
mesh->totloop,
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index c5e8858ea12..d8fc6ee55bc 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1381,6 +1381,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
BKE_mesh_calc_normals_poly(verts_dst,
NULL,
numverts_dst,
+ edges_dst,
+ numedges_dst,
loops_dst,
polys_dst,
numloops_dst,
@@ -2233,6 +2235,8 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
BKE_mesh_calc_normals_poly(verts_dst,
NULL,
numverts_dst,
+ NULL, /* FIXME: `medge`. */
+ 0, /* FIXME: `totedege`. */
loops_dst,
polys_dst,
numloops_dst,
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index b2379610f65..4127b787892 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -1010,6 +1010,8 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
BKE_mesh_calc_normals_poly(me->mvert,
NULL,
me->totvert,
+ me->medge,
+ me->totedge,
me->mloop,
me->mpoly,
me->totloop,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index e7750f0a0d1..69dc674cc0a 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -559,6 +559,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
BKE_mesh_calc_normals_poly(mvert,
NULL,
num_verts,
+ NULL, /* FIXME: `medge`. */
+ 0, /* FIXME: `totedege`. */
mloop,
mpoly,
num_loops,
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c
index e97190b1878..07a94bac948 100644
--- a/source/blender/modifiers/intern/MOD_solidify_extrude.c
+++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c
@@ -261,6 +261,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
BKE_mesh_calc_normals_poly(orig_mvert,
NULL,
(int)numVerts,
+ orig_medge,
+ (int)numEdges,
orig_mloop,
orig_mpoly,
(int)numLoops,
diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
index b872f04b60f..c7e55cd1bbf 100644
--- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
+++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
@@ -205,6 +205,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
BKE_mesh_calc_normals_poly(orig_mvert,
NULL,
(int)numVerts,
+ orig_medge,
+ (int)numEdges,
orig_mloop,
orig_mpoly,
(int)numLoops,
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 3b147c69716..484c7672bef 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -615,8 +615,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
polynors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys);
CustomData_set_layer_flag(pdata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- BKE_mesh_calc_normals_poly(
- mvert, NULL, numVerts, mloop, mpoly, numLoops, numPolys, polynors, false);
+ BKE_mesh_calc_normals_poly(mvert,
+ NULL,
+ numVerts,
+ NULL, /* FIXME: `medge`. */
+ 0, /* FIXME: `totedege`. */
+ mloop,
+ mpoly,
+ numLoops,
+ numPolys,
+ polynors,
+ false);
const float split_angle = mesh->smoothresh;
short(*clnors)[2];