[Bf-blender-cvs] [0c1934f3c2d] blender2.8: Multi-Objects: MESH_OT_select_similar worldspace completion

Habib Gahbiche noreply at git.blender.org
Fri Nov 9 20:19:15 CET 2018


Commit: 0c1934f3c2d3dff3bce65e2e8169866bafea04e0
Author: Habib Gahbiche
Date:   Fri Nov 9 17:03:41 2018 -0200
Branches: blender2.8
https://developer.blender.org/rB0c1934f3c2d3dff3bce65e2e8169866bafea04e0

Multi-Objects: MESH_OT_select_similar worldspace completion

This makes the operator to work 100% with worldspace similarity:
* SIMFACE_PERIMETER
* SIMFACE_AREA
* SIMEDGE_FACE_ANGLE

Note from revisor (Dalai Felinto):

I'm not sure we want to pass Object * to the bmesh api, though I
personally don't see why not. Either way I group the patches together so
we can more easily roll them back if needs be.

Maniphest Tasks: T56948
Differential Revision: D3908, D3899, D3896

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

M	source/blender/bmesh/intern/bmesh_polygon.c
M	source/blender/bmesh/intern/bmesh_polygon.h
M	source/blender/bmesh/intern/bmesh_query.c
M	source/blender/bmesh/intern/bmesh_query.h
M	source/blender/editors/mesh/editmesh_select_similar.c

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

diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 8c96c938cef..8374fd8f51f 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -30,6 +30,7 @@
 
 #include "DNA_listBase.h"
 #include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -239,6 +240,30 @@ float BM_face_calc_area(const BMFace *f)
 	return len_v3(n) * 0.5f;
 }
 
+/**
+ * Get the area of the face in world space.
+ */
+float BM_face_calc_area_worldspace(Object *ob, const BMFace *f)
+{
+	/* inline 'area_poly_v3' logic, avoid creating a temp array */
+	const BMLoop *l_iter, *l_first;
+	float n[3];
+
+	zero_v3(n);
+	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+	float rsmat[3][3];
+	copy_m3_m4(rsmat, ob->obmat);
+	do {
+		float co[3], co_next[3];
+		copy_v3_v3(co, l_iter->v->co);
+		copy_v3_v3(co_next, l_iter->next->v->co);
+		mul_m3_v3(rsmat, co);
+		mul_m3_v3(rsmat, co_next);
+		add_newell_cross_v3_v3v3(n, co, co_next);
+	} while ((l_iter = l_iter->next) != l_first);
+	return len_v3(n) * 0.5f;
+}
+
 /**
  * compute the perimeter of an ngon
  */
@@ -255,6 +280,29 @@ float BM_face_calc_perimeter(const BMFace *f)
 	return perimeter;
 }
 
+/**
+ * Calculate the perimeter of a ngon in world space.
+ */
+float BM_face_calc_perimeter_worldspace(Object *ob, const BMFace *f)
+{
+	const BMLoop *l_iter, *l_first;
+	float perimeter = 0.0f;
+
+	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+	float rsmat[3][3];
+	copy_m3_m4(rsmat, ob->obmat);
+	do {
+		float co[3], co_next[3];
+		copy_v3_v3(co, l_iter->v->co);
+		copy_v3_v3(co_next, l_iter->next->v->co);
+		mul_m3_v3(rsmat, co);
+		mul_m3_v3(rsmat, co_next);
+		perimeter += len_v3v3(co, co_next);
+	} while ((l_iter = l_iter->next) != l_first);
+
+	return perimeter;
+}
+
 /**
  * Utility function to calculate the edge which is most different from the other two.
  *
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index a40da2bfbfa..29bb49a8e40 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -28,6 +28,7 @@
  */
 
 struct Heap;
+struct Object;
 
 #include "BLI_compiler_attrs.h"
 
@@ -44,7 +45,9 @@ float BM_face_calc_normal_vcos(
         float const (*vertexCos)[3]) ATTR_NONNULL();
 float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) ATTR_NONNULL();
 float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_face_calc_area_worldspace(struct Object *ob, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 float BM_face_calc_perimeter(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_face_calc_perimeter_worldspace(struct Object *ob, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 void  BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
 void  BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
 void  BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 540888ac0b9..c51c6322136 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -31,6 +31,8 @@
  * of inspecting the mesh structure directly.
  */
 
+#include "DNA_object_types.h"
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_math.h"
@@ -39,6 +41,7 @@
 #include "BLI_utildefines_stack.h"
 
 #include "BKE_customdata.h"
+#include "BKE_object.h"
 
 #include "bmesh.h"
 #include "intern/bmesh_private.h"
@@ -1677,6 +1680,43 @@ float BM_edge_calc_face_angle(const BMEdge *e)
 	return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f));
 }
 
+/**
+* \brief BMESH EDGE/FACE ANGLE
+*
+* Calculates the angle between two faces in world space.
+* Assumes the face normals are correct.
+*
+* \return angle in radians
+*/
+float BM_edge_calc_face_angle_worldspace_ex(Object *ob, const BMEdge *e, const float fallback)
+{
+	if (BM_edge_is_manifold(e)) {
+		const BMLoop *l1 = e->l;
+		const BMLoop *l2 = e->l->radial_next;
+		float no1[3], no2[3];
+		copy_v3_v3(no1, l1->f->no);
+		copy_v3_v3(no2, l2->f->no);
+
+		float smat[3][3];
+		BKE_object_scale_to_mat3(ob, smat);
+		invert_m3(smat);
+
+		mul_m3_v3(smat, no1);
+		mul_m3_v3(smat, no2);
+		normalize_v3(no1);
+		normalize_v3(no2);
+
+		return angle_normalized_v3v3(no1, no2);
+	}
+	else {
+		return fallback;
+	}
+}
+float BM_edge_calc_face_angle_worldspace(Object *ob, const BMEdge *e)
+{
+	return BM_edge_calc_face_angle_worldspace_ex(ob, e, DEG2RADF(90.0f));
+}
+
 /**
  * \brief BMESH EDGE/FACE ANGLE
  *
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index 51956761d8f..1cfd6cc07a3 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -27,6 +27,8 @@
  *  \ingroup bmesh
  */
 
+struct Object;
+
 bool    BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 int     BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 bool    BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -123,6 +125,8 @@ void    BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
 float   BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 float   BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 float   BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float   BM_edge_calc_face_angle_worldspace_ex(struct Object *ob, const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float   BM_edge_calc_face_angle_worldspace(struct Object *ob, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 float   BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 void    BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
 
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index d33802dca05..85b59cb78c3 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -293,14 +293,14 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
 					}
 					case SIMFACE_AREA:
 					{
-						float area = BM_face_calc_area(face);
+						float area = BM_face_calc_area_worldspace(ob, face);
 						float dummy[3] = {area, 0.0f, 0.0f};
 						BLI_kdtree_insert(tree, tree_index++, dummy);
 						break;
 					}
 					case SIMFACE_PERIMETER:
 					{
-						float perimeter = BM_face_calc_perimeter(face);
+						float perimeter = BM_face_calc_perimeter_worldspace(ob, face);
 						float dummy[3] = {perimeter, 0.0f, 0.0f};
 						BLI_kdtree_insert(tree, tree_index++, dummy);
 						break;
@@ -440,7 +440,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
 					}
 					case SIMFACE_AREA:
 					{
-						float area = BM_face_calc_area(face);
+						float area = BM_face_calc_area_worldspace(ob, face);
 						if (ED_select_similar_compare_float_tree(tree, area, thresh, compare)) {
 							select = true;
 						}
@@ -448,7 +448,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
 					}
 					case SIMFACE_PERIMETER:
 					{
-						float perimeter = BM_face_calc_perimeter(face);
+						float perimeter = BM_face_calc_perimeter_worldspace(ob, face);
 						if (ED_select_similar_compare_float_tree(tree, perimeter, thresh, compare)) {
 							select = true;
 						}
@@ -774,7 +774,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
 					case SIMEDGE_FACE_ANGLE:
 					{
 						if (BM_edge_face_count_at_most(edge, 2) == 2) {
-							float angle = BM_edge_calc_face_angle(edge);
+							float angle = BM_edge_calc_face_angle_worldspace(ob, edge);
 							float dummy[3] = {angle, 0.0f, 0.0f};
 							BLI_kdtree_insert(tree, tree_index++, dummy);
 						}
@@ -904,7 +904,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
 					case SIMEDGE_FACE_ANGLE:
 					{
 						if (BM_edge_face_count_at_most(edge, 2) == 2) {
-							float angle = BM_edge_calc_face_angle(edge);
+							float angle = BM_edge_calc_face_angle_worldspace(ob, edge);
 							if (ED_select_similar_compare_float_tree(tree, angle, thresh, SIM_CMP_EQ)) {
 								select = true;
 							}



More information about the Bf-blender-cvs mailing list