[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