[Bf-blender-cvs] [9ce20d3] master: BMesh: join tris now delimits all UV/Color layers

Campbell Barton noreply at git.blender.org
Tue May 26 05:45:19 CEST 2015


Commit: 9ce20d3341cf215233f46f0326a9619fe80b6cb2
Author: Campbell Barton
Date:   Tue May 26 13:39:07 2015 +1000
Branches: master
https://developer.blender.org/rB9ce20d3341cf215233f46f0326a9619fe80b6cb2

BMesh: join tris now delimits all UV/Color layers

Previously was only checking active layers

Also add delimit by edge seam

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

M	source/blender/bmesh/intern/bmesh_opdefines.c
M	source/blender/bmesh/operators/bmo_join_triangles.c
M	source/blender/editors/mesh/editmesh_tools.c

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

diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 2ba65f5..211c53a 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -493,6 +493,7 @@ static BMOpDefine bmo_join_triangles_def = {
 	"join_triangles",
 	/* slots_in */
 	{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input geometry. */
+	 {"cmp_seam", BMO_OP_SLOT_BOOL},
 	 {"cmp_sharp", BMO_OP_SLOT_BOOL},
 	 {"cmp_uvs", BMO_OP_SLOT_BOOL},
 	 {"cmp_vcols", BMO_OP_SLOT_BOOL},
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 5705b8e..06200ba 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -42,164 +42,219 @@
 
 #include "intern/bmesh_operators_private.h" /* own include */
 
-#define FACE_OUT (1 << 0)
-
 /* assumes edges are validated before reaching this poin */
-static float measure_facepair(
+static float quad_calc_error(
         const float v1[3], const float v2[3],
-        const float v3[3], const float v4[3],
-        const float limit)
+        const float v3[3], const float v4[3])
 {
 	/* gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make */
 	/* Note: this is more complicated than it needs to be and should be cleaned up.. */
-	float n1[3], n2[3], measure = 0.0f, angle1, angle2, diff;
-	float edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3];
-	float minarea, maxarea, areaA, areaB;
-
-	/* First Test: Normal difference */
-	normal_tri_v3(n1, v1, v2, v3);
-	normal_tri_v3(n2, v1, v3, v4);
-	angle1 = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
-
-	normal_tri_v3(n1, v2, v3, v4);
-	normal_tri_v3(n2, v4, v1, v2);
-	angle2 = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
-
-	measure += (angle1 + angle2) * 0.5f;
-	if (measure > limit) {
-		return measure;
-	}
+	float error = 0.0f;
+
+	/* Normal difference */
+	{
+		float n1[3], n2[3];
+		float angle_a, angle_b;
+		float diff;
 
-	/* Second test: Colinearity */
-	sub_v3_v3v3(edgeVec1, v1, v2);
-	sub_v3_v3v3(edgeVec2, v2, v3);
-	sub_v3_v3v3(edgeVec3, v3, v4);
-	sub_v3_v3v3(edgeVec4, v4, v1);
-
-	normalize_v3(edgeVec1);
-	normalize_v3(edgeVec2);
-	normalize_v3(edgeVec3);
-	normalize_v3(edgeVec4);
-
-	/* a completely skinny face is 'pi' after halving */
-	diff = 0.25f * (fabsf(angle_normalized_v3v3(edgeVec1, edgeVec2) - (float)M_PI_2) +
-	                fabsf(angle_normalized_v3v3(edgeVec2, edgeVec3) - (float)M_PI_2) +
-	                fabsf(angle_normalized_v3v3(edgeVec3, edgeVec4) - (float)M_PI_2) +
-	                fabsf(angle_normalized_v3v3(edgeVec4, edgeVec1) - (float)M_PI_2));
-
-	if (!diff) {
-		return 0.0;
+		normal_tri_v3(n1, v1, v2, v3);
+		normal_tri_v3(n2, v1, v3, v4);
+		angle_a = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
+
+		normal_tri_v3(n1, v2, v3, v4);
+		normal_tri_v3(n2, v4, v1, v2);
+		angle_b = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
+
+		diff = (angle_a + angle_b) / (float)(M_PI * 2);
+
+		error += diff;
 	}
 
-	measure +=  diff;
-	if (measure > limit) {
-		return measure;
+	/* Colinearity */
+	{
+		float edge_vecs[4][3];
+		float diff;
+
+		sub_v3_v3v3(edge_vecs[0], v1, v2);
+		sub_v3_v3v3(edge_vecs[1], v2, v3);
+		sub_v3_v3v3(edge_vecs[2], v3, v4);
+		sub_v3_v3v3(edge_vecs[3], v4, v1);
+
+		normalize_v3(edge_vecs[0]);
+		normalize_v3(edge_vecs[1]);
+		normalize_v3(edge_vecs[2]);
+		normalize_v3(edge_vecs[3]);
+
+		/* a completely skinny face is 'pi' after halving */
+		diff = (fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) +
+		        fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) +
+		        fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) +
+		        fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2)) / (float)(M_PI * 2);
+
+		error += diff;
 	}
 
-	/* Third test: Concavity */
-	areaA = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v3, v4);
-	areaB = area_tri_v3(v2, v3, v4) + area_tri_v3(v4, v1, v2);
+	/* Concavity */
+	{
+		float area_min, area_max, area_a, area_b;
+		float diff;
 
-	if (areaA <= areaB) minarea = areaA;
-	else minarea = areaB;
+		area_a = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v3, v4);
+		area_b = area_tri_v3(v2, v3, v4) + area_tri_v3(v4, v1, v2);
 
-	if (areaA >= areaB) maxarea = areaA;
-	else maxarea = areaB;
+		area_min = min_ff(area_a, area_b);
+		area_max = max_ff(area_a, area_b);
 
-	if (!maxarea) measure += 1;
-	else measure += (1 - (minarea / maxarea));
+		diff = area_max ? (1.0 - (area_min / area_max)) : 1.0f;
 
-	return measure;
+		error += diff;
+	}
+
+	return error;
 }
 
-#define T2QUV_LIMIT 0.005f
-#define T2QCOL_LIMIT 3
+static void bm_edge_to_quad_verts(const BMEdge *e, const BMVert *r_v_quad[4])
+{
+	BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3);
+	BLI_assert(BM_edge_is_manifold(e));
+	r_v_quad[0] = e->l->v;
+	r_v_quad[1] = e->l->prev->v;
+	r_v_quad[2] = e->l->next->v;
+	r_v_quad[3] = e->l->radial_next->prev->v;
+}
 
-static bool bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const bool do_uv, const bool do_tf, const bool do_vcol)
+/* cache customdata delimiters */
+struct DelimitData_CD {
+	int cd_type;
+	int cd_size;
+	int cd_offset;
+	int cd_offset_end;
+};
+
+struct DelimitData {
+	unsigned int do_seam : 1;
+	unsigned int do_sharp : 1;
+	unsigned int do_mat : 1;
+	unsigned int do_angle : 1;
+
+	float angle;
+	float angle__cos;
+
+	struct DelimitData_CD cdata[4];
+	int cdata_len;
+};
+
+static bool bm_edge_is_contiguous_loop_cd_all(
+        const BMEdge *e, const struct DelimitData_CD *delimit_data)
 {
-	/* first get loops */
-	BMLoop *l[4];
-
-	l[0] = e->l;
-	l[2] = e->l->radial_next;
-	
-	/* match up loops on each side of an edge corresponding to each vert */
-	if (l[0]->v == l[2]->v) {
-		l[1] = l[0]->next;
-		l[3] = l[1]->next;
+	int cd_offset;
+	for (cd_offset = delimit_data->cd_offset;
+	     cd_offset < delimit_data->cd_offset_end;
+	     cd_offset += delimit_data->cd_size)
+	{
+		if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_type, cd_offset) == false) {
+			return false;
+		}
 	}
-	else {
-		l[1] = l[0]->next;
 
-		l[3] = l[2];
-		l[2] = l[3]->next;
+	return true;
+}
+
+static bool bm_edge_delimit_cdata(
+        CustomData *ldata, CustomDataType type,
+        struct DelimitData_CD *r_delim_cd)
+{
+	const int layer_len = CustomData_number_of_layers(ldata, type);
+	r_delim_cd->cd_type = type;
+	r_delim_cd->cd_size = CustomData_sizeof(r_delim_cd->cd_type);
+	r_delim_cd->cd_offset = CustomData_get_n_offset(ldata, type, 0);
+	r_delim_cd->cd_offset_end = r_delim_cd->cd_size * layer_len;
+	return (r_delim_cd->cd_offset != -1);
+}
+
+static float bm_edge_is_delimit(
+        const BMEdge *e,
+        const struct DelimitData *delimit_data)
+{
+	BMFace *f_a = e->l->f, *f_b = e->l->radial_next->f;
+#if 0
+	const bool is_contig = BM_edge_is_contiguous(e);
+	float angle;
+#endif
+
+	if ((delimit_data->do_seam) &&
+	    (BM_elem_flag_test(e, BM_ELEM_SEAM)))
+	{
+		goto fail;
 	}
 
-	/* Test UV's */
-	if (do_uv) {
-		const MLoopUV *luv[4] = {
-		    CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPUV),
-		    CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPUV),
-		    CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPUV),
-		    CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPUV),
-		};
-
-		/* do UV */
-		if (luv[0] && (!compare_v2v2(luv[0]->uv, luv[2]->uv, T2QUV_LIMIT) ||
-		               !compare_v2v2(luv[1]->uv, luv[3]->uv, T2QUV_LIMIT)))
-		{
-			return false;
-		}
+	if ((delimit_data->do_sharp) &&
+	    (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0))
+	{
+		goto fail;
 	}
 
-	if (do_tf) {
-		const MTexPoly *tp[2] = {
-		    CustomData_bmesh_get(&bm->pdata, l[0]->f->head.data, CD_MTEXPOLY),
-		    CustomData_bmesh_get(&bm->pdata, l[1]->f->head.data, CD_MTEXPOLY),
-		};
+	if ((delimit_data->do_mat) &&
+	    (f_a->mat_nr != f_b->mat_nr))
+	{
+		goto fail;
+	}
 
-		if (tp[0] && (tp[0]->tpage != tp[1]->tpage)) {
-			return false;
+	if (delimit_data->do_angle) {
+		if (dot_v3v3(f_a->no, f_b->no) < delimit_data->angle__cos) {
+			goto fail;
+		}
+		else {
+			const BMVert *verts[4];
+			float edge_vecs[4][3];
+
+			bm_edge_to_quad_verts(e, verts);
+
+			sub_v3_v3v3(edge_vecs[0], verts[0]->co, verts[1]->co);
+			sub_v3_v3v3(edge_vecs[1], verts[1]->co, verts[2]->co);
+			sub_v3_v3v3(edge_vecs[2], verts[2]->co, verts[3]->co);
+			sub_v3_v3v3(edge_vecs[3], verts[3]->co, verts[0]->co);
+
+			normalize_v3(edge_vecs[0]);
+			normalize_v3(edge_vecs[1]);
+			normalize_v3(edge_vecs[2]);
+			normalize_v3(edge_vecs[3]);
+
+			if ((fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) > delimit_data->angle) ||
+			    (fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) > delimit_data->angle) ||
+			    (fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) > delimit_data->angle) ||
+			    (fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2) > delimit_data->angle))
+			{
+				goto fail;
+			}
 		}
 	}
 
-	/* Test Vertex Colors */
-	if (do_vcol) {
-		const MLoopCol *lcol[4] = {
-		    CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPCOL),
-			CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPCOL),
-			CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPCOL),
-			CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPCOL),
-		};
-
-		if (lcol[0]) {
-			if (!compare_rgb_uchar((unsigned char *)&lcol[0]->r, (unsigned char *)&lcol[2]->r, T2QCOL_LIMIT) ||
-			    !compare_rgb_uchar((unsigned char *)&lcol[1]->r, (unsigned char *)&lcol[3]->r, T2QCOL_LIMIT))
-			{
-				return false;
+	if (delimit_data->cdata_len) {
+		int i;
+		for (i = 0; i < delimit_data->cdata_len; i++) {
+			if (!bm_edge_is_contiguous_loop_cd_all(e, &delimit_data->cdata[i])) {
+				goto fail;
 			}
 		}
 	}
 
+	return false;
+
+fail:
 	return true;
 }
 
 
-#define EDGE_MARK	1
-#define EDGE_CHOSEN	2
-
-#define FACE_MARK	1
-#defin

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list