diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index a2aecf80456..8b185b17a3a 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -225,20 +225,26 @@ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) return len_v3(n) * 0.5f; } -float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) +float BM_face_calc_area_uv_signed(const BMFace *f, int cd_loop_uv_offset) { /* inline 'area_poly_v2' logic, avoid creating a temp array */ const BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); - /* The Trapezium Area Rule */ + /* Green's theorem applied to area of a polygon. + * TODO: `cross` should be of type `double` to reduce rounding error. */ float cross = 0.0f; do { const float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset); const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l_iter->next, cd_loop_uv_offset); cross += (luv_next[0] - luv[0]) * (luv_next[1] + luv[1]); } while ((l_iter = l_iter->next) != l_first); - return fabsf(cross * 0.5f); + return cross * 0.5f; +} + +float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) +{ + return fabsf(BM_face_calc_area_uv_signed(f, cd_loop_uv_offset)); } float BM_face_calc_perimeter(const BMFace *f) diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 6262f185eca..bff1d1d587d 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -73,7 +73,12 @@ float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /** - * get the area of UV face + * Calculate the signed area of UV face. + */ +float BM_face_calc_area_uv_signed(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +/** + * Calculate the area of UV face. */ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 50185049fe1..99ee1ca0002 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -87,9 +87,11 @@ typedef enum { UV_SSIM_FACE, UV_SSIM_LENGTH_UV, UV_SSIM_LENGTH_3D, - UV_SSIM_SIDES, - UV_SSIM_PIN, UV_SSIM_MATERIAL, + UV_SSIM_OBJECT, + UV_SSIM_PIN, + UV_SSIM_SIDES, + UV_SSIM_WINDING, } eUVSelectSimilar; /* -------------------------------------------------------------------- */ @@ -4633,6 +4635,7 @@ static float get_uv_edge_needle(const eUVSelectSimilar type, static float get_uv_face_needle(const eUVSelectSimilar type, BMFace *face, + int ob_index, const float ob_m3[3][3], const BMUVOffsets offsets) { @@ -4646,6 +4649,8 @@ static float get_uv_face_needle(const eUVSelectSimilar type, return BM_face_calc_area_with_mat3(face, ob_m3); case UV_SSIM_SIDES: return face->len; + case UV_SSIM_OBJECT: + return ob_index; case UV_SSIM_PIN: { BMLoop *l; BMIter liter; @@ -4657,6 +4662,8 @@ static float get_uv_face_needle(const eUVSelectSimilar type, } break; case UV_SSIM_MATERIAL: return face->mat_nr; + case UV_SSIM_WINDING: + return signum_i(BM_face_calc_area_uv_signed(face, offsets.uv)); default: BLI_assert_unreachable(); return false; @@ -4966,7 +4973,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op) continue; } - float needle = get_uv_face_needle(type, face, ob_m3, offsets); + float needle = get_uv_face_needle(type, face, ob_index, ob_m3, offsets); if (tree_1d) { BLI_kdtree_1d_insert(tree_1d, tree_index++, &needle); } @@ -5000,7 +5007,7 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op) continue; } - float needle = get_uv_face_needle(type, face, ob_m3, offsets); + float needle = get_uv_face_needle(type, face, ob_index, ob_m3, offsets); bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); if (select) { @@ -5180,8 +5187,10 @@ static EnumPropertyItem prop_edge_similar_types[] = { static EnumPropertyItem prop_face_similar_types[] = { {UV_SSIM_AREA_UV, "AREA", 0, "Area", ""}, {UV_SSIM_AREA_3D, "AREA_3D", 0, "Area 3D", ""}, - {UV_SSIM_SIDES, "SIDES", 0, "Polygon Sides", ""}, {UV_SSIM_MATERIAL, "MATERIAL", 0, "Material", ""}, + {UV_SSIM_OBJECT, "OBJECT", 0, "Object", ""}, + {UV_SSIM_SIDES, "SIDES", 0, "Polygon Sides", ""}, + {UV_SSIM_WINDING, "WINDING", 0, "Winding", ""}, {0}}; static EnumPropertyItem prop_island_similar_types[] = {