Query pipeline: add methods to collect all intersections with a point or a shape.
This commit is contained in:
@@ -12,6 +12,9 @@ use cdl::query::details::{
|
|||||||
RayCompositeShapeToiAndNormalBestFirstVisitor, RayCompositeShapeToiBestFirstVisitor,
|
RayCompositeShapeToiAndNormalBestFirstVisitor, RayCompositeShapeToiBestFirstVisitor,
|
||||||
TOICompositeShapeShapeBestFirstVisitor,
|
TOICompositeShapeShapeBestFirstVisitor,
|
||||||
};
|
};
|
||||||
|
use cdl::query::visitors::{
|
||||||
|
BoundingVolumeIntersectionsVisitor, PointIntersectionsVisitor, RayIntersectionsVisitor,
|
||||||
|
};
|
||||||
use cdl::query::{DefaultQueryDispatcher, QueryDispatcher, TOI};
|
use cdl::query::{DefaultQueryDispatcher, QueryDispatcher, TOI};
|
||||||
use cdl::shape::{FeatureId, Shape, TypedSimdCompositeShape};
|
use cdl::shape::{FeatureId, Shape, TypedSimdCompositeShape};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -183,35 +186,33 @@ impl QueryPipeline {
|
|||||||
/// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray.
|
/// limits the length of the ray to `ray.dir.norm() * max_toi`. Use `Real::MAX` for an unbounded ray.
|
||||||
/// - `callback`: function executed on each collider for which a ray intersection has been found.
|
/// - `callback`: function executed on each collider for which a ray intersection has been found.
|
||||||
/// There is no guarantees on the order the results will be yielded. If this callback returns `false`,
|
/// There is no guarantees on the order the results will be yielded. If this callback returns `false`,
|
||||||
/// this method will exit early, ignory any further raycast.
|
/// this method will exit early, ignore any further raycast.
|
||||||
pub fn intersections_with_ray<'a>(
|
pub fn intersections_with_ray<'a>(
|
||||||
&self,
|
&self,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
ray: &Ray,
|
ray: &Ray,
|
||||||
max_toi: Real,
|
max_toi: Real,
|
||||||
|
solid: bool,
|
||||||
groups: InteractionGroups,
|
groups: InteractionGroups,
|
||||||
mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool,
|
mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool,
|
||||||
) {
|
) {
|
||||||
// TODO: avoid allocation?
|
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
||||||
let mut inter = Vec::new();
|
if let Some(coll) = colliders.get(*handle) {
|
||||||
self.quadtree.cast_ray(ray, max_toi, &mut inter);
|
if coll.collision_groups.test(groups) {
|
||||||
|
if let Some(hit) =
|
||||||
|
coll.shape()
|
||||||
|
.cast_ray_and_get_normal(coll.position(), ray, max_toi, solid)
|
||||||
|
{
|
||||||
|
return callback(*handle, coll, hit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for handle in inter {
|
true
|
||||||
let collider = &colliders[handle];
|
};
|
||||||
|
|
||||||
if collider.collision_groups.test(groups) {
|
let mut visitor = RayIntersectionsVisitor::new(ray, max_toi, &mut leaf_callback);
|
||||||
if let Some(inter) = collider.shape().cast_ray_and_get_normal(
|
self.quadtree.traverse_depth_first(&mut visitor);
|
||||||
collider.position(),
|
|
||||||
ray,
|
|
||||||
max_toi,
|
|
||||||
true,
|
|
||||||
) {
|
|
||||||
if !callback(handle, collider, inter) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find up to one collider intersecting the given shape.
|
/// Find up to one collider intersecting the given shape.
|
||||||
@@ -235,8 +236,6 @@ impl QueryPipeline {
|
|||||||
.map(|h| (h.1 .0))
|
.map(|h| (h.1 .0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: intersections_with_point (collect all colliders containing the point).
|
|
||||||
|
|
||||||
/// Projects a point on the scene.
|
/// Projects a point on the scene.
|
||||||
fn project_point(
|
fn project_point(
|
||||||
&self,
|
&self,
|
||||||
@@ -254,6 +253,31 @@ impl QueryPipeline {
|
|||||||
.map(|h| (h.1 .1, h.1 .0))
|
.map(|h| (h.1 .1, h.1 .0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets all the colliders containing the given point.
|
||||||
|
pub fn intersections_with_point<'a>(
|
||||||
|
&self,
|
||||||
|
colliders: &'a ColliderSet,
|
||||||
|
point: &Point<Real>,
|
||||||
|
groups: InteractionGroups,
|
||||||
|
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
||||||
|
) {
|
||||||
|
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
||||||
|
if let Some(coll) = colliders.get(*handle) {
|
||||||
|
if coll.collision_groups.test(groups)
|
||||||
|
&& coll.shape().contains_point(coll.position(), point)
|
||||||
|
{
|
||||||
|
return callback(*handle, coll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut visitor = PointIntersectionsVisitor::new(point, &mut leaf_callback);
|
||||||
|
|
||||||
|
self.quadtree.traverse_depth_first(&mut visitor);
|
||||||
|
}
|
||||||
|
|
||||||
/// Projects a point on the scene and get
|
/// Projects a point on the scene and get
|
||||||
fn project_point_and_get_feature(
|
fn project_point_and_get_feature(
|
||||||
&self,
|
&self,
|
||||||
@@ -313,8 +337,7 @@ impl QueryPipeline {
|
|||||||
self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1)
|
self.quadtree.traverse_best_first(&mut visitor).map(|h| h.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Gets all the colliders containing the given shape.
|
||||||
/// Gets all the colliders with a shape intersecting the given `shape`.
|
|
||||||
pub fn intersections_with_shape<'a>(
|
pub fn intersections_with_shape<'a>(
|
||||||
&self,
|
&self,
|
||||||
colliders: &'a ColliderSet,
|
colliders: &'a ColliderSet,
|
||||||
@@ -323,6 +346,26 @@ impl QueryPipeline {
|
|||||||
groups: InteractionGroups,
|
groups: InteractionGroups,
|
||||||
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
mut callback: impl FnMut(ColliderHandle, &'a Collider) -> bool,
|
||||||
) {
|
) {
|
||||||
|
let dispatcher = &*self.query_dispatcher;
|
||||||
|
let inv_shape_pos = shape_pos.inverse();
|
||||||
|
|
||||||
|
let mut leaf_callback = &mut |handle: &ColliderHandle| {
|
||||||
|
if let Some(coll) = colliders.get(*handle) {
|
||||||
|
if coll.collision_groups.test(groups) {
|
||||||
|
let pos12 = inv_shape_pos * coll.position();
|
||||||
|
|
||||||
|
if dispatcher.intersection_test(&pos12, shape, coll.shape()) == Ok(true) {
|
||||||
|
return callback(*handle, coll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
let shape_aabb = shape.compute_aabb(shape_pos);
|
||||||
|
let mut visitor = BoundingVolumeIntersectionsVisitor::new(&shape_aabb, &mut leaf_callback);
|
||||||
|
|
||||||
|
self.quadtree.traverse_depth_first(&mut visitor);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user