[Bf-blender-cvs] [d5f484e] temp_custom_loop_normals: Simplify/fix code to set custom split normals.

Bastien Montagne noreply at git.blender.org
Sun Aug 17 15:54:37 CEST 2014


Commit: d5f484e68fbdb8866dd9dd8f079c6021ce654f42
Author: Bastien Montagne
Date:   Sun Aug 17 15:03:02 2014 +0200
Branches: temp_custom_loop_normals
https://developer.blender.org/rBd5f484e68fbdb8866dd9dd8f079c6021ce654f42

Simplify/fix code to set custom split normals.

We might lose a (very tiny) bit of performances in some cases, but this is not
a critical area, more important to have a simple and working code. Also,
this func no longer modifies given array of custom normals! And hopefully
weights handling is now correct in all cases.

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

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 8f6a989..7a3654d 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1181,7 +1181,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int numVerts, MEdge *medge
 
 /**
  * Compute internal representation of given custom normals (as an array of float[2]).
- * It also make sure the mesh matches those custom normals, by setting sharp edges fag as needed to get a
+ * It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed to get a
  * same custom lnor for all loops sharing a same smooth fan.
  * If use_vertices if true, custom_loopnors and custom_loopnors_facs are assumed to be per-vertex, not per-loop
  * (this allows to set whole vert's normals at once, useful in some cases).
@@ -1200,8 +1200,6 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 	 */
 	MLoopsNorSpaces lnors_spaces = {NULL};
 	BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
-	/* To avoid interpolating custom vnors more than once in case their weight is not 1.0f!!! */
-	BLI_bitmap *done_verts = use_vertices ? BLI_BITMAP_NEW((size_t)numVerts, __func__) : NULL;
 	float (*lnors)[3] = MEM_callocN(sizeof(*lnors) * (size_t)numLoops, __func__);
 	int *loop_to_poly = MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
 	const float split_angle = (float)M_PI;  /* In this case we do not want to use angle to define smooth fans! */
@@ -1213,14 +1211,14 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 	BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
 	                            mpolys, polynors, numPolys, split_angle, &lnors_spaces, NULL, loop_to_poly);
 
+	/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
+	 * are not (enough) equal, add sharp edges as needed.
+	 * This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spaces/smooth fans matching
+	 * given custom lnors.
+	 * Note this code *will never* unsharp edges!
+	 * And quite obviously, when we set custom normals per vertices, running this is absolutely useless.
+	 */
 	if (!use_vertices) {
-		/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
-		 * are not (enough) equal, add sharp edges as needed.
-		 * This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spaces/smooth fans matching
-		 * given custom lnors.
-		 * Note this code *will never* unsharp edges!
-		 * And quite obviously, when we set custom normals per vertices, running this is absolutely useless!
-		 */
 		for (i = 0; i < numLoops; i++) {
 			if (!lnors_spaces.lspaces[i]) {
 				/* This should not happen in theory, but in some rare case (probably ugly geometry)
@@ -1236,47 +1234,31 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 				/* 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
-				 *       BKE_mesh_normals_loop_split(), but this is not a problem). Hence, we just have to compare
-				 *       current value to the previous one!
+				 *       BKE_mesh_normals_loop_split(), but this is not a problem). Which means if we find a
+				 *       mismatching clnor, we know all remaining loops will have to be in a new, different smooth fan/
+				 *       lnor space.
+				 *     * In smooth fan case, we compare each clnor against a ref one, to avoid small differences adding
+				 *       up into a real big one in the end!
 				 */
 				LinkNode *loops = lnors_spaces.lspaces[i]->loops;
 				MLoop *prev_ml = NULL;
 				const float *org_nor = NULL;
-				if (!loops) {
-					MLoop *ml = &mloops[i];
-					const int idx = use_vertices ? (int)ml->v : i;
-					float *nor = custom_loopnors[idx];
+				float org_fac = 0.0f;
 
-					if (custom_loopnors_facs) {
-						const float fac = custom_loopnors_facs[idx];
-
-						if (fac != 1.0f) {
-							/* Note: inplace modification to get final custom lnor! */
-							interp_v3_v3v3_slerp_safe(nor, lnors_spaces.lspaces[i]->vec_lnor, nor, fac);
-						}
-					}
-					BLI_BITMAP_ENABLE(done_loops, i);
-				}
-				/* Hidden else, avoids one indentation. ;) */
 				while (loops) {
 					const int lidx = GET_INT_FROM_POINTER(loops->link);
 					MLoop *ml = &mloops[lidx];
-					const int idx = use_vertices ? (int)ml->v : lidx;
-					float *nor = custom_loopnors[idx];
-
-					if (custom_loopnors_facs) {
-						const float fac = custom_loopnors_facs[idx];
-
-						if (fac != 1.0f) {
-							/* Note: inplace modification to get final custom lnor! */
-							interp_v3_v3v3_slerp_safe(nor, lnors_spaces.lspaces[i]->vec_lnor, nor, fac);
-						}
-					}
+					const int nidx = use_vertices ? (int)ml->v : lidx;
+					float *nor = custom_loopnors[nidx];
+					const float fac = custom_loopnors_facs ? custom_loopnors_facs[nidx] : 0.0f;
 
 					if (!org_nor) {
 						org_nor = nor;
+						org_fac = fac;
 					}
-					else if (dot_v3v3(org_nor, nor) < 1.0f - 1e-6f) {
+					else if (dot_v3v3(org_nor, nor) < 1.0f - 1e-6f ||
+					         (custom_loopnors_facs && fabsf(org_fac - fac) > 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
@@ -1287,12 +1269,14 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 						medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
 
 						org_nor = nor;
+						org_fac = fac;
 					}
 
 					prev_ml = ml;
 					loops = loops->next;
 					BLI_BITMAP_ENABLE(done_loops, lidx);
 				}
+				BLI_BITMAP_ENABLE(done_loops, i);  /* For single loops, where lnors_spaces.lspaces[i]->loops is NULL. */
 			}
 		}
 
@@ -1322,26 +1306,20 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 			if (loops) {
 				int nbr_nors = 0;
 				float avg_nor[3];
+				float avg_fac = 0.0f;
 				short clnor_data_tmp[2], *clnor_data;
 
 				zero_v3(avg_nor);
 				while (loops) {
 					const int lidx = GET_INT_FROM_POINTER(loops->link);
-					const int idx = use_vertices ? (int)mloops[lidx].v : lidx;
-					float *nor = custom_loopnors[idx];
-
-					if (custom_loopnors_facs && use_vertices && !BLI_BITMAP_TEST_BOOL(done_verts, idx)) {
-						const float fac = custom_loopnors_facs[idx];
-
-						if (fac != 1.0f) {
-							/* Note: inplace modification to get final custom lnor! */
-							interp_v3_v3v3_slerp_safe(nor, lnors_spaces.lspaces[i]->vec_lnor, nor, fac);
-						}
-						BLI_BITMAP_ENABLE(done_verts, idx);
-					}
+					const int nidx = use_vertices ? (int)mloops[lidx].v : lidx;
+					float *nor = custom_loopnors[nidx];
 
 					nbr_nors++;
 					add_v3_v3(avg_nor, nor);
+					if (custom_loopnors_facs) {
+						avg_fac += custom_loopnors_facs[nidx];
+					}
 					BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]);
 
 					loops = loops->next;
@@ -1349,6 +1327,12 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 				}
 
 				mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors);
+				if (custom_loopnors_facs) {
+					avg_fac /= (float)nbr_nors;
+					if (avg_fac < 1.0f - 1e-6f) {
+						interp_v3_v3v3_slerp_safe(avg_nor, lnors_spaces.lspaces[i]->vec_lnor, avg_nor, avg_fac);
+					}
+				}
 				BKE_lnor_space_custom_normal_to_data(lnors_spaces.lspaces[i], avg_nor, clnor_data_tmp);
 
 				while ((clnor_data = BLI_SMALLSTACK_POP(clnors_data))) {
@@ -1357,17 +1341,17 @@ static void mesh_normals_loop_custom_set(MVert *mverts, const int numVerts, MEdg
 				}
 			}
 			else {
-				const int idx = use_vertices ? (int)mloops[i].v : i;
-				float *nor = custom_loopnors[idx];
+				const int nidx = use_vertices ? (int)mloops[i].v : i;
+				float *nor = custom_loopnors[nidx];
+				float tnor[3];
 
-				if (custom_loopnors_facs && use_vertices && !BLI_BITMAP_TEST_BOOL(done_verts, idx)) {
-					const float fac = custom_loopnors_facs[idx];
+				if (custom_loopnors_facs) {
+					const float fac = custom_loopnors_facs[nidx];
 
-					if (fac != 1.0f) {
-						/* Note: inplace modification to get final custom lnor! */
-						interp_v3_v3v3_slerp_safe(nor, lnors_spaces.lspaces[i]->vec_lnor, nor, fac);
+					if (fac < 1.0f - 1e-6f) {
+						interp_v3_v3v3_slerp_safe(tnor, lnors_spaces.lspaces[i]->vec_lnor, nor, fac);
+						nor = tnor;
 					}
-					BLI_BITMAP_ENABLE(done_verts, idx);
 				}
 
 				BKE_lnor_space_custom_normal_to_data(lnors_spaces.lspaces[i], nor, r_clnors_data[i]);




More information about the Bf-blender-cvs mailing list