UV: add "similar object" and "similar winding" to uv "select similar"

Adds new options to UV Face selection in the UV Editor, with UV > Select > Select Similar

In multi object edit mode, "Similar Object" selects faces which have the same object.

"Similar Winding" will select faces which have the same winding, i.e. are they
facing upwards or downwards.

Resolves: T103975
Differential Revision: https://developer.blender.org/D17125
This commit is contained in:
Chris Blackbourn 2023-01-27 17:52:31 +13:00
parent 6c8db7c22b
commit 2b4bafeac6
Notes: blender-bot 2023-02-14 06:45:14 +01:00
Referenced by issue #103975, UV: "Select by object" for select Similar
3 changed files with 29 additions and 9 deletions

View File

@ -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)

View File

@ -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();

View File

@ -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[] = {