Commit: 1966924467c901d541bfe3f510d21a20c29842e3 Author: Campbell Barton Date: Mon Mar 12 13:46:25 2018 +1100 Branches: master https://developer.blender.org/rB1966924467c901d541bfe3f510d21a20c29842e3
UV: internal changes to picking Nothing user visible, only things needed for multi-object support, making picking functions more flexible too. - Support passing in an initialized hit-struct, so it's possible to do multiple nearest calls on the same hit data. - Replace manhattan distance w/ squared distance so they can be compared. - Return success to detect changes to a hit-data which might already be initialized (also more readable). =================================================================== M source/blender/editors/sculpt_paint/sculpt_uv.c M source/blender/editors/uvedit/uvedit_intern.h M source/blender/editors/uvedit/uvedit_ops.c M source/blender/editors/uvedit/uvedit_smart_stitch.c =================================================================== diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 5ef9d4a6499..7b636530d61 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -650,9 +650,9 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm /* we need to find the active island here */ if (do_island_optimization) { UvElement *element; - NearestHit hit; + UvNearestHit hit = UV_NEAREST_HIT_INIT; Image *ima = CTX_data_edit_image(C); - uv_find_nearest_vert(scene, ima, em, co, NULL, &hit); + uv_find_nearest_vert(scene, ima, em, co, 0.0f, &hit); element = BM_uv_element_get(data->elementMap, hit.efa, hit.l); island_index = element->island; diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index e028c08091c..b5ff46e9219 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -51,18 +51,31 @@ void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_off /* find nearest */ -typedef struct NearestHit { +typedef struct UvNearestHit { + /** Always set if we have a hit. */ struct BMFace *efa; struct MTexPoly *tf; struct BMLoop *l; struct MLoopUV *luv, *luv_next; - int lindex; /* index of loop within face */ -} NearestHit; + /** Index of loop within face. */ + int lindex; + /** Needs to be set before calling nearest functions. */ + float dist_sq; +} UvNearestHit; -void uv_find_nearest_vert(struct Scene *scene, struct Image *ima, struct BMEditMesh *em, - const float co[2], const float penalty[2], struct NearestHit *hit); -void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditMesh *em, - const float co[2], struct NearestHit *hit); +#define UV_NEAREST_HIT_INIT { .dist_sq = FLT_MAX, } + +bool uv_find_nearest_vert( + struct Scene *scene, struct Image *ima, struct BMEditMesh *em, + const float co[2], const float penalty_dist, struct UvNearestHit *hit_final); + +bool uv_find_nearest_edge( + struct Scene *scene, struct Image *ima, struct BMEditMesh *em, + const float co[2], struct UvNearestHit *hit_final); + +bool uv_find_nearest_face( + struct Scene *scene, struct Image *ima, struct BMEditMesh *em, + const float co[2], struct UvNearestHit *hit_final); /* utility tool functions */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index bf5a06f0a1c..1ee10268be5 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -760,83 +760,93 @@ static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2 /************************** find nearest ****************************/ -void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit) +bool uv_find_nearest_edge( + Scene *scene, Image *ima, BMEditMesh *em, const float co[2], + UvNearestHit *hit) { MTexPoly *tf; BMFace *efa; BMLoop *l; BMIter iter, liter; MLoopUV *luv, *luv_next; - float mindist_squared, dist_squared; int i; + bool found = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - mindist_squared = 1e10f; - memset(hit, 0, sizeof(*hit)); - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) + if (!uvedit_face_visible_test(scene, ima, efa, tf)) { continue; - + } BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); + const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); - if (dist_squared < mindist_squared) { + if (dist_test_sq < hit->dist_sq) { hit->tf = tf; hit->efa = efa; - + hit->l = l; hit->luv = luv; hit->luv_next = luv_next; hit->lindex = i; - mindist_squared = dist_squared; + hit->dist_sq = dist_test_sq; + found = true; } } } + return found; } -static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit) +bool uv_find_nearest_face( + Scene *scene, Image *ima, BMEditMesh *em, const float co[2], + UvNearestHit *hit_final) { - MTexPoly *tf; - BMFace *efa; - BMIter iter; - float mindist, dist, cent[2]; + bool found = false; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - mindist = 1e10f; - memset(hit, 0, sizeof(*hit)); + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, em, co, &hit)) { + hit.dist_sq = dist_sq_init; + hit.l = NULL; + hit.luv = hit.luv_next = NULL; - /*this will fill in hit.vert1 and hit.vert2*/ - uv_find_nearest_edge(scene, ima, em, co, hit); - hit->l = NULL; - hit->luv = hit->luv_next = NULL; + BMIter iter; + BMFace *efa; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) - continue; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) { + continue; + } - uv_poly_center(efa, cent, cd_loop_uv_offset); + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); - dist = len_manhattan_v2v2(co, cent); + const float dist_test_sq = len_squared_v2v2(co, cent); - if (dist < mindist) { - hit->tf = tf; - hit->efa = efa; - mindist = dist; + if (dist_test_sq < hit.dist_sq) { + hit.efa = efa; + hit.dist_sq = dist_test_sq; + found = true; + } } } + if (found) { + *hit_final = hit; + } + return found; } static bool uv_nearest_between(const BMLoop *l, const float co[2], @@ -850,60 +860,74 @@ static bool uv_nearest_between(const BMLoop *l, const float co[2], (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f)); } -void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, - float const co[2], const float penalty[2], NearestHit *hit) +bool uv_find_nearest_vert( + Scene *scene, Image *ima, BMEditMesh *em, + float const co[2], const float penalty_dist, UvNearestHit *hit_final) { - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MTexPoly *tf; - MLoopUV *luv; - float mindist, dist; - int i; + bool found = false; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, em, co, &hit)) { + hit.dist_sq = dist_sq_init; - /*this will fill in hit.vert1 and hit.vert2*/ - uv_find_nearest_edge(scene, ima, em, co, hit); - hit->l = NULL; - hit->luv = hit->luv_next = NULL; + hit.l = NULL; + hit.luv = hit.luv_next = NULL; - mindist = 1e10f; - memset(hit, 0, sizeof(*hit)); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); + BMFace *efa; + BMIter iter; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!uvedit_face_visible_test(scene, ima, efa, tf)) - continue; + BM_mesh_elem_index_ensure(em->bm, BM_VERT); - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (penalty && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) - dist = len_manhattan_v2v2(co, luv->uv) + len_manhattan_v2(penalty); - else - dist = len_manhattan_v2v2(co, luv->uv); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); - if (dist <= mindist) { - if (dist == mindist) { - if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { - continue; - } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) { + continue; + } + + BMIter liter; + BMLoop *l; + int i; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + float dist_test_sq; + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist; + dist_test_sq = SQUARE(dist_test_sq); + } + else { + dist_test_sq = len_squared_v2v2(co, luv->uv); } - mindist = dist; + if (dist_test_sq <= hit.dist_sq) { + if (dist_test_sq == hit.dist_sq) { + if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { + continue; + } + } - hit->l = l; - hit->luv = luv; - hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - hit->tf = tf; - hit->efa = efa; - hit->lindex = i; + hit.dist_sq = dist_test_sq; + + hit.l = l; + hit.luv = luv; + hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + hit.efa = efa; + hit.lindex = i; + found = true; + } } } } + + if (found) { + *hit_final = hit; + } + + return found; } bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float co[2], float r_uv[2]) @@ -1029,8 +1053,9 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMes @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs