[Bf-blender-cvs] [a2a7260] master: BMesh: option to filter out faces during raycast

Campbell Barton noreply at git.blender.org
Tue Jan 13 15:37:28 CET 2015


Commit: a2a7260915633eda8a3d26aa678baba49b2429ce
Author: Campbell Barton
Date:   Tue Jan 13 23:54:14 2015 +1100
Branches: master
https://developer.blender.org/rBa2a7260915633eda8a3d26aa678baba49b2429ce

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

===================================================================

M	source/blender/blenkernel/BKE_editmesh_bvh.h
M	source/blender/blenkernel/intern/editmesh_bvh.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 168f700..3ee7dcd 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -43,6 +43,8 @@ struct Scene;
 
 typedef struct BMBVHTree BMBVHTree;
 
+typedef bool (*BMBVHTree_FaceFilter)(struct BMFace *f, void *userdata);
+
 BMBVHTree      *BKE_bmbvh_new_from_editmesh(
         struct BMEditMesh *em, int flag,
         const float (*cos_cage)[3], const bool cos_cage_free);
@@ -55,8 +57,16 @@ BMBVHTree      *BKE_bmbvh_new(
         const float (*cos_cage)[3], const bool cos_cage_free);
 void            BKE_bmbvh_free(BMBVHTree *tree);
 struct BVHTree *BKE_bmbvh_tree_get(BMBVHTree *tree);
-struct BMFace  *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
-                                   float *r_dist, float r_hitout[3], float r_cagehit[3]);
+
+struct BMFace  *BKE_bmbvh_ray_cast(
+        BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
+        float *r_dist, float r_hitout[3], float r_cagehit[3]);
+
+struct BMFace  *BKE_bmbvh_ray_cast_filter(
+        BMBVHTree *tree, 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, void *filter_cb);
+
 /* find a face intersecting a segment (but not apart of the segment) */
 struct BMFace  *BKE_bmbvh_find_face_segment(BMBVHTree *tree, const float co_a[3], const float co_b[3],
                                             float *r_fac, float r_hitout[3], float r_cagehit[3]);
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 442ab26..5f2660b 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 */




More information about the Bf-blender-cvs mailing list