Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions build/ncollide2d/examples/ray_bvt2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ extern crate ncollide2d;

use na::{Isometry2, Point2, Vector2};
use ncollide2d::bounding_volume::{self, BoundingSphere, HasBoundingVolume};
use ncollide2d::partitioning::{BVH, BVT};
use ncollide2d::query::{visitors::RayInterferencesCollector, Ray, RayCast};
use ncollide2d::partitioning::{VisitStatus, BVH, BVT};
use ncollide2d::query::{visitors::RayInterferencesVisitor, Ray, RayCast};
use ncollide2d::shape::{Ball, Cuboid};

/*
Expand Down Expand Up @@ -61,20 +61,24 @@ fn main() {
/*
* Collecting all objects with bounding volumes intersecting the ray.
*/
let mut collector_hit: Vec<usize> = Vec::new();
let mut collector_miss: Vec<usize> = Vec::new();
let mut hit_count = 0;
let mut miss_count = 0;

// We need a new scope here to avoid borrowing issues.
{
let mut visitor_hit =
RayInterferencesCollector::new(&ray_hit, std::f64::MAX, &mut collector_hit);
let mut visitor_miss =
RayInterferencesCollector::new(&ray_miss, std::f64::MAX, &mut collector_miss);
let mut visitor_hit = RayInterferencesVisitor::new(&ray_hit, std::f64::MAX, |_| {
hit_count += 1;
VisitStatus::Continue
});
let mut visitor_miss = RayInterferencesVisitor::new(&ray_miss, std::f64::MAX, |_| {
miss_count += 1;
VisitStatus::Continue
});

bvt.visit(&mut visitor_hit);
bvt.visit(&mut visitor_miss);
}

assert!(collector_hit.len() == 3);
assert!(collector_miss.len() == 0);
assert_eq!(hit_count, 3);
assert_eq!(miss_count, 0);
}
24 changes: 14 additions & 10 deletions build/ncollide3d/examples/ray_bvt3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ extern crate ncollide3d;

use na::{Isometry3, Point3, Vector3};
use ncollide3d::bounding_volume::{self, BoundingSphere, HasBoundingVolume};
use ncollide3d::partitioning::{BVH, BVT};
use ncollide3d::query::{visitors::RayInterferencesCollector, Ray, RayCast};
use ncollide3d::partitioning::{VisitStatus, BVH, BVT};
use ncollide3d::query::{visitors::RayInterferencesVisitor, Ray, RayCast};
use ncollide3d::shape::{Ball, Capsule, Cone, Cuboid};

/*
Expand Down Expand Up @@ -60,20 +60,24 @@ fn main() {
/*
* Ray cast using a visitor.
*/
let mut collector_hit: Vec<usize> = Vec::new();
let mut collector_miss: Vec<usize> = Vec::new();
let mut hit_count = 0;
let mut miss_count = 0;

// We need a new scope here to avoid borrowing issues.
{
let mut visitor_hit =
RayInterferencesCollector::new(&ray_hit, std::f64::MAX, &mut collector_hit);
let mut visitor_miss =
RayInterferencesCollector::new(&ray_miss, std::f64::MAX, &mut collector_miss);
let mut visitor_hit = RayInterferencesVisitor::new(&ray_hit, std::f64::MAX, |_| {
hit_count += 1;
VisitStatus::Continue
});
let mut visitor_miss = RayInterferencesVisitor::new(&ray_miss, std::f64::MAX, |_| {
miss_count += 1;
VisitStatus::Continue
});

bvt.visit(&mut visitor_hit);
bvt.visit(&mut visitor_miss);
}

assert!(collector_hit.len() == 3);
assert!(collector_miss.len() == 0);
assert_eq!(hit_count, 3);
assert_eq!(miss_count, 0);
}
110 changes: 49 additions & 61 deletions src/pipeline/broad_phase/dbvt_broad_phase.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::bounding_volume::BoundingVolume;
use crate::math::Point;
use crate::partitioning::{DBVTLeaf, DBVTLeafId, BVH, DBVT};
use crate::partitioning::{DBVTLeaf, DBVTLeafId, VisitStatus, BVH, DBVT};
use crate::pipeline::broad_phase::{
BroadPhase, BroadPhaseInterferenceHandler, BroadPhaseProxyHandle,
};
use crate::query::visitors::{
BoundingVolumeInterferencesCollector, PointInterferencesCollector, RayInterferencesCollector,
BoundingVolumeInterferencesVisitor, PointInterferencesVisitor, RayInterferencesVisitor,
RayIntersectionCostFnVisitor,
};
use crate::query::{PointQuery, Ray, RayCast, RayIntersection};
Expand Down Expand Up @@ -67,7 +67,6 @@ pub struct DBVTBroadPhase<N: RealField, BV, T> {
purge_all: bool,

// Just to avoid dynamic allocations.
collector: Vec<BroadPhaseProxyHandle>,
leaves_to_update: Vec<DBVTLeaf<N, BroadPhaseProxyHandle, BV>>,
proxies_to_update: VecDeque<(BroadPhaseProxyHandle, BV)>,
}
Expand All @@ -85,7 +84,6 @@ where
stree: DBVT::new(),
pairs: HashMap::with_hasher(DeterministicState::new()),
purge_all: false,
collector: Vec::new(),
leaves_to_update: Vec::new(),
proxies_to_update: VecDeque::new(),
margin,
Expand Down Expand Up @@ -171,7 +169,7 @@ where
BV: BoundingVolume<N> + RayCast<N> + PointQuery<N> + Any + Send + Sync + Clone,
T: Any + Send + Sync + Clone,
{
fn update(&mut self, handler: &mut dyn BroadPhaseInterferenceHandler<T>) {
fn update(&mut self, mut handler: &mut dyn BroadPhaseInterferenceHandler<T>) {
/*
* Remove from the trees all nodes that have been deleted or modified.
*/
Expand Down Expand Up @@ -218,32 +216,34 @@ where
for leaf in self.leaves_to_update.drain(..) {
{
let proxy1 = &self.proxies[leaf.data.uid()];
{
let mut visitor = BoundingVolumeInterferencesCollector::new(
let mut visitor = {
let proxies = &self.proxies;
let pairs = &mut self.pairs;
let handler = &mut handler;
let leaf = &leaf;
BoundingVolumeInterferencesVisitor::new(
&leaf.bounding_volume,
&mut self.collector,
);

self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}

// Event generation.
for proxy_key2 in self.collector.iter() {
let proxy2 = &self.proxies[proxy_key2.uid()];

if handler.is_interference_allowed(&proxy1.data, &proxy2.data) {
match self.pairs.entry(SortedPair::new(leaf.data, *proxy_key2)) {
Entry::Occupied(entry) => *entry.into_mut() = true,
Entry::Vacant(entry) => {
handler.interference_started(&proxy1.data, &proxy2.data);
let _ = entry.insert(true);
move |proxy_key2: &BroadPhaseProxyHandle| {
// Event generation.
let proxy2 = &proxies[proxy_key2.uid()];

if handler.is_interference_allowed(&proxy1.data, &proxy2.data) {
match pairs.entry(SortedPair::new(leaf.data, *proxy_key2)) {
Entry::Occupied(entry) => *entry.into_mut() = true,
Entry::Vacant(entry) => {
handler.interference_started(&proxy1.data, &proxy2.data);
let _ = entry.insert(true);
}
}
}
}
}
}

self.collector.clear();
VisitStatus::Continue
},
)
};

self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}

let proxy1 = &mut self.proxies[leaf.data.uid()];
Expand Down Expand Up @@ -385,48 +385,36 @@ where
}

fn interferences_with_bounding_volume<'a>(&'a self, bv: &BV, out: &mut Vec<&'a T>) {
let mut collector = Vec::new();

{
let mut visitor = BoundingVolumeInterferencesCollector::new(bv, &mut collector);

self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}
let mut visitor =
BoundingVolumeInterferencesVisitor::new(bv, |handle: &BroadPhaseProxyHandle| {
out.push(&self.proxies[handle.uid()].data);
VisitStatus::Continue
});

for l in collector.into_iter() {
out.push(&self.proxies[l.uid()].data)
}
self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}

fn interferences_with_ray<'a>(&'a self, ray: &Ray<N>, max_toi: N, out: &mut Vec<&'a T>) {
let mut collector = Vec::new();

{
let mut visitor = RayInterferencesCollector::new(ray, max_toi, &mut collector);

self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}
let mut visitor =
RayInterferencesVisitor::new(ray, max_toi, |handle: &BroadPhaseProxyHandle| {
out.push(&self.proxies[handle.uid()].data);
VisitStatus::Continue
});

for l in collector.into_iter() {
out.push(&self.proxies[l.uid()].data)
}
self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}

fn interferences_with_point<'a>(&'a self, point: &Point<N>, out: &mut Vec<&'a T>) {
let mut collector = Vec::new();

{
let mut visitor = PointInterferencesCollector::new(point, &mut collector);

self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}
let mut visitor =
PointInterferencesVisitor::new(point, |handle: &BroadPhaseProxyHandle| {
out.push(&self.proxies[handle.uid()].data);
VisitStatus::Continue
});

for l in collector.into_iter() {
out.push(&self.proxies[l.uid()].data)
}
self.tree.visit(&mut visitor);
self.stree.visit(&mut visitor);
}

/// Returns the first object that interferes with a ray.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::math::Isometry;
use crate::partitioning::VisitStatus;
use crate::pipeline::narrow_phase::{
ContactAlgorithm, ContactDispatcher, ContactManifoldGenerator,
};
use crate::query::{
visitors::AABBSetsInterferencesCollector, ContactManifold, ContactPrediction,
ContactPreprocessor,
visitors::AABBSetsInterferencesVisitor, ContactManifold, ContactPrediction, ContactPreprocessor,
};
use crate::shape::{CompositeShape, Shape};
use crate::utils::DeterministicState;
Expand All @@ -14,7 +14,6 @@ use std::collections::{hash_map::Entry, HashMap};
/// Collision detector between a concave shape and another shape.
pub struct CompositeShapeCompositeShapeManifoldGenerator<N> {
sub_detectors: HashMap<(usize, usize), (ContactAlgorithm<N>, usize), DeterministicState>,
interferences: Vec<(usize, usize)>,
timestamp: usize,
}

Expand All @@ -23,7 +22,6 @@ impl<N> CompositeShapeCompositeShapeManifoldGenerator<N> {
pub fn new() -> CompositeShapeCompositeShapeManifoldGenerator<N> {
CompositeShapeCompositeShapeManifoldGenerator {
sub_detectors: HashMap::with_hasher(DeterministicState),
interferences: Vec::new(),
timestamp: 0,
}
}
Expand All @@ -49,36 +47,33 @@ impl<N: RealField> CompositeShapeCompositeShapeManifoldGenerator<N> {
// For transforming AABBs from g2 in the local space of g1.
let ls_m2_abs_rot = ls_m2.rotation.to_rotation_matrix().matrix().abs();

{
let mut visitor = AABBSetsInterferencesCollector::new(
prediction.linear(),
&ls_m2,
&ls_m2_abs_rot,
&mut self.interferences,
);
g1.bvh().visit_bvtt(g2.bvh(), &mut visitor);
}

for id in self.interferences.drain(..) {
match self.sub_detectors.entry(id) {
Entry::Occupied(mut entry) => {
entry.get_mut().1 = self.timestamp;
}
Entry::Vacant(entry) => {
let mut new_detector = None;
let mut visitor = AABBSetsInterferencesVisitor::new(
prediction.linear(),
&ls_m2,
&ls_m2_abs_rot,
|a, b| {
match self.sub_detectors.entry((*a, *b)) {
Entry::Occupied(mut entry) => {
entry.get_mut().1 = self.timestamp;
}
Entry::Vacant(entry) => {
let mut new_detector = None;

g1.map_part_at(id.0, &Isometry::identity(), &mut |_, g1| {
g2.map_part_at(id.1, &Isometry::identity(), &mut |_, g2| {
new_detector = dispatcher.get_contact_algorithm(g1, g2)
g1.map_part_at(*a, &Isometry::identity(), &mut |_, g1| {
g2.map_part_at(*b, &Isometry::identity(), &mut |_, g2| {
new_detector = dispatcher.get_contact_algorithm(g1, g2)
});
});
});

if let Some(new_detector) = new_detector {
let _ = entry.insert((new_detector, self.timestamp));
if let Some(new_detector) = new_detector {
let _ = entry.insert((new_detector, self.timestamp));
}
}
}
}
}
VisitStatus::Continue
},
);
g1.bvh().visit_bvtt(g2.bvh(), &mut visitor);

// Update all collisions
let timestamp = self.timestamp;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::bounding_volume::{self, BoundingVolume};
use crate::math::Isometry;
use crate::partitioning::VisitStatus;
use crate::pipeline::narrow_phase::{
ContactAlgorithm, ContactDispatcher, ContactManifoldGenerator,
};
use crate::query::{
visitors::BoundingVolumeInterferencesCollector, ContactManifold, ContactPrediction,
visitors::BoundingVolumeInterferencesVisitor, ContactManifold, ContactPrediction,
ContactPreprocessor, ContactTrackingMode,
};
use crate::shape::{CompositeShape, Shape};
Expand All @@ -15,7 +16,6 @@ use std::collections::{hash_map::Entry, HashMap};
/// Collision detector between a concave shape and another shape.
pub struct CompositeShapeShapeManifoldGenerator<N: RealField> {
sub_detectors: HashMap<usize, (ContactAlgorithm<N>, usize), DeterministicState>,
interferences: Vec<usize>,
flip: bool,
timestamp: usize,
}
Expand All @@ -25,7 +25,6 @@ impl<N: RealField> CompositeShapeShapeManifoldGenerator<N> {
pub fn new(flip: bool) -> CompositeShapeShapeManifoldGenerator<N> {
CompositeShapeShapeManifoldGenerator {
sub_detectors: HashMap::with_hasher(DeterministicState),
interferences: Vec::new(),
flip,
timestamp: 0,
}
Expand All @@ -49,14 +48,7 @@ impl<N: RealField> CompositeShapeShapeManifoldGenerator<N> {
// Find new collisions
let ls_m2 = m1.inverse() * m2.clone();
let ls_aabb2 = bounding_volume::aabb(g2, &ls_m2).loosened(prediction.linear());

{
let mut visitor =
BoundingVolumeInterferencesCollector::new(&ls_aabb2, &mut self.interferences);
g1.bvh().visit(&mut visitor);
}

for i in self.interferences.drain(..) {
let mut visitor = BoundingVolumeInterferencesVisitor::new(&ls_aabb2, |&i| {
match self.sub_detectors.entry(i) {
Entry::Occupied(mut entry) => entry.get_mut().1 = self.timestamp,
Entry::Vacant(entry) => {
Expand All @@ -75,7 +67,10 @@ impl<N: RealField> CompositeShapeShapeManifoldGenerator<N> {
}
}
}
}

VisitStatus::Continue
});
g1.bvh().visit(&mut visitor);

// Update all collisions
let timestamp = self.timestamp;
Expand Down
Loading