#![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, fat_aabb: Aabb2, } impl Value { pub fn new(id: u32, aabb: Aabb2) -> Self { Self { id, fat_aabb: aabb.add_margin(Vector2::new(0., 0.)), aabb, } } } impl TreeValue for Value { type Bound = Aabb2; fn bound(&self) -> &Aabb2 { &self.aabb } fn get_bound_with_margin(&self) -> Aabb2 { self.fat_aabb } } #[bench] fn benchmark_insert(b: &mut Bencher) { let mut rng = rand::thread_rng(); let mut tree = DynamicBoundingVolumeTree::::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::::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::::new(); for i in 0..100000 { let neg_y = if rng.gen::() { -1. } else { 1. }; let neg_x = if rng.gen::() { -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> = (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, Value>> = rays.iter() .map(|ray| DiscreteVisitor::, 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::::new(); for i in 0..100000 { let neg_y = if rng.gen::() { -1. } else { 1. }; let neg_x = if rng.gen::() { -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> = (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 { Aabb2::new(Point2::new(minx, miny), Point2::new(maxx, maxy)) }