#![feature(test)]
extern crate cgmath;
extern crate collision;
extern crate rand;
extern crate test;
use cgmath::{Point2, Vector2};
use cgmath::prelude::*;
use collision::{Aabb2, Ray2};
use collision::dbvt::*;
use collision::prelude::*;
use rand::Rng;
use test::Bencher;
#[derive(Debug, Clone)]
struct Value {
pub id: u32,
pub aabb: Aabb2<f32>,
fat_aabb: Aabb2<f32>,
}
impl Value {
pub fn new(id: u32, aabb: Aabb2<f32>) -> Self {
Self {
id,
fat_aabb: aabb.add_margin(Vector2::new(0., 0.)),
aabb,
}
}
}
impl TreeValue for Value {
type Bound = Aabb2<f32>;
fn bound(&self) -> &Aabb2<f32> {
&self.aabb
}
fn get_bound_with_margin(&self) -> Aabb2<f32> {
self.fat_aabb
}
}
#[bench]
fn benchmark_insert(b: &mut Bencher) {
let mut rng = rand::thread_rng();
let mut tree = DynamicBoundingVolumeTree::<Value>::new();
let mut i = 0;
b.iter(|| {
let offset = rng.gen_range(0., 100.);
tree.insert(Value::new(
i,
aabb2(offset + 2., offset + 2., offset + 4., offset + 4.),
));
i += 1;
});
}
#[bench]
fn benchmark_do_refit(b: &mut Bencher) {
let mut rng = rand::thread_rng();
let mut tree = DynamicBoundingVolumeTree::<Value>::new();
let mut i = 0;
b.iter(|| {
let offset = rng.gen_range(0., 100.);
tree.insert(Value::new(
i,
aabb2(offset + 2., offset + 2., offset + 4., offset + 4.),
));
tree.do_refit();
i += 1;
});
}
#[bench]
fn benchmark_query(b: &mut Bencher) {
let mut rng = rand::thread_rng();
let mut tree = DynamicBoundingVolumeTree::<Value>::new();
for i in 0..100000 {
let neg_y = if rng.gen::<bool>() { -1. } else { 1. };
let neg_x = if rng.gen::<bool>() { -1. } else { 1. };
let offset_x = neg_x * rng.gen_range(9000., 10000.);
let offset_y = neg_y * rng.gen_range(9000., 10000.);
tree.insert(Value::new(
i,
aabb2(offset_x + 2., offset_y + 2., offset_x + 4., offset_y + 4.),
));
tree.tick();
}
let rays: Vec<Ray2<f32>> = (0..1000)
.map(|_| {
let p = Point2::new(
rng.gen_range(-10000., 10000.),
rng.gen_range(-10000., 10000.),
);
let d = Vector2::new(rng.gen_range(-1., 1.), rng.gen_range(-1., 1.)).normalize();
Ray2::new(p, d)
})
.collect();
let mut visitors: Vec<DiscreteVisitor<Ray2<f32>, Value>> = rays.iter()
.map(|ray| DiscreteVisitor::<Ray2<f32>, Value>::new(ray))
.collect();
let mut i = 0;
b.iter(|| {
tree.query(&mut visitors[i % 1000]).len();
i += 1;
});
}
#[bench]
fn benchmark_ray_closest_query(b: &mut Bencher) {
let mut rng = rand::thread_rng();
let mut tree = DynamicBoundingVolumeTree::<Value>::new();
for i in 0..100000 {
let neg_y = if rng.gen::<bool>() { -1. } else { 1. };
let neg_x = if rng.gen::<bool>() { -1. } else { 1. };
let offset_x = neg_x * rng.gen_range(9000., 10000.);
let offset_y = neg_y * rng.gen_range(9000., 10000.);
tree.insert(Value::new(
i,
aabb2(offset_x + 2., offset_y + 2., offset_x + 4., offset_y + 4.),
));
tree.tick();
}
let rays: Vec<Ray2<f32>> = (0..1000)
.map(|_| {
let p = Point2::new(
rng.gen_range(-10000., 10000.),
rng.gen_range(-10000., 10000.),
);
let d = Vector2::new(rng.gen_range(-1., 1.), rng.gen_range(-1., 1.)).normalize();
Ray2::new(p, d)
})
.collect();
let mut i = 0;
b.iter(|| {
query_ray_closest(&tree, rays[i % 1000]);
i += 1;
});
}
fn aabb2(minx: f32, miny: f32, maxx: f32, maxy: f32) -> Aabb2<f32> {
Aabb2::new(Point2::new(minx, miny), Point2::new(maxx, maxy))
}