Skip to main content

box2d_rs/
b2_broad_phase.rs

1use crate::b2_collision::*;
2use crate::b2_dynamic_tree::*;
3use crate::b2_math::*;
4use crate::private::collision::b2_broad_phase as private;
5
6use std::cell::RefCell;
7use std::rc::Rc;
8
9#[derive(Default, Clone, Copy, Debug)]
10pub struct B2pair {
11	pub proxy_id_a: i32,
12	pub proxy_id_b: i32,
13}
14
15pub type B2broadPhasePtr<UserDataType> = Rc<RefCell<B2broadPhase<UserDataType>>>;
16
17/// The broad-phase is used for computing pairs and performing volume queries and ray casts.
18/// This broad-phase does not persist pairs. Instead, this reports potentially new pairs.
19/// It is up to the client to consume the new pairs and to track subsequent overlap.
20#[derive(Debug)]
21pub struct B2broadPhase<UserDataType> {
22	pub(crate) m_tree: B2dynamicTree<UserDataType>,
23
24	pub(crate) m_proxy_count: i32,
25
26	pub(crate) m_move_buffer: Vec<i32>,
27	pub(crate) m_move_capacity: i32,
28	pub(crate) m_move_count: i32,
29
30	pub(crate) pairs: B2broadPhasePairs,
31}
32
33//because of &mut
34#[derive(Debug, Default)]
35pub struct B2broadPhasePairs {
36	pub(crate) m_pair_buffer: Vec<B2pair>,
37	pub(crate) m_pair_capacity: i32,
38	pub(crate) m_pair_count: i32,
39}
40
41pub const E_NULL_PROXY: i32 = -1;
42
43impl<UserDataType: Default + Clone> B2broadPhase<UserDataType> {
44	pub fn new() -> Self {
45		return private::b2_broad_phase_b2_broad_phase();
46	}
47
48	//~B2broadPhase();
49
50	/// create a proxy with an initial AABB. Pairs are not reported until
51	/// UpdatePairs is called.
52	pub fn create_proxy(&mut self, aabb: B2AABB, user_data: &UserDataType) -> i32 {
53		return private::b2_broad_phase_create_proxy(self, aabb, user_data);
54	}
55
56	/// destroy a proxy. It is up to the client to remove any pairs.
57	pub fn destroy_proxy(&mut self, proxy_id: i32) {
58		private::b2_broad_phase_destroy_proxy(self, proxy_id);
59	}
60
61	/// Call move_proxy as many times as you like, then when you are done
62	/// call UpdatePairs to finalized the proxy pairs (for your time step).
63	pub fn move_proxy(&mut self, proxy_id: i32, aabb: B2AABB, displacement: B2vec2) {
64		private::b2_broad_phase_move_proxy(self, proxy_id, aabb, displacement);
65	}
66
67	/// Call to trigger a re-processing of it's pairs on the next call to UpdatePairs.
68	pub fn touch_proxy(&mut self, proxy_id: i32) {
69		private::b2_broad_phase_touch_proxy(self, proxy_id);
70	}
71
72	/// Get the fat AABB for a proxy.
73	pub fn get_fat_aabb(&self, proxy_id: i32) -> B2AABB {
74		return inline::get_fat_aabb(self, proxy_id);
75	}
76
77	/// Get user data from a proxy. Returns None if the id is invalid.
78	pub fn get_user_data(&self, proxy_id: i32) -> Option<UserDataType> {
79		return inline::get_user_data(self, proxy_id);
80	}
81
82	/// Test overlap of fat AABBs.
83	pub fn test_overlap(&self, proxy_id_a: i32, proxy_id_b: i32) -> bool {
84		return inline::test_overlap(self, proxy_id_a, proxy_id_b);
85	}
86
87	/// Get the number of proxies.
88	pub fn get_proxy_count(&self) -> i32 {
89		return inline::get_proxy_count(self);
90	}
91
92	/// update the pairs. This results in pair callbacks. This can only add pairs.
93	pub fn update_pairs<CallbackType: AddPairTrait<UserDataType>>(
94		&mut self,
95		callback: &mut CallbackType,
96	) {
97		inline::update_pairs(self, callback);
98	}
99
100	/// query an AABB for overlapping proxies. The callback class
101	/// is called for each proxy that overlaps the supplied AABB.
102	pub fn query<F:  QueryCallback>(&self, callback: F, aabb: B2AABB) {
103		inline::query(self, callback, aabb);
104	}
105
106	/// Ray-cast against the proxies in the tree. This relies on the callback
107	/// to perform a exact ray-cast in the case were the proxy contains a shape.
108	/// The callback also performs the any collision filtering. This has performance
109	/// roughly equal to k * log(n), where k is the number of collisions and n is the
110	/// number of proxies in the tree.
111	/// * `input` - the ray-cast input data. The ray extends from p1 to p1 + max_fraction * (p2 - p1).
112	/// * `callback` - a callback class that is called for each proxy that is hit by the ray.
113	pub fn ray_cast<T: RayCastCallback>(&self, callback: T, input: &B2rayCastInput) {
114		inline::ray_cast(self, callback, input);
115	}
116
117	/// Get the height of the embedded tree.
118	pub fn get_tree_height(&self) -> i32 {
119		return inline::get_tree_height(self);
120	}
121
122	/// Get the balance of the embedded tree.
123	pub fn get_tree_balance(&self) -> i32 {
124		return inline::get_tree_balance(self);
125	}
126
127	/// Get the quality metric of the embedded tree.
128	pub fn get_tree_quality(&self) -> f32 {
129		return inline::get_tree_quality(self);
130	}
131
132	/// Shift the world origin. Useful for large worlds.
133	/// The shift formula is: position -= new_origin
134	/// * `new_origin` - the new origin with respect to the old origin
135	pub fn shift_origin(&mut self, new_origin: B2vec2) {
136		inline::shift_origin(self, new_origin);
137	}
138
139	pub fn get_tree_mut(&mut self)->&mut B2dynamicTree<UserDataType>{
140		return &mut self.m_tree;
141	}
142
143	pub(crate) fn buffer_move(&mut self, proxy_id: i32) {
144		private::b2_broad_phase_buffer_move(self, proxy_id);
145	}
146
147	pub(crate) fn un_buffer_move(&mut self, proxy_id: i32) {
148		private::b2_broad_phase_un_buffer_move(self, proxy_id);
149	}
150}
151
152pub trait AddPairTrait<UserDataType> {
153	fn add_pair(
154		&mut self,
155		proxy_user_data_a: Option<UserDataType>,
156		proxy_user_data_b: Option<UserDataType>,
157	);
158}
159
160mod inline {
161	use super::*;
162
163	pub fn get_user_data<UserDataType: Default + Clone>(
164		self_: &B2broadPhase<UserDataType>,
165		proxy_id: i32,
166	) -> Option<UserDataType> {
167		return self_.m_tree.get_user_data(proxy_id);
168	}
169
170	pub fn test_overlap<T: Default + Clone>(
171		self_: &B2broadPhase<T>,
172		proxy_id_a: i32,
173		proxy_id_b: i32,
174	) -> bool {
175		let aabb_a: B2AABB = self_.m_tree.get_fat_aabb(proxy_id_a);
176		let aabb_b: B2AABB = self_.m_tree.get_fat_aabb(proxy_id_b);
177		return b2_test_overlap(aabb_a, aabb_b);
178	}
179
180	pub fn get_fat_aabb<T: Default + Clone>(self_: &B2broadPhase<T>, proxy_id: i32) -> B2AABB {
181		return self_.m_tree.get_fat_aabb(proxy_id);
182	}
183
184	pub fn get_proxy_count<T: Default + Clone>(self_: &B2broadPhase<T>) -> i32 {
185		return self_.m_proxy_count;
186	}
187
188	pub fn get_tree_height<T: Default + Clone>(self_: &B2broadPhase<T>) -> i32 {
189		return self_.m_tree.get_height();
190	}
191
192	pub fn get_tree_balance<T: Default + Clone>(self_: &B2broadPhase<T>) -> i32 {
193		return self_.m_tree.get_max_balance();
194	}
195
196	pub fn get_tree_quality<T: Default + Clone>(self_: &B2broadPhase<T>) -> f32 {
197		return self_.m_tree.get_area_ration();
198	}
199
200	pub fn update_pairs<T: Default + Clone, CallbackType: AddPairTrait<T>>(
201		self_: &mut B2broadPhase<T>,
202		callback: &mut CallbackType,
203	) {
204		// reset pair buffer
205		self_.pairs.m_pair_count=0;
206
207		// Perform tree queries for all moving proxies.
208		for i in 0..self_.m_move_count {
209			let m_query_proxy_id = self_.m_move_buffer[i as usize];
210			if m_query_proxy_id == E_NULL_PROXY {
211				continue;
212			}
213
214			// We have to query the tree with the fat AABB so that
215			// we don't fail to create a pair that may touch later.
216			let fat_aabb: B2AABB = self_.m_tree.get_fat_aabb(m_query_proxy_id);
217			{
218				let pairs = &mut self_.pairs;
219				let tree = &self_.m_tree;
220				// query tree, create pairs and add them pair buffer.
221				tree.query(|proxy_id:i32|->bool{
222					let moved = tree.was_moved(proxy_id);
223					return private::b2_broad_phase_query_callback(pairs, m_query_proxy_id, proxy_id, moved);
224				}, fat_aabb);
225			}
226		}
227
228		// Send pairs to caller
229		for i in 0..self_.pairs.m_pair_count {
230			let primary_pair: B2pair = self_.pairs.m_pair_buffer[i as usize];
231			let user_data_a = self_.m_tree.get_user_data(primary_pair.proxy_id_a);
232			let user_data_b = self_.m_tree.get_user_data(primary_pair.proxy_id_b);
233
234			callback.add_pair(user_data_a, user_data_b);
235		}
236
237		// clear move flags
238		for i in 0..self_.m_move_count {
239			let proxy_id: i32 = self_.m_move_buffer[i as usize];
240			if proxy_id == E_NULL_PROXY {
241				continue;
242			}
243
244			self_.m_tree.clear_moved(proxy_id);
245		}
246
247		// reset move buffer
248		self_.m_move_count = 0;
249	}
250
251	pub fn query<UserDataType: Default + Clone, F:  QueryCallback>(
252		self_: &B2broadPhase<UserDataType>,
253		callback: F,
254		aabb: B2AABB,
255	) {
256		self_.m_tree.query(callback, aabb);
257	}
258
259	pub fn ray_cast<UserDataType: Default + Clone, T: RayCastCallback>(
260		self_: &B2broadPhase<UserDataType>,
261		callback: T,
262		input: &B2rayCastInput,
263	) {
264		self_.m_tree.ray_cast(callback, input);
265	}
266
267	pub fn shift_origin<UserDataType: Default + Clone>(
268		self_: &mut B2broadPhase<UserDataType>,
269		new_origin: B2vec2,
270	) {
271		self_.m_tree.shift_origin(new_origin);
272	}
273}