[Bf-blender-cvs] [9b3d415f6a] master: Fix more corner cases failing in mesh faces split

Sergey Sharybin noreply at git.blender.org
Wed Feb 15 23:11:08 CET 2017


Commit: 9b3d415f6a315d8f79c58de189dbce18a4c2b5f0
Author: Sergey Sharybin
Date:   Wed Feb 15 23:09:31 2017 +0100
Branches: master
https://developer.blender.org/rB9b3d415f6a315d8f79c58de189dbce18a4c2b5f0

Fix more corner cases failing in mesh faces split

Now we handle properly case with edge-fan meshes, which should
fix bad topology calculated for cash register which was causing
crashes in the studio.

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

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

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

diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3d50b4729f..33e29dc0ff 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -2095,140 +2095,168 @@ void BKE_mesh_calc_normals_split(Mesh *mesh)
 	}
 }
 
-static void mesh_clear_vert_flags(Mesh *mesh)
-{
-	const int num_verts = mesh->totvert;
-	MVert *mvert = mesh->mvert;
-	for (int i = 0; i < num_verts; ++i, ++mvert) {
-		mvert->flag &= ~ME_VERT_TMP_TAG;
-	}
-}
-
-static void mesh_clear_edge_flags(Mesh *mesh)
-{
-	const int num_edge = mesh->totedge;
-	MEdge *medge = mesh->medge;
-	for (int i = 0; i < num_edge; ++i, ++medge) {
-		medge->flag &= ~ME_EDGE_TMP_TAG;
-	}
-}
+/* Split faces helper functions. */
 
-static int count_split_vert(MVert *mvert)
-{
-	if ((mvert->flag & ME_VERT_TMP_TAG) == 0) {
-		mvert->flag |= ME_VERT_TMP_TAG;
-		return 0;
-	}
-	else {
-		return 1;
-	}
-}
-
-static int count_split_edge(MEdge *medge)
-{
-	if ((medge->flag & ME_EDGE_TMP_TAG) == 0) {
-		medge->flag |= ME_EDGE_TMP_TAG;
-		return 0;
-	}
-	else {
-		return 1;
-	}
-}
+enum {
+	/* Vertex is adjacent to some loop which normal is different,
+	 * hence split of this vertex is required.
+	 */
+	SPLIT_VERT_NEED_SPLIT = (1 << 0),
+	/* Original vertex was already re-used by split logic. */
+	SPLIT_VERT_REUSED     = (1 << 1),
+};
+enum {
+	/* Edge is adjacent to any of vertex tagged for split.
+	 */
+	SPLIT_EDGE_NEED_SPLIT = (1 << 0),
+	/* Original edge was already re-used by split logic. */
+	SPLIT_EDGE_REUSED     = (1 << 1),
+};
 
-/* Split faces based on the edge angle.
- * Matches behavior of face splitting in render engines.
+/* Tag vertices which normals are not equal to any adjacent loop
+ * and hence split on that vertex is required.
+ *
+ * Returns truth if any of vertex needs to be split.
  */
-void BKE_mesh_split_faces(Mesh *mesh)
+static bool split_faces_tag_verts(const Mesh *mesh, uchar *vert_flags)
 {
-	const int num_verts = mesh->totvert;
-	const int num_edges = mesh->totedge;
 	const int num_polys = mesh->totpoly;
-	MVert *mvert = mesh->mvert;
-	MEdge *medge = mesh->medge;
-	MLoop *mloop = mesh->mloop;
-	MPoly *mpoly = mesh->mpoly;
-	float (*lnors)[3];
-	int num_new_verts = 0, num_new_edges = 0;
-	if ((mesh->flag & ME_AUTOSMOOTH) == 0) {
-		return;
-	}
-	if (num_polys == 0) {
-		return;
-	}
-	BKE_mesh_tessface_clear(mesh);
-	/* Compute loop normals if needed. */
-	if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
-		BKE_mesh_calc_normals_split(mesh);
-	}
-	lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
-	/* Clear runtime flags. */
-	mesh_clear_vert_flags(mesh);
-	mesh_clear_edge_flags(mesh);
-	/* Count number of vertices to be split. */
+	const MVert *mvert = mesh->mvert;
+	const MLoop *mloop = mesh->mloop;
+	const MPoly *mpoly = mesh->mpoly;
+	float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+	bool has_split_verts = false;
 	for (int poly = 0; poly < num_polys; poly++) {
-		MPoly *mp = &mpoly[poly];
+		const MPoly *mp = &mpoly[poly];
 		for (int loop = 0; loop < mp->totloop; loop++) {
 			const MLoop *ml = &mloop[mp->loopstart + loop];
-			MVert *mv = &mvert[ml->v];
+			const MVert *mv = &mvert[ml->v];
 			float vn[3];
 			normal_short_to_float_v3(vn, mv->no);
 			if (len_squared_v3v3(vn, lnors[mp->loopstart + loop]) > FLT_EPSILON) {
-				/* When vertex is adjacent to two faces and gets split we don't
-				 * want new vertex counted for both faces. We tag it for re-use
-				 * by one of the faces.
-				 */
-				num_new_verts += count_split_vert(mv);
+				vert_flags[ml->v] |= SPLIT_VERT_NEED_SPLIT;
+				has_split_verts = true;
 			}
 		}
 	}
-	if (num_new_verts == 0) {
-		/* No new vertices are to be added, can do early exit. */
-		return;
+	return has_split_verts;
+}
+
+/* Count number of new vertices to be added.
+ *
+ * Note that one of the loop where split is required will re-use
+ * it's vertex in order to avoid creation of loose vertices.
+ */
+static int split_faces_count_new_verts(const Mesh *mesh, uchar *vert_flags)
+{
+	const int num_polys = mesh->totpoly;
+	const MLoop *mloop = mesh->mloop;
+	const MPoly *mpoly = mesh->mpoly;
+	int num_new_verts = 0;
+	for (int poly = 0; poly < num_polys; poly++) {
+		const MPoly *mp = &mpoly[poly];
+		for (int loop = 0; loop < mp->totloop; loop++) {
+			const MLoop *ml = &mloop[mp->loopstart + loop];
+			if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) {
+				if (vert_flags[ml->v] & SPLIT_VERT_REUSED) {
+					++num_new_verts;
+				}
+				else {
+					vert_flags[ml->v] |= SPLIT_VERT_REUSED;
+				}
+			}
+		}
 	}
-	/* Count number of edges to be added. */
+	return num_new_verts;
+}
+
+/* Tag edges which are adjacent to at least one vertex tagged for split. */
+static void split_faces_tag_edges(Mesh *mesh,
+                                  const uchar *vert_flags,
+                                  uchar *edge_flags)
+{
+	const int num_polys = mesh->totpoly;
+	const MLoop *mloop = mesh->mloop;
+	const MPoly *mpoly = mesh->mpoly;
 	for (int poly = 0; poly < num_polys; poly++) {
-		MPoly *mp = &mpoly[poly];
+		const MPoly *mp = &mpoly[poly];
 		int loop_prev = mp->totloop - 1;
 		for (int loop = 0; loop < mp->totloop; loop++) {
 			const int poly_loop_prev = mp->loopstart + loop_prev;
 			const MLoop *ml = &mloop[mp->loopstart + loop];
-			const MVert *mv = &mvert[ml->v];
 			const MLoop *ml_prev = &mloop[poly_loop_prev];
-			const MVert *mv_prev = &mvert[ml_prev->v];
-			MEdge *me_prev = &medge[ml_prev->e];
-			if (mv->flag & ME_VERT_TMP_TAG) {
-				if (mv_prev->flag & ME_VERT_TMP_TAG) {
+			const int mv_flag = vert_flags[ml->v];
+			const int mv_prev_flag = vert_flags[ml_prev->v];
+			bool need_split = false;
+			if (mv_flag & SPLIT_VERT_NEED_SPLIT) {
+				if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) {
 					/* Create new edge between twp split vertices. */
-					num_new_edges += count_split_edge(me_prev);
+					need_split = true;
 				}
 				else {
 					/* Create new edge from existing vertex to a split one. */
-					num_new_edges += count_split_edge(me_prev);
+					need_split = true;
 				}
 			}
-			else if (mv_prev->flag & ME_VERT_TMP_TAG) {
+			else if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) {
 				/* Create new edge from split vertex to existing one. */
-				num_new_edges += count_split_edge(me_prev);
+				need_split = true;
+			}
+			if (need_split) {
+				edge_flags[ml_prev->e] |= SPLIT_EDGE_NEED_SPLIT;
 			}
 			loop_prev = loop;
 		}
 	}
-	/* Clear runtime flags again, they will be reused. */
-	mesh_clear_vert_flags(mesh);
-	mesh_clear_edge_flags(mesh);
-	/* Reallocate all vert and edge related data. */
-	mesh->totvert += num_new_verts;
-	mesh->totedge += num_new_edges;
-	CustomData_realloc(&mesh->vdata, mesh->totvert);
-	CustomData_realloc(&mesh->edata, mesh->totedge);
-	/* Update pointers to a newly allocated memory. */
-	BKE_mesh_update_customdata_pointers(mesh, false);
-	mvert = mesh->mvert;
-	medge = mesh->medge;
-	/* Perform actual split of vertices and adjacent edges. */
-	num_new_verts = 0;
-	num_new_edges = 0;
-	/* Insert new split vertices. */
+}
+
+/* Count number of new edges to be added.
+ *
+ * Note that one of the loop where split is required will re-use
+ * it's edge in order to avoid creation of loose edges.
+ */
+static int split_faces_count_new_edges(const Mesh *mesh, uchar *edge_flags)
+{
+	const int num_polys = mesh->totpoly;
+	const MLoop *mloop = mesh->mloop;
+	const MPoly *mpoly = mesh->mpoly;
+	int num_new_edges = 0;
+	for (int poly = 0; poly < num_polys; poly++) {
+		const MPoly *mp = &mpoly[poly];
+		for (int loop = 0; loop < mp->totloop; loop++) {
+			const MLoop *ml = &mloop[mp->loopstart + loop];
+			if (edge_flags[ml->e] & SPLIT_EDGE_NEED_SPLIT) {
+				if (edge_flags[ml->e] & SPLIT_EDGE_REUSED) {
+					++num_new_edges;
+				}
+				else {
+					edge_flags[ml->e] |= SPLIT_EDGE_REUSED;
+				}
+			}
+		}
+	}
+	return num_new_edges;
+}
+
+/* Perform actual split of vertices.
+ *
+ * NOTE: Will leave edges in inconsistent state.
+ */
+static void split_faces_split_verts(Mesh *mesh,
+                                    const int num_new_verts,
+                                    uchar *vert_flags)
+{
+	const int num_verts = mesh->totvert - num_new_verts;
+	const int num_polys = mesh->totpoly;
+	MVert *mvert = mesh->mvert;
+	MLoop *mloop = mesh->mloop;
+	MPoly *mpoly = mesh->mpoly;
+	const float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+	int num_added_verts = 0;
+	/* Clear reused flag, we need it again. */
+	for (int i = 0; i < num_verts; ++i) {
+		vert_flags[i] &= ~SPLIT_VERT_REUSED;
+	}
 	for (int poly = 0; poly < num_polys; poly++) {
 		MPoly *mp = &mpoly[poly];
 		/* First we split all vertices to get proper flag whether they are
@@ -2237,76 +2265,124 @@ void BKE_mesh_split_faces(Mesh *mesh)
 		for (int loop = 0; loop < mp->totloop; loop++) {
 			int poly_loop = mp->loopstart + loop;
 			MLoop *ml = &mloop[poly_loop];
-			MVert *mv = &mvert[ml->v];
-			float vn[3];
-			normal_short_to_float_v3(vn, mv->no);
-			if (len_squared_v3v3(vn, lnors[mp->loopstart + loop]) > FLT_EPSILON) {
-				if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
+			if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) {
+				if ((vert_flags[ml->v] & SPLIT_VERT_REUSED) == 0) {
 					/* Ignore first split on vertex, re-use it instead. */
-					mv->flag |= ME_VERT_TMP_TAG;
+					vert_flags[ml->v] |= SPLIT_VERT_REUSED;
 					continue;
 				}
-				/* Cretae new vertex. */
-				int new_vert = num_verts + num_new_verts;
+				/* Create new vertex. */
+				int new_vert = num_verts + num_added_verts;
 				CustomData_copy_data(&mesh->vdata, &mesh->vdata,
 				                     ml->v, new_vert, 1);
 				normal_float_to_short_v3(mvert[new_vert].no,
 				                         lnors[poly_loop]);
 				ml->v = new_vert;
-				num_new_verts++;
+				num_added_verts++;
 			}
 		}
 	}
-	/* Connect new vertices with edges. */
+}
+
+/* Perform actual split of edges.
+ *
+ * NOTE: Will correct all edges.
+ */
+static void split_faces_split_edges(Mesh *mesh,
+                                    const int num_new_edges,
+                                    uchar *edge_flags)
+{
+	const int num_edges = mesh->totedge - num_new_edges;
+	const int num_p

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list