Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2016-05-11 12:59:02 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-05-11 13:20:25 +0300
commit67d2de882841f56c9cd35f0f0e7329b0c9190c97 (patch)
tree49778334fe1d4e71e19a62a5876a8d10e4a6e2ff /source/blender/editors/transform
parent4a135ad2b7886c3a4731f7db7ddce60af8068f32 (diff)
Transform Volume rewrite/refactor
Take advantage of the efficiency provided by the snap_context. Also fixes errors: - volume snap fails based on view angle (T48394). - multiple instances of dupli-objects break volume calculation.
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/transform_snap.c474
-rw-r--r--source/blender/editors/transform/transform_snap_object.c423
2 files changed, 404 insertions, 493 deletions
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index bcbe1f582b7..38f1d37acd6 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -963,86 +963,10 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
mval[1] = t->mval[1];
if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) {
- ListBase depth_peels;
- DepthPeel *p1, *p2;
- const float *last_p = NULL;
- float max_dist = FLT_MAX;
- float p[3] = {0.0f, 0.0f, 0.0f};
-
- BLI_listbase_clear(&depth_peels);
-
- peelObjectsTransForm(t, mval, t->tsnap.modeSelect, &depth_peels);
-
-// if (LAST_SNAP_POINT_VALID)
-// {
-// last_p = LAST_SNAP_POINT;
-// }
-// else
- {
- last_p = t->tsnap.snapPoint;
- }
-
-
- for (p1 = depth_peels.first; p1; p1 = p1->next) {
- if (p1->flag == 0) {
- float vec[3];
- float new_dist;
-
- p2 = NULL;
- p1->flag = 1;
-
- /* if peeling objects, take the first and last from each object */
- if (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) {
- DepthPeel *peel;
- for (peel = p1->next; peel; peel = peel->next) {
- if (peel->ob == p1->ob) {
- peel->flag = 1;
- p2 = peel;
- }
- }
- }
- /* otherwise, pair first with second and so on */
- else {
- for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) {
- /* nothing to do here */
- }
- }
-
- if (p2) {
- p2->flag = 1;
-
- add_v3_v3v3(vec, p1->p, p2->p);
- mul_v3_fl(vec, 0.5f);
- }
- else {
- copy_v3_v3(vec, p1->p);
- }
-
- if (last_p == NULL) {
- copy_v3_v3(p, vec);
- max_dist = 0;
- break;
- }
-
- new_dist = len_squared_v3v3(last_p, vec);
-
- if (new_dist < max_dist) {
- copy_v3_v3(p, vec);
- max_dist = new_dist;
- }
- }
- }
-
- if (max_dist != FLT_MAX) {
- copy_v3_v3(loc, p);
- /* XXX, is there a correct normal in this case ???, for now just z up */
- no[0] = 0.0;
- no[1] = 0.0;
- no[2] = 1.0;
- found = true;
- }
-
- BLI_freelistN(&depth_peels);
+ found = peelObjectsTransform(
+ t, mval, t->tsnap.modeSelect,
+ (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
+ loc, no, NULL);
}
else {
zero_v3(no); /* objects won't set this */
@@ -1302,347 +1226,87 @@ bool snapObjectsTransform(
/******************** PEELING *********************************/
-
-static int cmpPeel(const void *arg1, const void *arg2)
-{
- const DepthPeel *p1 = arg1;
- const DepthPeel *p2 = arg2;
- int val = 0;
-
- if (p1->depth < p2->depth) {
- val = -1;
- }
- else if (p1->depth > p2->depth) {
- val = 1;
- }
-
- return val;
-}
-
-static void removeDoublesPeel(ListBase *depth_peels)
+bool peelObjectsSnapContext(
+ SnapObjectContext *sctx,
+ const float mval[2], SnapSelect snap_select, bool use_peel_object,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_thickness)
{
- DepthPeel *peel;
-
- for (peel = depth_peels->first; peel; peel = peel->next) {
- DepthPeel *next_peel = peel->next;
-
- if (next_peel && fabsf(peel->depth - next_peel->depth) < 0.0015f) {
- peel->next = next_peel->next;
-
- if (next_peel->next) {
- next_peel->next->prev = peel;
+ ListBase depths_peel = {0};
+ ED_transform_snap_object_project_all_view3d_ex(
+ sctx,
+ &(const struct SnapObjectParams){
+ .snap_to = SCE_SNAP_MODE_FACE,
+ .snap_select = snap_select,
+ .use_object_edit = true,
+ },
+ mval, -1.0f, false,
+ &depths_peel);
+
+ if (!BLI_listbase_is_empty(&depths_peel)) {
+ /* At the moment we only use the hits of the first object */
+ struct SnapObjectHitDepth *hit_min = depths_peel.first;
+ for (struct SnapObjectHitDepth *iter = hit_min->next; iter; iter = iter->next) {
+ if (iter->depth < hit_min->depth) {
+ hit_min = iter;
}
-
- MEM_freeN(next_peel);
}
- }
-}
-
-static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob)
-{
- DepthPeel *peel = MEM_callocN(sizeof(DepthPeel), "DepthPeel");
-
- peel->depth = depth;
- peel->ob = ob;
- copy_v3_v3(peel->p, p);
- copy_v3_v3(peel->no, no);
-
- BLI_addtail(depth_peels, peel);
-
- peel->flag = 0;
-}
-
-struct PeelRayCast_Data {
- BVHTreeFromMesh bvhdata;
-
- /* internal vars for adding peel */
- Object *ob;
- const float (*obmat)[4];
- const float (*timat)[3];
-
- const float *ray_start; /* globalspace */
-
- const MLoopTri *looptri;
- const float (*polynors)[3]; /* optional, can be NULL */
-
- /* output list */
- ListBase *depth_peels;
-};
-
-struct PeelEditMeshRayCast_Data {
- BVHTreeFromEditMesh bvhdata;
-
- /* internal vars for adding peel */
- Object *ob;
- const float(*obmat)[4];
- const float(*timat)[3];
-
- const float *ray_start; /* globalspace */
-
- /* output list */
- ListBase *depth_peels;
-};
-
-static void peelRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
-{
- struct PeelRayCast_Data *data = userdata;
-
- data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
-
- if (hit->index != -1) {
- /* get all values in worldspace */
- float location[3], normal[3];
- float depth;
-
- /* worldspace location */
- mul_v3_m4v3(location, (float (*)[4])data->obmat, hit->co);
- depth = len_v3v3(location, data->ray_start);
-
- /* worldspace normal */
- copy_v3_v3(normal, data->polynors ? data->polynors[data->looptri[hit->index].poly] : hit->no);
- mul_m3_v3((float (*)[3])data->timat, normal);
- normalize_v3(normal);
-
- addDepthPeel(data->depth_peels, depth, location, normal, data->ob);
- }
-}
-
-static void peelEditMeshRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
-{
- struct PeelEditMeshRayCast_Data *data = userdata;
-
- data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
-
- if (hit->index != -1) {
- /* get all values in worldspace */
- float location[3], normal[3];
- float depth;
-
- /* worldspace location */
- mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
- depth = len_v3v3(location, data->ray_start);
-
- /* worldspace normal */
- copy_v3_v3(normal, hit->no);
- mul_m3_v3((float(*)[3])data->timat, normal);
- normalize_v3(normal);
-
- addDepthPeel(data->depth_peels, depth, location, normal, data->ob);
- }
-}
-
-static bool peelDerivedMesh(
- Object *ob, DerivedMesh *dm, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]),
- ListBase *depth_peels)
-{
- bool retval = false;
- int totvert = dm->getNumVerts(dm);
-
- if (totvert > 0) {
- const MLoopTri *looptri = dm->getLoopTriArray(dm);
- const int looptri_num = dm->getNumLoopTri(dm);
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_start_local[3], ray_normal_local[3];
- bool test = true;
-
- invert_m4_m4(imat, obmat);
-
- transpose_m3_m4(timat, imat);
-
- mul_v3_m4v3(ray_start_local, imat, ray_start);
- mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
-
- /* If number of vert is more than an arbitrary limit,
- * test against boundbox first
- * */
- if (looptri_num > 16) {
- BoundBox *bb = BKE_object_boundbox_get(ob);
-
- if (bb) {
- BoundBox bb_temp;
-
- /* We cannot aford a bbox 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);
-
- test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
+ struct SnapObjectHitDepth *hit_max = NULL;
+
+ if (use_peel_object) {
+ /* if peeling objects, take the first and last from each object */
+ hit_max = hit_min;
+ for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
+ if ((iter->depth > hit_max->depth) && (iter->ob_uuid == hit_min->ob_uuid)) {
+ hit_max = iter;
+ }
}
}
-
- if (test == true) {
- struct PeelRayCast_Data data;
-
- bvhtree_from_mesh_looptri(&data.bvhdata, dm, 0.0f, 4, 6);
-
- if (data.bvhdata.tree != NULL) {
- data.ob = ob;
- data.obmat = (const float (*)[4])obmat;
- data.timat = (const float (*)[3])timat;
- data.ray_start = ray_start;
- data.looptri = looptri;
- data.polynors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
- data.depth_peels = depth_peels;
-
- BLI_bvhtree_ray_cast_all(
- data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f, BVH_RAYCAST_DIST_MAX,
- peelRayCast_cb, &data);
+ else {
+ /* otherwise, pair first with second and so on */
+ for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
+ if ((iter != hit_min) && (iter->ob_uuid == hit_min->ob_uuid)) {
+ if (hit_max == NULL) {
+ hit_max = iter;
+ }
+ else if (iter->depth < hit_max->depth) {
+ hit_max = iter;
+ }
+ }
}
-
- free_bvhtree_from_mesh(&data.bvhdata);
- }
- }
-
- return retval;
-}
-
-static bool peelEditMesh(
- Object *ob, BMEditMesh *em, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3],
- ListBase *depth_peels)
-{
- bool retval = false;
- int totvert = em->bm->totvert;
-
- if (totvert > 0) {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_start_local[3], ray_normal_local[3];
- bool test = true;
-
- invert_m4_m4(imat, obmat);
-
- transpose_m3_m4(timat, imat);
-
- mul_v3_m4v3(ray_start_local, imat, ray_start);
- mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
-
- if (test == true) {
- struct PeelEditMeshRayCast_Data data;
-
- BLI_bitmap *looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
- int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- em->bm, looptri_mask,
- BM_elem_cb_check_hflag_enabled_simple(BMFace *, (BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
-
- bvhtree_from_editmesh_looptri_ex(&data.bvhdata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6);
-
- MEM_freeN(looptri_mask);
-
- if (data.bvhdata.tree != NULL) {
- data.ob = ob;
- data.obmat = (const float(*)[4])obmat;
- data.timat = (const float(*)[3])timat;
- data.ray_start = ray_start;
- data.depth_peels = depth_peels;
-
- BLI_bvhtree_ray_cast_all(
- data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f, BVH_RAYCAST_DIST_MAX,
- peelEditMeshRayCast_cb, &data);
+ /* in this case has only one hit. treat as raycast */
+ if (hit_max == NULL) {
+ hit_max = hit_min;
}
-
- free_bvhtree_from_editmesh(&data.bvhdata);
}
- }
-
- return retval;
-}
-
-static bool peelObjects(
- Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
- const float mval[2], SnapSelect snap_select,
- ListBase *r_depth_peels)
-{
- Base *base;
- bool retval = false;
- float ray_start[3], ray_normal[3];
-
- if (ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal, true) == false) {
- return false;
- }
-
- for (base = scene->base.first; base != NULL; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- Object *ob = base->object;
-
- if (ob->transflag & OB_DUPLI) {
- DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
-
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- Object *dob = dupli_ob->ob;
-
- if (dob->type == OB_MESH) {
- BMEditMesh *em;
- bool val;
- if (dob != obedit) {
- DerivedMesh *dm;
- dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH);
- val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
+ mid_v3_v3v3(r_loc, hit_min->co, hit_max->co);
- dm->release(dm);
- }
- else {
- em = BKE_editmesh_from_object(dob);
- val = peelEditMesh(dob, em, dob->obmat, ray_start, ray_normal, r_depth_peels);
- }
+ if (r_thickness) {
+ *r_thickness = hit_max->depth - hit_min->depth;
+ }
- retval = retval || val;
- }
- }
-
- free_object_duplilist(lb);
- }
-
- if (ob->type == OB_MESH) {
- bool val = false;
+ /* XXX, is there a correct normal in this case ???, for now just z up */
+ r_no[0] = 0.0;
+ r_no[1] = 0.0;
+ r_no[2] = 1.0;
- if (ob != obedit && ((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT))) {
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
-
- val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
- dm->release(dm);
- }
- else if (ob == obedit && snap_select != SNAP_NOT_OBEDIT) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- DerivedMesh *dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
-
- val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
- dm->release(dm);
- }
-
- retval = retval || val;
-
- }
- }
+ BLI_freelistN(&depths_peel);
+ return true;
}
-
- BLI_listbase_sort(r_depth_peels, cmpPeel);
- removeDoublesPeel(r_depth_peels);
-
- return retval;
-}
-
-bool peelObjectsTransForm(
- TransInfo *t, const float mval[2], SnapSelect snap_select,
- ListBase *r_depth_peels)
-{
- return peelObjects(t->scene, t->view, t->ar, t->obedit, mval, snap_select, r_depth_peels);
+ return false;
}
-bool peelObjectsContext(
- bContext *C, const float mval[2], SnapSelect snap_select,
- ListBase *r_depth_peels)
+bool peelObjectsTransform(
+ TransInfo *t,
+ const float mval[2], SnapSelect snap_select, bool use_peel_object,
+ /* return args */
+ float r_loc[3], float r_no[3], float *r_thickness)
{
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- ARegion *ar = CTX_wm_region(C);
- Object *obedit = CTX_data_edit_object(C);
-
- return peelObjects(scene, v3d, ar, obedit, mval, snap_select, r_depth_peels);
+ return peelObjectsSnapContext(
+ t->tsnap.object_context,
+ mval, snap_select, use_peel_object,
+ r_loc, r_no, r_thickness);
}
/******************** NODES ***********************************/
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 57352f38789..17c77df58f2 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -34,6 +34,7 @@
#include "BLI_memarena.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_armature_types.h"
@@ -109,6 +110,111 @@ struct SnapObjectContext {
};
+static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Support for storing all depths, not just the first (raycast 'all')
+ *
+ * This uses a list of #SnapObjectHitDepth structs.
+ *
+ * \{ */
+
+/* Store all ray-hits */
+struct RayCastAll_Data {
+ void *bvhdata;
+
+ /* internal vars for adding depths */
+ BVHTree_RayCastCallback raycast_callback;
+
+ const float(*obmat)[4];
+ const float(*timat)[3];
+
+ float len_diff;
+ float local_scale;
+
+ Object *ob;
+ unsigned int ob_uuid;
+
+ /* DerivedMesh only */
+ DerivedMesh *dm;
+ const struct MLoopTri *dm_looptri;
+
+ /* output data */
+ ListBase *hit_list;
+ bool retval;
+};
+
+static struct SnapObjectHitDepth *hit_depth_create(
+ const float depth, const float co[3], const float no[3], int index,
+ Object *ob, const float obmat[4][4], unsigned int ob_uuid)
+{
+ struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
+
+ hit->depth = depth;
+ copy_v3_v3(hit->co, co);
+ copy_v3_v3(hit->no, no);
+ hit->index = index;
+
+ hit->ob = ob;
+ copy_m4_m4(hit->obmat, (float(*)[4])obmat);
+ hit->ob_uuid = ob_uuid;
+
+ return hit;
+}
+
+static int hit_depth_cmp(const void *arg1, const void *arg2)
+{
+ const struct SnapObjectHitDepth *h1 = arg1;
+ const struct SnapObjectHitDepth *h2 = arg2;
+ int val = 0;
+
+ if (h1->depth < h2->depth) {
+ val = -1;
+ }
+ else if (h1->depth > h2->depth) {
+ val = 1;
+ }
+
+ return val;
+}
+
+static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ struct RayCastAll_Data *data = userdata;
+ data->raycast_callback(data->bvhdata, index, ray, hit);
+ if (hit->index != -1) {
+ /* get all values in worldspace */
+ float location[3], normal[3];
+ float depth;
+
+ /* worldspace location */
+ mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
+ depth = (hit->dist + data->len_diff) / data->local_scale;
+
+ /* worldspace normal */
+ copy_v3_v3(normal, hit->no);
+ mul_m3_v3((float(*)[3])data->timat, normal);
+ normalize_v3(normal);
+
+ /* currently unused, and causes issues when looptri's havn't been calculated.
+ * since theres some overhead in ensuring this data is valid, it may need to be optional. */
+#if 0
+ if (data->dm) {
+ hit->index = dm_looptri_to_poly_index(data->dm, &data->dm_looptri[hit->index]);
+ }
+#endif
+
+ struct SnapObjectHitDepth *hit_item = hit_depth_create(
+ depth, location, normal, hit->index,
+ data->ob, data->obmat, data->ob_uuid);
+ BLI_addtail(data->hit_list, hit_item);
+ }
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
@@ -572,8 +678,10 @@ static bool snapDerivedMesh(
SnapObjectContext *sctx,
Object *ob, DerivedMesh *dm, float obmat[4][4],
const float mval[2], float *dist_px, const short snap_to, bool do_bb,
- const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
- float r_loc[3], float r_no[3], int *r_index)
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
+ float *ray_depth, unsigned int ob_index,
+ float r_loc[3], float r_no[3], int *r_index,
+ ListBase *r_hit_list)
{
ARegion *ar = sctx->v3d_data.ar;
bool retval = false;
@@ -729,31 +837,55 @@ static bool snapDerivedMesh(
switch (snap_to) {
case SCE_SNAP_MODE_FACE:
{
- BVHTreeRayHit hit;
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index,
+ data.dm = dm;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit;
- hit.index = -1;
- hit.dist = local_depth;
+ hit.index = -1;
+ hit.dist = local_depth;
- if (treedata->tree &&
- BLI_bvhtree_ray_cast(treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
- copy_v3_v3(r_no, hit.no);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
-
- retval = true;
-
- if (r_index) {
- *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
+ if (treedata->tree &&
+ BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+ copy_v3_v3(r_no, hit.no);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
+ }
}
}
}
@@ -814,8 +946,10 @@ static bool snapEditMesh(
SnapObjectContext *sctx,
Object *ob, BMEditMesh *em, float obmat[4][4],
const float mval[2], float *dist_px, const short snap_to,
- const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
- float r_loc[3], float r_no[3], int *r_index)
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
+ float *ray_depth, const unsigned int ob_index,
+ float r_loc[3], float r_no[3], int *r_index,
+ ListBase *r_hit_list)
{
ARegion *ar = sctx->v3d_data.ar;
bool retval = false;
@@ -951,7 +1085,7 @@ static bool snapEditMesh(
*/
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
- len_diff - len_v3v3(ray_start_local, ray_org_local));
+ len_diff - len_v3v3(ray_start_local, ray_org_local));
local_depth -= len_diff;
}
else {
@@ -961,32 +1095,55 @@ static bool snapEditMesh(
switch (snap_to) {
case SCE_SNAP_MODE_FACE:
{
- BVHTreeRayHit hit;
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.dm = NULL;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit;
- hit.index = -1;
- hit.dist = local_depth;
+ hit.index = -1;
+ hit.dist = local_depth;
- if (treedata->tree &&
- BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
- copy_v3_v3(r_no, hit.no);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
-
- retval = true;
-
- if (r_index) {
- *r_index = hit.index;
+ if (treedata->tree &&
+ BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+ copy_v3_v3(r_no, hit.no);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = hit.index;
+ }
}
}
}
@@ -1050,11 +1207,13 @@ static bool snapEditMesh(
static bool snapObject(
SnapObjectContext *sctx,
Object *ob, float obmat[4][4], bool use_obedit, const short snap_to,
- const float mval[2], float *dist_px,
- const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
+ const float mval[2], float *dist_px, const unsigned int ob_index,
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
+ float *ray_depth,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+ Object **r_ob, float r_obmat[4][4],
+ ListBase *r_hit_list)
{
ARegion *ar = sctx->v3d_data.ar;
bool retval = false;
@@ -1066,8 +1225,10 @@ static bool snapObject(
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
sctx, ob, em, obmat, mval, dist_px, snap_to,
- ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index);
+ ray_start, ray_normal, ray_origin,
+ ray_depth, ob_index,
+ r_loc, r_no, r_index,
+ r_hit_list);
}
else {
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
@@ -1082,8 +1243,9 @@ static bool snapObject(
}
retval = snapDerivedMesh(
sctx, ob, dm, obmat, mval, dist_px, snap_to, true,
- ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index);
+ ray_start, ray_normal, ray_origin,
+ ray_depth, ob_index,
+ r_loc, r_no, r_index, r_hit_list);
dm->release(dm);
}
@@ -1132,19 +1294,22 @@ static bool snapObjectsRay(
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+ Object **r_ob, float r_obmat[4][4],
+ ListBase *r_hit_list)
{
Base *base;
bool retval = false;
+ bool snap_obedit_first = snap_select == SNAP_ALL && obedit;
+ unsigned int ob_index = 0;
- if (snap_select == SNAP_ALL && obedit) {
+ if (snap_obedit_first) {
Object *ob = obedit;
retval |= snapObject(
sctx, ob, ob->obmat, true, snap_to,
- mval, dist_px,
+ mval, dist_px, ob_index++,
ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index, r_ob, r_obmat);
+ r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
/* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
@@ -1157,9 +1322,9 @@ static bool snapObjectsRay(
Object *ob = base->object;
retval |= snapObject(
sctx, ob, ob->obmat, false, snap_to,
- mval, dist_px,
+ mval, dist_px, ob_index++,
ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index, r_ob, r_obmat);
+ r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
for (base = sctx->scene->base.first; base != NULL; base = base->next) {
@@ -1173,12 +1338,6 @@ static bool snapObjectsRay(
Object *ob_snap = ob;
bool use_obedit = false;
- /* for linked objects, use the same object but a different matrix */
- if (obedit && ob->data == obedit->data) {
- use_obedit = true;
- ob_snap = obedit;
- }
-
if (ob->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
@@ -1189,19 +1348,33 @@ static bool snapObjectsRay(
retval |= snapObject(
sctx, dupli_snap, dupli_ob->mat, use_obedit_dupli, snap_to,
- mval, dist_px,
+ mval, dist_px, ob_index++,
ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index, r_ob, r_obmat);
+ r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
free_object_duplilist(lb);
}
+ if (obedit) {
+ if ((ob == obedit) &&
+ (snap_obedit_first || (snap_select == SNAP_NOT_OBEDIT)))
+ {
+ continue;
+ }
+
+ if (ob->data == obedit->data) {
+ /* for linked objects, use the same object but a different matrix */
+ use_obedit = true;
+ ob_snap = obedit;
+ }
+ }
+
retval |= snapObject(
sctx, ob_snap, ob->obmat, use_obedit, snap_to,
- mval, dist_px,
+ mval, dist_px, ob_index++,
ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index, r_ob, r_obmat);
+ r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
}
@@ -1315,7 +1488,53 @@ bool ED_transform_snap_object_project_ray_ex(
base_act, obedit,
ray_start, ray_normal, ray_start, ray_depth,
r_loc, r_no, r_index,
- r_ob, r_obmat);
+ r_ob, r_obmat, NULL);
+}
+
+/**
+ * Fill in a list of all hits.
+ *
+ * \param ray_depth: Only depths in this range are considered, -1.0 for maximum.
+ * \param sort: Optionally sort the hits by depth.
+ * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
+ */
+bool ED_transform_snap_object_project_ray_all(
+ SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3], const float ray_normal[3],
+ float ray_depth, bool sort,
+ ListBase *r_hit_list)
+{
+ Base *base_act = params->use_object_active ? sctx->scene->basact : NULL;
+ Object *obedit = params->use_object_edit ? sctx->scene->obedit : NULL;
+
+ if (ray_depth == -1.0f) {
+ ray_depth = BVH_RAYCAST_DIST_MAX;
+ }
+
+#ifdef DEBUG
+ float ray_depth_prev = ray_depth;
+#endif
+
+ bool retval = snapObjectsRay(
+ sctx,
+ params->snap_select, params->snap_to,
+ NULL, NULL,
+ base_act, obedit,
+ ray_start, ray_normal, ray_start, &ray_depth,
+ NULL, NULL, NULL, NULL, NULL,
+ r_hit_list);
+
+ /* meant to be readonly for 'all' hits, ensure it is */
+#ifdef DEBUG
+ BLI_assert(ray_depth_prev == ray_depth);
+#endif
+
+ if (sort) {
+ BLI_listbase_sort(r_hit_list, hit_depth_cmp);
+ }
+
+ return retval;
}
/**
@@ -1327,7 +1546,7 @@ bool ED_transform_snap_object_project_ray_ex(
*/
static bool transform_snap_context_project_ray_impl(
SnapObjectContext *sctx,
- const float ray_start[3], const float ray_normal[3], float *ray_dist,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
float r_co[3], float r_no[3])
{
bool ret;
@@ -1340,7 +1559,7 @@ static bool transform_snap_context_project_ray_impl(
.snap_to = SCE_SNAP_MODE_FACE,
.use_object_edit = (sctx->scene->obedit != NULL),
},
- ray_start, ray_normal, ray_dist,
+ ray_start, ray_normal, ray_depth,
r_co, r_no, NULL,
NULL, NULL);
@@ -1349,13 +1568,13 @@ static bool transform_snap_context_project_ray_impl(
bool ED_transform_snap_object_project_ray(
SnapObjectContext *sctx,
- const float ray_origin[3], const float ray_direction[3], float *ray_dist,
+ const float ray_origin[3], const float ray_direction[3], float *ray_depth,
float r_co[3], float r_no[3])
{
- float ray_dist_fallback;
- if (ray_dist == NULL) {
- ray_dist_fallback = BVH_RAYCAST_DIST_MAX;
- ray_dist = &ray_dist_fallback;
+ float ray_depth_fallback;
+ if (ray_depth == NULL) {
+ ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
+ ray_depth = &ray_depth_fallback;
}
float no_fallback[3];
@@ -1365,7 +1584,7 @@ bool ED_transform_snap_object_project_ray(
return transform_snap_context_project_ray_impl(
sctx,
- ray_origin, ray_direction, ray_dist,
+ ray_origin, ray_direction, ray_depth,
r_co, r_no);
}
@@ -1376,7 +1595,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
bool use_depth,
float r_co[3], float r_no[3])
{
- float ray_dist = BVH_RAYCAST_DIST_MAX;
+ float ray_depth = BVH_RAYCAST_DIST_MAX;
bool is_hit = false;
float r_no_dummy[3];
@@ -1394,7 +1613,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
for (int i = 0; i < 3; i++) {
if ((params->snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
if (use_depth == false) {
- ray_dist = BVH_RAYCAST_DIST_MAX;
+ ray_depth = BVH_RAYCAST_DIST_MAX;
}
params_temp.snap_to = elem_type[i];
@@ -1402,7 +1621,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
if (ED_transform_snap_object_project_view3d(
sctx,
&params_temp,
- mval, dist_px, &ray_dist,
+ mval, dist_px, &ray_depth,
r_co, r_no))
{
is_hit = true;
@@ -1470,7 +1689,7 @@ bool ED_transform_snap_object_project_view3d_ex(
mval, dist_px,
base_act, obedit,
ray_start, ray_normal, ray_orgigin, ray_depth,
- r_loc, r_no, r_index, NULL, NULL);
+ r_loc, r_no, r_index, NULL, NULL, NULL);
}
bool ED_transform_snap_object_project_view3d(
@@ -1488,4 +1707,32 @@ bool ED_transform_snap_object_project_view3d(
r_loc, r_no, NULL);
}
+/**
+ * see: #ED_transform_snap_object_project_ray_all
+ */
+bool ED_transform_snap_object_project_all_view3d_ex(
+ SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float ray_depth, bool sort,
+ ListBase *r_hit_list)
+{
+ float ray_start[3], ray_normal[3];
+
+ BLI_assert(params->snap_to == SCE_SNAP_MODE_FACE);
+
+ if (!ED_view3d_win_to_ray_ex(
+ sctx->v3d_data.ar, sctx->v3d_data.v3d,
+ mval, NULL, ray_normal, ray_start, true))
+ {
+ return false;
+ }
+
+ return ED_transform_snap_object_project_ray_all(
+ sctx,
+ params,
+ ray_start, ray_normal, ray_depth, sort,
+ r_hit_list);
+}
+
/** \} */