[Bf-blender-cvs] [d6940e4e896] soc-2017-normal-tools: Heavy refactor of weighted normals code, especially 'keep sharp' part.

Bastien Montagne noreply at git.blender.org
Mon Mar 12 17:37:36 CET 2018


Commit: d6940e4e896457bab83aceb7588342054ad0892b
Author: Bastien Montagne
Date:   Mon Mar 12 17:22:21 2018 +0100
Branches: soc-2017-normal-tools
https://developer.blender.org/rBd6940e4e896457bab83aceb7588342054ad0892b

Heavy refactor of weighted normals code, especially 'keep sharp' part.

Before, 'keep sharp' was bsically:
* Overwriting everything just computed by 'single nor per vertex' code,
leading to a nice share of computations being tossed to nowhere.
* Re-implementing most of core clnor computaion code, only skipping all
'sharp edge' cases but the one defined by shapr edge tags. This was not
only bad for code maintenance and (reasonable) simplicity, it was also
introducing inconsistencies in how we define sharp edges, since
everwhere else in code we take into account sharp edge tag, flat face
tag, and 'smooth threshold' value (aka split angle) of mesh.

At first I though 'keep sharp' would need its own totally separated code
path, but thanks to some data structure tricks, it was possible to merge
most of both cases into single code. So this commit:
* Heavily factorizes and simplifies code, especially the 'keep sharp' case.
* Makes use of clnor spaces as generated by core BKE code to define
'smooth fans' that should have the same weighted normals, just like
anywhere else in Blender.

Note that since code is now using same functions in all cases, it also
naturally brings back vgroup support in keep_sharp case.

Also, this has been a fairly involved change, basic testing seems to be
OK, but more would be welcomed here. :)

===================================================================

M	source/blender/makesrna/intern/rna_modifier.c
M	source/blender/modifiers/intern/MOD_weighted_normal.c

===================================================================

diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 0cc5a33f0ca..35d44a97566 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -4821,8 +4821,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
 	static EnumPropertyItem prop_weighting_mode_items[] = {
 		{MOD_WEIGHTEDNORMAL_MODE_FACE, "FACE_AREA", 0, "Face Area", "Generate face area weighted normals"},
 		{MOD_WEIGHTEDNORMAL_MODE_ANGLE, "CORNER_ANGLE", 0, "Corner Angle", "Generate corner angle weighted normals"},
-		{MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE, "FACE_AREA_WITH_ANGLE", 0, "Face Area with Angle",
-		                                     "Generated normals weighted by both Face Area and Angle"},
+		{MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE, "FACE_AREA_WITH_ANGLE", 0, "Face Area And Angle",
+		                                     "Generated normals weighted by both face area and angle"},
 		{0, NULL, 0, NULL, NULL}
 	};
 
@@ -4834,7 +4834,10 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
 	prop = RNA_def_property(srna, "weight", PROP_INT, PROP_NONE);
 	RNA_def_property_range(prop, 1, 100);
 	RNA_def_property_ui_range(prop, 1, 100, 1, -1);
-	RNA_def_property_ui_text(prop, "Weight", "Weights given to Face Normal for each mode");
+	RNA_def_property_ui_text(prop, "Weight",
+	                         "Corrective factor applied to faces' weights, 50 is neutral, "
+	                         "lower values increase weight of weak faces, "
+	                         "higher values increase weight of strong faces");
 	RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
 	prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
@@ -4850,7 +4853,9 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
 
 	prop = RNA_def_property(srna, "keep_sharp", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_KEEP_SHARP);
-	RNA_def_property_ui_text(prop, "Keep Sharp Edges", "Do not edit normals of sharp edges");
+	RNA_def_property_ui_text(prop, "Keep Sharp",
+	                         "Keep sharp edges as computed for default split normals, "
+	                         "instead of setting a single weighted normal for each vertex.");
 	RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
 	prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index ffd16397c59..1559007d8a7 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -36,7 +36,7 @@
 #include "BKE_mesh.h"
 
 #include "BLI_math.h"
-#include "BLI_stack.h"
+#include "BLI_linklist.h"
 
 #include "bmesh_class.h"
 
@@ -60,27 +60,17 @@ static int modepair_cmp_by_val_inverse(const void *p1, const void *p2)
 	ModePair *r1 = (ModePair *)p1;
 	ModePair *r2 = (ModePair *)p2;
 
-	if (r1->val < r2->val)
-		return 1;
-	else if (r1->val > r2->val)
-		return -1;
-
-	return 0;
+	return (r1->val < r2->val) ? 1 : ((r1->val > r2->val) ? -1 : 0);
 }
 
-/* Sorts by index in increasing order. */
-static int modepair_cmp_by_index(const void *p1, const void *p2)
-{
-	ModePair *r1 = (ModePair *)p1;
-	ModePair *r2 = (ModePair *)p2;
+/* There will be one of those per vertex (simple case, computing one normal per vertex), or per smooth fan. */
+typedef struct WeightedNormalDataAggregateItem {
+	float normal[3];
 
-	if (r1->index > r2->index)
-		return 1;
-	else if (r1->index < r2->index)
-		return -1;
-
-	return 0;
-}
+	int num_loops;  /* Count number of loops using this item so far. */
+	float curr_val;  /* Current max val for this item. */
+	int curr_strength;  /* Current max strength encountered for this item. */
+} WeightedNormalDataAggregateItem;
 
 #define NUM_CACHED_INVERSE_POWERS_OF_WEIGHT 128
 
@@ -95,6 +85,8 @@ typedef struct WeightedNormalData {
 
 	MLoop *mloop;
 	short (*clnors)[2];
+	const bool has_clnors;  /* True if clnors already existed, false if we had to create them. */
+	const float split_angle;
 
 	MPoly *mpoly;
 	float (*polynors)[3];
@@ -105,198 +97,42 @@ typedef struct WeightedNormalData {
 	const bool use_invert_vgroup;
 
 	const float weight;
-	short mode;
+	const short mode;
 
 	/* Lower-level, internal processing data. */
 	float cached_inverse_powers_of_weight[NUM_CACHED_INVERSE_POWERS_OF_WEIGHT];
 
+	WeightedNormalDataAggregateItem *items_data;
+
 	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)
+/* Check strength of given poly compared to those found so far for that given item (vertex or smooth fan),
+ * and reset matching item_data in case we get a stronger new strength. */
+static bool check_item_poly_strength(
+        WeightedNormalData *wn_data, WeightedNormalDataAggregateItem *item_data, const int mp_index)
 {
 	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 > curr_vert_strength[mv_index]) {
-		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 mp_strength == curr_vert_strength[mv_index];
-}
-
-static void apply_weights_sharp_loops(
-        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[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;
-			}
-			else if ((wnmd->mode == MOD_WEIGHTEDNORMAL_MODE_ANGLE || wnmd->mode == MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE)
-				&& mode_pair[loop_index[j]].val < mode_pair[loop_index[j + 1]].val) {
-				int temp = loop_index[j];
-				loop_index[j] = loop_index[j + 1];
-				loop_index[j + 1] = temp;
-			}
-		}
-	}
-
-	const bool has_face_influence = (wnmd->flag & MOD_WEIGHTEDNORMAL_FACE_INFLUENCE) != 0 && poly_strength != NULL;
-
-	zero_v3(wn_data->vert_normals[0]);
-	wn_data->vert_loops_count[0] = 0;
-	wn_data->curr_vert_val[0] = 0.0f;
-	if (has_face_influence) {
-		wn_data->curr_vert_strength[0] = FACE_STRENGTH_WEAK;
+	if (mp_strength > item_data->curr_strength) {
+		item_data->curr_strength = mp_strength;
+		item_data->curr_val = 0.0f;
+		item_data->num_loops = 0;
+		zero_v3(item_data->normal);
 	}
 
-	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++) {
-		int j, mp_index;
-		bool do_loop = true;
-
-		if (wnmd->mode == MOD_WEIGHTEDNORMAL_MODE_FACE) {
-			j = loop_to_poly[loop_index[i]];
-			mp_index = mode_pair[j].index;
-		}
-		else {
-			j = loop_index[i];
-			mp_index = loop_to_poly[j];
-		}
-
-		if (has_face_influence) {
-			do_loop = check_strength(wn_data, 0, mp_index);
-		}
-		if (do_loop) {
-			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(*curr_vert_val, mode_pair[j].val, wnmd->thresh)) {
-				(*vert_loops_count)++;
-				*curr_vert_val = curr_val;
-			}
-
-			/* 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);
-		}
-	}
-	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]], vert_normals);
-	}
-}
-
-/* Modified version of loop_split_worker_do which sets custom_normals without considering smoothness of faces or
- * loop normal space array.
- * Used only to work on sharp edges. */
-static void loop_split_worker(
-        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_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;
-		int mlfan_curr_index = ml_prev_index;
-		int mlfan_vert_index = ml_curr_index;
-		int mpfan_curr_index = mp_index;
-
-		BLI_Stack *loop_index = BLI_stack_new(sizeof(int), __func__);
-
-		while (true) {
-			const unsigned int mv_pivot_index = ml_cu

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list