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:
authorCampbell Barton <ideasman42@gmail.com>2015-01-13 15:54:14 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-01-13 17:36:03 +0300
commita2a7260915633eda8a3d26aa678baba49b2429ce (patch)
tree41e042f052e8629a57d0b8d7a0153a420addb605 /source/blender/blenkernel/intern/editmesh_bvh.c
parentbd0077071521f212e8408638c6bf05b55a140eac (diff)
BMesh: option to filter out faces during raycast
This allows us to more easily cast from the surface of a mesh without normal offsets (Which can give precision issues).
Diffstat (limited to 'source/blender/blenkernel/intern/editmesh_bvh.c')
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c96
1 files changed, 79 insertions, 17 deletions
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 442ab26ffc8..5f2660b5365 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -239,6 +239,32 @@ struct RayCastUserData {
float uv[2];
};
+
+static BMFace *bmbvh_ray_cast_handle_hit(
+ BMBVHTree *bmtree, struct RayCastUserData *bmcb_data, const BVHTreeRayHit *hit,
+ float *r_dist, float r_hitout[3], float r_cagehit[3])
+{
+ if (r_hitout) {
+ if (bmtree->flag & BMBVH_RETURN_ORIG) {
+ BMLoop **ltri = bmtree->looptris[hit->index];
+ interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data->uv);
+ }
+ else {
+ copy_v3_v3(r_hitout, hit->co);
+ }
+
+ if (r_cagehit) {
+ copy_v3_v3(r_cagehit, hit->co);
+ }
+ }
+
+ if (r_dist) {
+ *r_dist = hit->dist;
+ }
+
+ return bmtree->looptris[hit->index][0]->f;
+}
+
static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
struct RayCastUserData *bmcb_data = userdata;
@@ -284,32 +310,68 @@ BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir
bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage;
BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb, &bmcb_data);
+
if (hit.index != -1 && hit.dist != dist) {
- if (r_hitout) {
- if (bmtree->flag & BMBVH_RETURN_ORIG) {
- BMLoop **ltri = bmtree->looptris[hit.index];
- interp_v3_v3v3v3_uv(r_hitout, ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co, bmcb_data.uv);
- }
- else {
- copy_v3_v3(r_hitout, hit.co);
- }
+ return bmbvh_ray_cast_handle_hit(bmtree, &bmcb_data, &hit, r_dist, r_hitout, r_cagehit);
+ }
- if (r_cagehit) {
- copy_v3_v3(r_cagehit, hit.co);
- }
- }
+ return NULL;
+}
- if (r_dist) {
- *r_dist = hit.dist;
- }
+/* -------------------------------------------------------------------- */
+/* bmbvh_ray_cast_cb_filter */
- return bmtree->looptris[hit.index][0]->f;
+/* Same as BKE_bmbvh_ray_cast but takes a callback to filter out faces.
+ */
+
+struct RayCastUserData_Filter {
+ struct RayCastUserData bmcb_data;
+
+ BMBVHTree_FaceFilter filter_cb;
+ void *filter_userdata;
+};
+
+static void bmbvh_ray_cast_cb_filter(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ struct RayCastUserData_Filter *bmcb_data_filter = userdata;
+ struct RayCastUserData *bmcb_data = &bmcb_data_filter->bmcb_data;
+ const BMLoop **ltri = bmcb_data->looptris[index];
+ if (bmcb_data_filter->filter_cb(ltri[0]->f, bmcb_data_filter->filter_userdata)) {
+ bmbvh_ray_cast_cb(bmcb_data, index, ray, hit);
+ }
+}
+
+BMFace *BKE_bmbvh_ray_cast_filter(
+ BMBVHTree *bmtree, const float co[3], const float dir[3], const float radius,
+ float *r_dist, float r_hitout[3], float r_cagehit[3],
+ BMBVHTree_FaceFilter filter_cb, void *filter_userdata)
+{
+ BVHTreeRayHit hit;
+ struct RayCastUserData_Filter bmcb_data_filter;
+ struct RayCastUserData *bmcb_data = &bmcb_data_filter.bmcb_data;
+
+ const float dist = r_dist ? *r_dist : FLT_MAX;
+
+ bmcb_data_filter.filter_cb = filter_cb;
+ bmcb_data_filter.filter_userdata = filter_userdata;
+
+ if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
+
+ hit.dist = dist;
+ hit.index = -1;
+
+ /* ok to leave 'uv' uninitialized */
+ bmcb_data->looptris = (const BMLoop *(*)[3])bmtree->looptris;
+ bmcb_data->cos_cage = (const float (*)[3])bmtree->cos_cage;
+
+ BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb_filter, &bmcb_data_filter);
+ if (hit.index != -1 && hit.dist != dist) {
+ return bmbvh_ray_cast_handle_hit(bmtree, bmcb_data, &hit, r_dist, r_hitout, r_cagehit);
}
return NULL;
}
-
/* -------------------------------------------------------------------- */
/* BKE_bmbvh_find_face_segment */