[Bf-blender-cvs] [a63a26a] temp_custom_loop_normals: Rework a bit `BKE_mesh_normals_loop_custom_set()`, should be more robust now.

Bastien Montagne noreply at git.blender.org
Wed Aug 6 21:36:44 CEST 2014


Commit: a63a26a5fcd0d958b5f8bc072232913d41bdd3c0
Author: Bastien Montagne
Date:   Sun Jul 27 23:04:46 2014 +0200
Branches: temp_custom_loop_normals
https://developer.blender.org/rBa63a26a5fcd0d958b5f8bc072232913d41bdd3c0

Rework a bit `BKE_mesh_normals_loop_custom_set()`, should be more robust now.

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

M	source/blender/blenkernel/intern/mesh_evaluate.c

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

diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 39d7f5f..2897fc8 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -599,7 +599,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int numVerts, MEdge *medge
 
 	if (r_lnors_spaces) {
 		/* Tag vertices that have at least one sharp edge as 'sharp' (used for the lnor spaces computation).
-		/* XXX This third loop over edges is a bit disappointing, could not find any other way yet.
+		 * XXX This third loop over edges is a bit disappointing, could not find any other way yet.
 		 *     Not really performance-critical anyway.
 		 */
 		for (me_index = 0; me_index < numEdges; me_index++) {
@@ -902,11 +902,13 @@ void BKE_mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdge *
 	 * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice!
 	 */
 	MLoopsNorSpaces lnors_spaces = {NULL};
+	BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
 	float (*lnors)[3] = MEM_callocN(sizeof(*lnors) * (size_t)numLoops, __func__);
 	int *loop_to_poly = MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
-	BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
-	int i;
 	const float split_angle = (float)M_PI;  /* In this case we do not want to use angle to define smooth fans! */
+	int i;
+
+	BLI_SMALLSTACK_DECLARE(clnors_data, float *);
 
 	printf("%s\n", __func__);
 
@@ -921,7 +923,17 @@ void BKE_mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdge *
 	 * Note this code *will never* unsharp edges!
 	 */
 	for (i = 0; i < numLoops; i++) {
-		if (!BLI_BITMAP_TEST_BOOL(done_loops, i) && lnors_spaces.lspaces[i]) {
+		if (!lnors_spaces.lspaces[i]) {
+			/* This should not happen in theory, but in some rare case (probably ugly geometry)
+			 * we can get some NULL loopspaces at this point. :/
+			 * Maybe we should set those loops' edges as sharp?
+			 */
+			BLI_BITMAP_ENABLE(done_loops, i);
+			printf("WARNING! Getting invalid NULL loop spaces for loop %d!\n", i);
+			continue;
+		}
+
+		if (!BLI_BITMAP_TEST_BOOL(done_loops, i)) {
 			/* Notes:
 			 *     * In case of mono-loop smooth fan, loops is NULL, so everything is fine (we have nothing to do).
 			 *     * Loops in this linklist are ordered (in reversed order compared to how they were discovered by
@@ -929,40 +941,86 @@ void BKE_mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdge *
 			 *       current value to the previous one!
 			 */
 			LinkNode *loops = lnors_spaces.lspaces[i]->loops;
-			const float *prev_nor = NULL;
 			MLoop *prev_ml = NULL;
+			const float *org_nor = NULL;
 			while (loops) {
 				const int lidx = GET_INT_FROM_POINTER(loops->link);
 				const float *nor = custom_loopnors[lidx];
 				MLoop *ml = &mloops[lidx];
 
-				if (prev_ml) print_v3("prev_nor", prev_nor), print_v3("nor", nor);
-
-				if (prev_ml && dot_v3v3(prev_nor, nor) < 1.0f - 1e-6f) {
-					/* Not equal enough normals, we have to tag the edge between those two loops' faces as sharp.
+				if (!org_nor) {
+					org_nor = nor;
+				}
+				else if (dot_v3v3(org_nor, nor) < 1.0f - 1e-6f) {
+					/* Current normal differs too much from org one, we have to tag the edge between
+					 * previous loop's face and current's one as sharp.
 					 * We know those two loops do not point to the same edge, since we do not allow reversed winding
 					 * in a same smooth fan.
 					 */
 					const MPoly *mp = &mpolys[loop_to_poly[lidx]];
 					const MLoop *mlp = &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
 					medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
+
+					org_nor = nor;
 				}
 
-				prev_nor = nor;
 				prev_ml = ml;
 				loops = loops->next;
 				BLI_BITMAP_ENABLE(done_loops, lidx);
 			}
+			BLI_BITMAP_ENABLE(done_loops, i);  /* in case it's a single-loop case... */
 		}
 	}
 
 	/* And now, recompute our new auto lnors and lnor spaces! */
+	BKE_free_loops_normal_spaces(&lnors_spaces);
 	BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
 	                            mpolys, polynors, numPolys, split_angle, &lnors_spaces, NULL, loop_to_poly);
 
 	/* And we just have to convert plain object-space custom normals to our lnor space-encoded ones. */
 	for (i = 0; i < numLoops; i++) {
-		BKE_lnor_space_custom_normal_to_data(lnors_spaces.lspaces[i], custom_loopnors[i], r_clnors_data[i]);
+		if (!lnors_spaces.lspaces[i]) {
+			BLI_BITMAP_DISABLE(done_loops, i);
+			printf("WARNING! Still getting invalid NULL loop spaces in second loop for loop %d!\n", i);
+			continue;
+		}
+
+		if (BLI_BITMAP_TEST_BOOL(done_loops, i)) {
+			/* Note we accumulate and average all custom normals in current smooth fan, to avoid getting different
+			 * clnors data (tiny differences in plain custom normals can give rather huge differences in
+			 * computed 2D factors).
+			 */
+			LinkNode *loops = lnors_spaces.lspaces[i]->loops;
+			if (loops) {
+				int nbr_nors = 0;
+				float avg_nor[3];
+				float clnor_data_tmp[2], *clnor_data;
+
+				zero_v3(avg_nor);
+				while (loops) {
+					const int lidx = GET_INT_FROM_POINTER(loops->link);
+					const float *nor = custom_loopnors[lidx];
+
+					nbr_nors++;
+					add_v3_v3(avg_nor, nor);
+					BLI_SMALLSTACK_PUSH(clnors_data, (float *)r_clnors_data[lidx]);
+
+					loops = loops->next;
+					BLI_BITMAP_DISABLE(done_loops, lidx);
+				}
+
+				mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors);
+				BKE_lnor_space_custom_normal_to_data(lnors_spaces.lspaces[i], avg_nor, clnor_data_tmp);
+
+				while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) {
+					copy_v2_v2(clnor_data, clnor_data_tmp);
+				}
+			}
+			else {
+				BKE_lnor_space_custom_normal_to_data(lnors_spaces.lspaces[i], custom_loopnors[i], r_clnors_data[i]);
+				BLI_BITMAP_DISABLE(done_loops, i);
+			}
+		}
 	}
 
 	MEM_freeN(lnors);




More information about the Bf-blender-cvs mailing list