[Bf-blender-cvs] [ec82e6ffcdc] soc-2017-normal-tools: Serious refactor, adding common data struct, some factorizing...
Bastien Montagne
noreply at git.blender.org
Fri Mar 9 18:50:45 CET 2018
Commit: ec82e6ffcdc2e57afaa681f21db1803f5eab0890
Author: Bastien Montagne
Date: Fri Mar 9 18:21:23 2018 +0100
Branches: soc-2017-normal-tools
https://developer.blender.org/rBec82e6ffcdc2e57afaa681f21db1803f5eab0890
Serious refactor, adding common data struct, some factorizing...
We now pass most common parameters to processing functions using a
single struct, this is much cleaner.
Also, factorized code aggregating poly nors into vertex nors in new
aggregate_vertex_normal function, and optimized expensive powf calls
(exponential inverse weight...) by computing once and caching most
common values (since weight is static all-over processing, and nearly
all vertices will only have a few faces or loops using them...).
Note that am still very unhapy with 'keep sharp edges' case, that one
seems to copy a lot of code we already have in BKE_mesh_evaluate, and
(if I followed code correctly) recompute everything, essentially
ditching the whole first computations of weighted normals!
===================================================================
M source/blender/modifiers/intern/MOD_weighted_normal.c
===================================================================
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 847d42ba2bc..d1dd1d78237 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -82,30 +82,85 @@ static int modepair_cmp_by_index(const void *p1, const void *p2)
return 0;
}
-static bool check_strength(int strength, int *cur_strength, float *cur_val, int *vertcount, float (*custom_normal)[3])
+#define NUM_CACHED_INVERSE_POWERS_OF_WEIGHT 128
+
+typedef struct WeightedNormalData {
+ const int numVerts;
+ const int numEdges;
+ const int numLoops;
+ const int numPolys;
+
+ MVert *mvert;
+ MEdge *medge;
+
+ MLoop *mloop;
+ short (*clnors)[2];
+
+ MPoly *mpoly;
+ float (*polynors)[3];
+ int *poly_strength;
+
+ MDeformVert *dvert;
+ const int defgrp_index;
+ const bool use_invert_vgroup;
+
+ const float weight;
+ short mode;
+
+ /* Lower-level, internal processing data. */
+ float cached_inverse_powers_of_weight[NUM_CACHED_INVERSE_POWERS_OF_WEIGHT];
+
+ ModePair *mode_pair;
+
+ int *loop_to_poly;
+
+ float (*vert_normals)[3];
+
+ int *vert_loops_count; /* Count number of loops using this vertex so far. */
+ float *curr_vert_val; /* Current max val for this vertex. */
+ int *curr_vert_strength; /* Current max strength encountered for this vertex. */
+} WeightedNormalData;
+
+
+static bool check_strength(WeightedNormalData *wn_data, const int mv_index, const int mp_index)
{
- if ((strength == FACE_STRENGTH_STRONG && *cur_strength != FACE_STRENGTH_STRONG) ||
- (strength == FACE_STRENGTH_MEDIUM && *cur_strength == FACE_STRENGTH_WEAK))
+ BLI_assert (wn_data->poly_strength != NULL);
+ BLI_assert (wn_data->curr_vert_strength != NULL);
+
+ const int mp_strength = wn_data->poly_strength[mp_index];
+
+ int *curr_vert_strength = wn_data->curr_vert_strength;
+ float *curr_vert_val = wn_data->curr_vert_val;
+ int *vert_loops_count = wn_data->vert_loops_count;
+ float (*vert_normals)[3] = wn_data->vert_normals;
+
+ if ((mp_strength == FACE_STRENGTH_STRONG && curr_vert_strength[mv_index] != FACE_STRENGTH_STRONG) ||
+ (mp_strength == FACE_STRENGTH_MEDIUM && curr_vert_strength[mv_index] == FACE_STRENGTH_WEAK))
{
- *cur_strength = strength;
- *cur_val = 0.0f;
- *vertcount = 0;
- zero_v3(*custom_normal);
- }
- else if (strength != *cur_strength) {
- return false;
+ curr_vert_strength[mv_index] = mp_strength;
+ curr_vert_val[mv_index] = 0.0f;
+ vert_loops_count[mv_index] = 0;
+ zero_v3(vert_normals[mv_index]);
}
- return true;
+
+ return mp_strength == curr_vert_strength[mv_index];
}
static void apply_weights_sharp_loops(
- WeightedNormalModifierData *wnmd, int *loop_index, int size, ModePair *mode_pair,
- float(*loop_normal)[3], int *loops_to_poly, float(*polynors)[3], int weight, int *strength)
+ WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data,
+ int *loop_index, int size, float(*loop_normal)[3])
{
+ ModePair *mode_pair = wn_data->mode_pair;
+
+ int *loop_to_poly = wn_data->loop_to_poly;
+ float(*polynors)[3] = wn_data->polynors;
+ int *poly_strength = wn_data->poly_strength;
+ const int weight = wn_data->weight;
+
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (wnmd->mode == MOD_WEIGHTEDNORMAL_MODE_FACE
- && mode_pair[loops_to_poly[loop_index[j]]].val < mode_pair[loops_to_poly[loop_index[j + 1]]].val) {
+ && mode_pair[loop_to_poly[loop_index[j]]].val < mode_pair[loop_to_poly[loop_index[j + 1]]].val) {
int temp = loop_index[j];
loop_index[j] = loop_index[j + 1];
loop_index[j + 1] = temp;
@@ -118,45 +173,63 @@ static void apply_weights_sharp_loops(
}
}
}
- float cur_val = 0, custom_normal[3] = { 0.0f };
- int vertcount = 0, cur_strength = FACE_STRENGTH_WEAK;
- const bool face_influence = (wnmd->flag & MOD_WEIGHTEDNORMAL_FACE_INFLUENCE) != 0;
+
+ zero_v3(wn_data->vert_normals[0]);
+ wn_data->vert_loops_count[0] = 0;
+ wn_data->curr_vert_val[0] = 0.0f;
+ wn_data->curr_vert_strength[0] = FACE_STRENGTH_WEAK;
+ const bool has_face_influence = (wnmd->flag & MOD_WEIGHTEDNORMAL_FACE_INFLUENCE) != 0 && poly_strength != NULL;
+
+ float *vert_normals = wn_data->vert_normals[0];
+ int *vert_loops_count = &wn_data->vert_loops_count[0];
+ float *curr_vert_val = &wn_data->curr_vert_val[0];
for (int i = 0; i < size; i++) {
- float wnor[3];
int j, mp_index;
bool do_loop = true;
if (wnmd->mode == MOD_WEIGHTEDNORMAL_MODE_FACE) {
- j = loops_to_poly[loop_index[i]];
+ j = loop_to_poly[loop_index[i]];
mp_index = mode_pair[j].index;
}
else {
j = loop_index[i];
- mp_index = loops_to_poly[j];
- }
- if (face_influence && strength) {
- do_loop = check_strength(strength[mp_index], &cur_strength, &cur_val, &vertcount, &custom_normal);
+ mp_index = loop_to_poly[j];
+ }
+
+ if (has_face_influence && poly_strength) {
+ do_loop = check_strength(wn_data, 0, mp_index);
}
if (do_loop) {
- if (!cur_val) {
- cur_val = mode_pair[j].val;
+ const float curr_val = mode_pair[j].val;
+
+ float *cached_inverse_powers_of_weight = wn_data->cached_inverse_powers_of_weight;
+
+ if (*curr_vert_val == 0.0f) {
+ *curr_vert_val = curr_val;
}
- if (!compare_ff(cur_val, mode_pair[j].val, wnmd->thresh)) {
- vertcount++;
- cur_val = mode_pair[j].val;
+ if (!compare_ff(*curr_vert_val, mode_pair[j].val, wnmd->thresh)) {
+ (*vert_loops_count)++;
+ *curr_vert_val = curr_val;
}
- float n_weight = pow(weight, vertcount);
- copy_v3_v3(wnor, polynors[mp_index]);
- mul_v3_fl(wnor, mode_pair[j].val * (1.0f / n_weight));
- add_v3_v3(custom_normal, wnor);
+ /* Exponentially divided weight for each normal (since a few values will be used by most vertices, we cache those). */
+ const int vl_count = *vert_loops_count;
+ if (vl_count < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT && cached_inverse_powers_of_weight[vl_count] == 0.0f) {
+ cached_inverse_powers_of_weight[vl_count] = 1.0f / powf(weight, vl_count);
+ }
+ const float inverted_n_weight = vl_count < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT ?
+ cached_inverse_powers_of_weight[vl_count] : 1.0f / powf(weight, vl_count);
+
+ madd_v3_v3fl(vert_normals, polynors[mp_index], curr_val * inverted_n_weight);
}
}
- normalize_v3(custom_normal);
+ if (normalize_v3(vert_normals) < CLNORS_VALID_VEC_LEN) {
+ zero_v3(vert_normals);
+ }
for (int i = 0; i < size; i++) {
- copy_v3_v3(loop_normal[loop_index[i]], custom_normal);
+ copy_v3_v3(loop_normal[loop_index[i]], vert_normals);
}
}
@@ -164,11 +237,18 @@ static void apply_weights_sharp_loops(
* loop normal space array.
* Used only to work on sharp edges. */
static void loop_split_worker(
- WeightedNormalModifierData *wnmd, ModePair *mode_pair, MLoop *ml_curr, MLoop *ml_prev,
+ WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data,
+ MLoop *ml_curr, MLoop *ml_prev,
int ml_curr_index, int ml_prev_index, int *e2l_prev, int mp_index,
- float (*loop_normal)[3], int *loops_to_poly, float (*polynors)[3],
- MEdge *medge, MLoop *mloop, MPoly *mpoly, int (*edge_to_loops)[2], int weight, int *strength)
+ float (*loop_normals)[3], int (*edge_to_loops)[2])
{
+ MEdge *medge = wn_data->medge;
+ MLoop *mloop = wn_data->mloop;
+ MPoly *mpoly = wn_data->mpoly;
+
+ int *loop_to_poly = wn_data->loop_to_poly;
+ float (*polynors)[3] = wn_data->polynors;
+
if (e2l_prev) {
int *e2lfan_curr = e2l_prev;
const MLoop *mlfan_curr = ml_prev;
@@ -190,7 +270,7 @@ static void loop_split_worker(
}
BKE_mesh_loop_manifold_fan_around_vert_next(
- mloop, mpoly, loops_to_poly, e2lfan_curr, mv_pivot_index,
+ mloop, mpoly, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
e2lfan_curr = edge_to_loops[mlfan_curr->e];
@@ -202,28 +282,94 @@ static void loop_split_worker(
BLI_stack_pop(loop_index, &index[cur]);
cur++;
}
- apply_weights_sharp_loops(wnmd, index, cur, mode_pair, loop_normal, loops_to_poly, polynors, weight, strength);
+ apply_weights_sharp_loops(wnmd, wn_data, index, cur, loop_normals);
MEM_freeN(index);
BLI_stack_free(loop_index);
}
else {
- copy_v3_v3(loop_normal[ml_curr_index], polynors[loops_to_poly[ml_curr_index]]);
+ copy_v3_v3(loop_normals[ml_curr_index], polynors[loop_to_poly[ml_curr_index]]);
}
}
-static void apply_weights_vertex_normal(
- WeightedNormalModifierData *wnmd,
- MVert *mvert, const int numVerts,
- MEdge *medge, const int numEdges,
- MLoop *mloop, const int numLoops, short (*clnors)[2], int *loop_to_poly,
- MPoly *mpoly, const int numPoly, float (*polynors)[3], int *poly_strength,
- MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
- const float weight, short mode, ModePair *mode_pair)
+static void aggregate_vertex_normal(
+ WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data,
+ const int mv_index, const int mp_index,
+ const float curr_val,
+ const bool use_face_influence)
{
+ float (*polynors)[3] = wn_data->polynors;
+
+ MDeformVert *dvert = wn_data->dvert;
+ const int defgrp_index = wn_data->defgrp_index;
+ const bool use_invert_vgroup = wn_data->use_invert_vgroup;
+
+ const float weight = wn_data->weight;
+
+ float (*vert_normals)[3] = wn_data->vert_normals;
+ int *vert_loops_count = wn_data->vert_loops_count;
+ float *curr_vert_val = wn_data->curr_vert_val;
+
+ float *cached_inverse_powers_of_weight = wn_data->cached_inverse_powers_of_weight;
+
+ const bool has_vgroup = dvert != NULL;
+ const bool vert_of_group = has_vgroup && defvert_find_index(&dvert[mv_index], defgrp_index) != NULL;
+
+ if (has_vgroup && ((vert_of_group && use_invert_vgroup) || (!vert_of_group && !use_invert_vgroup))) {
+ return;
+ }
+
+ if (use_face_influence && !check_strength(wn_data, mv_index, mp_index)) {
+ return;
+ }
+
+ /* If cur_val is 0 init it to present value. */
+ if (curr_vert_val[mv_index] == 0.0f) {
+ curr_vert_val[mv_index] = curr_v
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list