diff options
Diffstat (limited to 'source/blender/editors/transform')
5 files changed, 242 insertions, 86 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 1916f9b4dab..7d9063c3285 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2176,7 +2176,14 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve calculateCenter(t); if (event) { - initMouseInput(t, &t->mouse, t->center2d, event->mval, event->shift); + /* Initialize accurate transform to settings requested by keymap. */ + bool use_accurate = false; + if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) && RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + use_accurate = true; + } + } + initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate); } switch (mode) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 091a5773cf0..5e67f304755 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1973,9 +1973,12 @@ void flushTransParticles(TransInfo *t) /* ********************* mesh ****************** */ -static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, - float *dists, const float *dists_prev, - float mtx[3][3]) +static bool bmesh_test_dist_add( + BMVert *v, BMVert *v_other, + float *dists, const float *dists_prev, + /* optionally track original index */ + int *index, const int *index_prev, + float mtx[3][3]) { if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) @@ -1990,6 +1993,9 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, dist_other = dists_prev[i] + len_v3(vec); if (dist_other < dists[i_other]) { dists[i_other] = dist_other; + if (index != NULL) { + index[i_other] = index_prev[i]; + } return true; } } @@ -1997,11 +2003,13 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, return false; } -static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists) +/** + * \parm mtx: Measure disatnce in this space. + * \parm dists: Store the closest connected distance to selected vertices. + * \parm index: Optionally store the original index we're measuring the distance to (can be NULL). + */ +static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index) { - /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ - float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__); - BLI_LINKSTACK_DECLARE(queue, BMVert *); /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ @@ -2022,17 +2030,27 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { dist = FLT_MAX; + if (index != NULL) { + index[i] = i; + } } else { BLI_LINKSTACK_PUSH(queue, v); dist = 0.0f; + if (index != NULL) { + index[i] = i; + } } - dists[i] = dists_prev[i] = dist; + dists[i] = dist; } bm->elem_index_dirty &= ~BM_VERT; } + /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ + float *dists_prev = MEM_dupallocN(dists); + int *index_prev = MEM_dupallocN(index); /* may be NULL */ + do { BMVert *v; LinkNode *lnk; @@ -2061,7 +2079,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float /* edge distance */ { BMVert *v_other = BM_edge_other_vert(e_iter, v); - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); @@ -2086,7 +2104,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) { BMVert *v_other = l_iter_radial->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); @@ -2110,6 +2128,9 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float /* keep in sync, avoid having to do full memcpy each iteration */ dists_prev[i] = dists[i]; + if (index != NULL) { + index_prev[i] = index[i]; + } } BLI_LINKSTACK_SWAP(queue, queue_next); @@ -2123,9 +2144,14 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float BLI_LINKSTACK_FREE(queue_next); MEM_freeN(dists_prev); + if (index_prev != NULL) { + MEM_freeN(index_prev); + } } -static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map) +static struct TransIslandData *editmesh_islands_info_calc( + BMEditMesh *em, int *r_island_tot, int **r_island_vert_map, + bool calc_single_islands) { BMesh *bm = em->bm; struct TransIslandData *trans_islands; @@ -2237,6 +2263,42 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r MEM_freeN(groups_array); MEM_freeN(group_index); + /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */ + if (calc_single_islands) { + BMIter viter; + BMVert *v; + int group_tot_single = 0; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + group_tot_single += 1; + } + } + + if (group_tot_single != 0) { + trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single); + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + struct TransIslandData *v_island = &trans_islands[group_tot]; + vert_map[i] = group_tot; + + copy_v3_v3(v_island->co, v->co); + + if (is_zero_v3(v->no) != 0.0f) { + axis_dominant_v3_to_m3(v_island->axismtx, v->no); + invert_m3(v_island->axismtx); + } + else { + unit_m3(v_island->axismtx); + } + + group_tot += 1; + } + } + } + } + *r_island_tot = group_tot; *r_island_vert_map = vert_map; @@ -2336,6 +2398,11 @@ static void createTransEditVerts(TransInfo *t) int island_info_tot; int *island_vert_map = NULL; + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION); + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology); mirror = 1; @@ -2367,8 +2434,12 @@ static void createTransEditVerts(TransInfo *t) t->total = count; /* allocating scratch arrays */ - if (prop_mode & T_PROP_CONNECTED) - dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); + if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__); + } + } } else { t->total = bm->totvertsel; @@ -2390,7 +2461,7 @@ static void createTransEditVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); if (prop_mode & T_PROP_CONNECTED) { - editmesh_set_connectivity_distance(em->bm, mtx, dists); + editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index); } /* Only in case of rotation and resize, we want the elements of the edited @@ -2398,8 +2469,14 @@ static void createTransEditVerts(TransInfo *t) * * TODO: use island_info to detect the closest point when the "Snap Target" * in Blender UI is "Closest" */ - if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) { - island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); + if (is_island_center) { + /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */ + const bool calc_single_islands = ( + (prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands); } /* detect CrazySpace [tm] */ @@ -2449,10 +2526,16 @@ static void createTransEditVerts(TransInfo *t) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ? - &island_info[island_vert_map[a]] : NULL; + struct TransIslandData *v_island = NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; + if (island_info) { + const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; + v_island = (island_vert_map[connected_index] != -1) ? + &island_info[island_vert_map[connected_index]] : NULL; + } + + VertsToTransData(t, tob, tx, em, eve, bweight, v_island); if (tx) tx++; @@ -2531,6 +2614,8 @@ cleanup: MEM_freeN(defmats); if (dists) MEM_freeN(dists); + if (dists_index) + MEM_freeN(dists_index); if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_end(em); @@ -8038,7 +8123,12 @@ void createTransData(bContext *C, TransInfo *t) if (t->data && t->flag & T_PROP_EDIT) { if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) { sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, 0); + if ((t->obedit->type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) { + /* already calculated by editmesh_set_connectivity_distance */ + } + else { + set_prop_dist(t, 0); + } sort_trans_data_dist(t); } else { diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index e141724f2df..0a984d90ae3 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -1724,14 +1724,14 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; - rctf rect, selrect; + rcti rect; GLuint buffer[64]; // max 4 items per select, so large enuf short hits; const bool is_picksel = true; const bool do_passes = GPU_select_query_check_active(); /* XXX check a bit later on this... (ton) */ - extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect); + extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rcti *rect); /* when looking through a selected camera, the manipulator can be at the * exact same position as the view, skip so we don't break selection */ @@ -1743,15 +1743,13 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl rect.ymin = mval[1] - hotspot; rect.ymax = mval[1] + hotspot; - selrect = rect; - view3d_winmatrix_set(ar, v3d, &rect); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); if (do_passes) - GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0); + GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); else - GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0); + GPU_select_begin(buffer, 64, &rect, GPU_SELECT_ALL, 0); /* do the drawing */ if (v3d->twtype & V3D_MANIP_ROTATE) { @@ -1766,7 +1764,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl hits = GPU_select_end(); if (do_passes) { - GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits); + GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); /* do the drawing */ if (v3d->twtype & V3D_MANIP_ROTATE) { @@ -1826,6 +1824,23 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl return 0; } +static const char *manipulator_get_operator_name(int man_val) +{ + if (man_val & MAN_TRANS_C) { + return "TRANSFORM_OT_translate"; + } + else if (man_val == MAN_ROT_T) { + return "TRANSFORM_OT_trackball"; + } + else if (man_val & MAN_ROT_C) { + return "TRANSFORM_OT_rotate"; + } + else if (man_val & MAN_SCALE_C) { + return "TRANSFORM_OT_resize"; + } + + return NULL; +} /* return 0; nothing happened */ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) @@ -1846,11 +1861,24 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) // find the hotspots first test narrow hotspot val = manipulator_selectbuf(sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); if (val) { + wmOperatorType *ot; + PointerRNA props_ptr; + PropertyRNA *prop; + const char *opname; // drawflags still global, for drawing call above drawflags = manipulator_selectbuf(sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); if (drawflags == 0) drawflags = val; + /* Planar constraint doesn't make sense for rotation, give other keymaps a chance */ + if ((drawflags & MAN_ROT_C) && use_planar) { + return 0; + } + + opname = manipulator_get_operator_name(drawflags); + ot = WM_operatortype_find(opname, true); + WM_operator_properties_create_ptr(&props_ptr, ot); + if (drawflags & MAN_TRANS_C) { switch (drawflags) { case MAN_TRANS_C: @@ -1880,8 +1908,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) constraint_axis[2] = 1; break; } - RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis); - WM_operator_name_call(C, "TRANSFORM_OT_translate", WM_OP_INVOKE_DEFAULT, op->ptr); + RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); } else if (drawflags & MAN_SCALE_C) { switch (drawflags) { @@ -1910,22 +1937,10 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) constraint_axis[2] = 1; break; } - RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis); - WM_operator_name_call(C, "TRANSFORM_OT_resize", WM_OP_INVOKE_DEFAULT, op->ptr); + RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); } - else if (drawflags == MAN_ROT_T) { /* trackball need special case, init is different */ - /* Do not pass op->ptr!!! trackball has no "constraint" properties! - * See [#34621], it's a miracle it did not cause more problems!!! */ - /* However, we need to copy the "release_confirm" property, but only if defined, see T41112. */ - PointerRNA props_ptr; - PropertyRNA *prop; - wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_trackball", true); - WM_operator_properties_create_ptr(&props_ptr, ot); - if ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); - } - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); + else if (drawflags == MAN_ROT_T) { + /* pass */ } else if (drawflags & MAN_ROT_C) { switch (drawflags) { @@ -1939,9 +1954,25 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) constraint_axis[2] = 1; break; } - RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis); - WM_operator_name_call(C, "TRANSFORM_OT_rotate", WM_OP_INVOKE_DEFAULT, op->ptr); + RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); + } + + /* pass operator properties on to transform operators */ + prop = RNA_struct_find_property(op->ptr, "use_accurate"); + if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); + } + prop = RNA_struct_find_property(op->ptr, "release_confirm"); + if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); } + prop = RNA_struct_find_property(op->ptr, "constraint_orientation"); + if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_enum_set(&props_ptr, prop, RNA_property_enum_get(op->ptr, prop)); + } + + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); } /* after transform, restore drawflags */ drawflags = 0xFFFF; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index cbe58ddf586..2a97384cf7d 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -569,6 +569,9 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) // Add confirm method all the time. At the end because it's not really that important and should be hidden only in log, not in keymap edit /*prop =*/ RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button"); //RNA_def_property_flag(prop, PROP_HIDDEN); + + prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation"); + RNA_def_property_flag(prop, PROP_HIDDEN); } } diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 7c9dc43dbe4..b33528b4149 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -87,6 +87,8 @@ typedef struct SnapObjectData { typedef struct SnapObjectData_Mesh { SnapObjectData sd; BVHTreeFromMesh *bvh_trees[3]; + MPoly *mpoly; + bool poly_allocated; } SnapObjectData_Mesh; @@ -934,9 +936,10 @@ static bool snapEmpty( float tmp_co[3]; copy_v3_v3(tmp_co, obmat[3]); if (test_projected_vert_dist( - snapdata->depth_range, snapdata->mval, tmp_co, - snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, - r_loc)) { + snapdata->depth_range, snapdata->mval, tmp_co, + snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc)) + { *dist_px = sqrtf(dist_px_sq); *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); retval = true; @@ -1051,7 +1054,6 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) static bool snapDerivedMesh( SnapObjectContext *sctx, SnapData *snapdata, Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, - bool do_bb, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1112,39 +1114,30 @@ static bool snapDerivedMesh( copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); - if (do_bb) { - BoundBox *bb = BKE_object_boundbox_get(ob); - - if (bb) { - BoundBox bb_temp; - - /* We cannot afford a bounding box with some null dimension, which may happen in some cases... - * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ - bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); - - /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ - if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - float dist_px_sq = dist_squared_to_projected_aabb_simple( - lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, - ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); - if (dist_px_sq > SQUARE(*dist_px)) - { - return retval; - } + /* Test BoundBox */ + BoundBox *bb = BKE_object_boundbox_get(ob); + if (bb) { + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + float dist_px_sq = dist_squared_to_projected_aabb_simple( + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) { + return retval; } - else { - /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ - if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) - { - return retval; - } + } + else { + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) + { + return retval; } - /* was local_depth, see: T47838 */ - len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); - if (len_diff < 0) len_diff = 0.0f; - need_ray_start_correction_init = false; } + /* was local_depth, see: T47838 */ + len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); + if (len_diff < 0) len_diff = 0.0f; + need_ray_start_correction_init = false; } SnapObjectData_Mesh *sod = NULL; @@ -1182,6 +1175,29 @@ static bool snapDerivedMesh( if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { free_bvhtree_from_mesh(treedata); } + else { + if (!treedata->vert_allocated) { + treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated); + } + if ((tree_index == 1) && !treedata->edge_allocated) { + treedata->edge = DM_get_edge_array(dm, &treedata->vert_allocated); + } + if (tree_index == 2) { + if (!treedata->loop_allocated) { + treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated); + } + if (!treedata->looptri_allocated) { + if (!sod->poly_allocated) { + sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated); + } + treedata->looptri = DM_get_looptri_array( + dm, treedata->vert, + sod->mpoly, dm->getNumPolys(dm), + treedata->loop, dm->getNumLoops(dm), + &treedata->looptri_allocated); + } + } + } } } @@ -1295,10 +1311,17 @@ static bool snapDerivedMesh( } /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ else { + + /* Warning: the depth_max is currently being used only in perspective view. + * It is not correct to limit the maximum depth for elements obtained with nearest + * since this limitation depends on the normal and the size of the occlusion face. + * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */ + const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0]; + Nearest2dUserData neasrest2d = { .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .depth_range = {snapdata->depth_range[0], ray_depth_max_global}, .userdata = treedata, .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, @@ -1650,7 +1673,6 @@ static bool snapObject( } retval = snapDerivedMesh( sctx, snapdata, ob, dm, obmat, ob_index, - true, ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); @@ -1858,6 +1880,9 @@ static void snap_object_data_free(void *sod_v) free_bvhtree_from_mesh(sod->bvh_trees[i]); } } + if (sod->poly_allocated) { + MEM_freeN(sod->mpoly); + } break; } case SNAP_EDIT_MESH: @@ -2053,10 +2078,10 @@ static bool transform_snap_context_project_view3d_mixed_impl( for (int i = 0; i < 3; i++) { if (snap_to_flag & (1 << i)) { if (ED_transform_snap_object_project_view3d( - sctx, - elem_type[i], params, - mval, dist_px, &ray_depth, - r_co, r_no)) + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) { is_hit = true; break; |