ami/
octree.rs

1// Copyright Jeron A. Lau 2017-2018.
2// Copyright Douglas Lau 2017
3// Dual-licensed under either the MIT License or the Boost Software License,
4// Version 1.0.  (See accompanying file LICENSE_1_0.txt or copy at
5// https://www.boost.org/LICENSE_1_0.txt)
6
7use std::fmt;
8use *;
9
10/// An octree is a DAG that can quickly search for points in 3D space.
11///
12/// The bounding box of the root node contains all points in the octree.
13/// If a point outside the bounding box is added, a new root node is created
14/// which contains the old root as one of its octants.  This process is repeated
15/// until the point is contained.
16///
17/// The nodes are stored in a vector, and are indexed using a 32-bit node ID.
18/// This saves memory over using pointers on 64-bit systems.  Node ID 1 is the
19/// first node in the vector.
20pub struct Octree<T: Collider> {
21	colliders: Vec<T>,
22	collider_garbage: Vec<Id>,
23	nodes: Vec<Node>,
24	garbage: Vec<Id>,
25	bcube: BCube,
26	root: Id,
27	n_colliders: u32,
28}
29
30const LINK: usize = 15;			// link to coincident leaf nodes
31const LEAF: u32 = 0xFF_FF_FF_FF;	// max u32 value (invalid handle)
32
33/// A 32-bit index value.
34#[derive(Debug, PartialEq, Eq, Copy, Clone)]
35pub struct Id(u32);
36
37impl Id {
38	/// Get an `Id` that represents nothing.
39	fn none() -> Self {
40		Id(0)
41	}
42
43	/// Does this `Id` represent nothing?
44	fn is_none(&self) -> bool {
45		self.0 == 0
46	}
47
48	/// Does this `Id` represent something?
49	fn is_some(&self) -> bool {
50		!self.is_none()
51	}
52}
53
54impl Into<Id> for usize {
55	fn into(self) -> Id {
56		Id(self as u32 + 1)
57	}
58}
59
60impl Into<usize> for Id {
61	fn into(self) -> usize {
62		(self.0 - 1) as usize
63	}
64}
65
66/// A node is either a branch or a leaf.
67///
68/// A branch can have up to 8 child nodes (each octant adjacent to the center)
69/// and 7 objects, plus an optional link to a leaf.
70///
71/// A leaf can store up to 14 points; the first child must contain a LEAF
72/// sentinel value, and the last may link to another leaf node.
73///
74/// Each node has an implicit bounding box determined by its position in the
75/// octree.  The bounding box contains all descendant nodes.
76struct Node {
77	/// child node handles
78	child: [Id; 16],
79}
80
81impl fmt::Display for Node {
82	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83		if self.is_leaf() {
84			let l = self.link();
85			if l.is_some() {
86				write!(f, " LINK ")?;
87			}
88			for i in 0..=14 {
89				let id = self.child[i];
90				if id.is_some() {
91					let id: usize = id.into();
92					write!(f, "{} ", id)?;
93				}
94			}	
95		} else {
96			write!(f, "Branch: [")?;
97			for i in 8..=14 {
98				let id = self.child[i];
99				if id.is_some() {
100					let id: usize = id.into();
101					write!(f, "{} ", id)?;
102				}
103			}
104			write!(f, "] -D [")?;
105			for i in 0..8 {
106				let id = self.child[i];
107				if id.is_some() {
108					let id: usize = id.into();
109					write!(f, "{}:{}", i, id)?;
110				}
111			}
112			write!(f, "];")?;
113		}
114
115		Ok(())
116	}
117}
118
119impl fmt::Debug for Node {
120	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121		if self.is_leaf() {
122			try!(write!(f, "leaf"));
123//			try!(write!(f, "leaf: {:?}", self.leaf_children()));
124			let l = self.link();
125			if l.is_some() {
126				try!(write!(f, " link: {:?}", l));
127			}
128			Ok(())
129		} else {
130			write!(f, "branch: {:?}", self.child)
131		}
132	}
133}
134
135impl Node {
136	/// Create a new leaf node
137	fn new_leaf() -> Node {
138		Node {
139			// no elements, no linking
140			child: [
141				Id(LEAF), Id::none(), Id::none(), Id::none(),
142				Id::none(), Id::none(), Id::none(), Id::none(),
143				Id::none(), Id::none(), Id::none(), Id::none(),
144				Id::none(), Id::none(), Id::none(), Id::none()
145			],
146		}
147	}
148
149	/// Create a new branch node
150	fn new_branch() -> Node {
151		Node {
152			child: [Id::none(); 16],
153		}
154	}
155
156	/// Test if a node is a leaf
157	fn is_leaf(&self) -> bool {
158		self.child[0] == Id(LEAF)
159	}
160
161	/// Test if a node is a branch
162	fn is_branch(&self) -> bool {
163		!self.is_leaf()
164	}
165
166	/// Get link to next link node ID
167	fn link(&self) -> Option<usize> {
168		// Can be a branch or a leaf.
169		if self.child[LINK].is_none() {
170			// No link found - shouldn't happen.
171			None
172		} else {
173			// Convert link Id to usize
174			Some(self.child[LINK].into())
175		}
176	}
177
178	/// None has no child branches and no collider Ids
179	fn is_empty(&self) -> bool {
180		assert!(self.is_branch());
181		// First 8 are branches.
182		for i in &self.child[..=14] { // skip link
183			if i.is_some() {
184				return false // isn't empty
185			}
186		}
187
188		true // is empty
189	}
190
191	/// Find the only full ch. branch, if there is only one, None otherwise.
192	fn branch_is_one(&self) -> Option<usize> {
193		assert!(self.is_branch());
194		// First 8 are branches.
195		let mut found = None;
196
197		for i in 0..8 { // First 8 are branches
198			if self.child[i].is_some() {
199				if found.is_some() { // 2, not 1
200					return None;
201				} else {
202					found = Some(i);
203				}
204			}
205		}
206		for i in &self.child[8..=14] { // Skip link are collider Ids
207			if i.is_some() {
208				return None // isn't empty
209			}
210		}
211
212		found
213	}
214
215	/// Find the first open child slot in a branch, None if full.
216	fn branch_open_slot(&self) -> Option<usize> {
217		assert!(self.is_branch());
218		// Skip 0-7 as that is descending the octree, and skip 15 (link)
219		for i in 8..=14 {
220			if self.child[i].is_none() { return Some(i) }
221		}
222		None
223	}
224
225	/// Add a collider to a branch node.
226	fn branch_add_collider(&mut self, id: Id) -> Option<()> {
227		assert!(self.is_branch());
228		let s = self.branch_open_slot()?;
229		self.child[s] = id;
230		// Successfully added it.
231		Some(())
232	}
233
234	/// Remove a collider from a branch node.
235	fn branch_remove_collider(&mut self, id: Id) -> Option<()> {
236		assert!(self.is_branch());
237		// Look for collider in this branch.
238		for i in 8..=14 {
239			// Delete it when found, and return successfully.
240			if self.child[i] == id {
241				self.child[i] = Id::none();
242				return Some(());
243			}
244		}
245		// Not here, look in links next.
246		return None;
247	}
248
249	/// Remove a collider from a leaf node.
250	fn leaf_remove_collider(&mut self, id: Id) -> Option<()> {
251		assert!(self.is_leaf());
252		// Look for collider in this branch.
253		for i in 1..=14 {
254			// Delete it when found, and return successfully.
255			if self.child[i] == id {
256				self.child[i] = Id::none();
257				return Some(());
258			}
259		}
260		// Not here, look in links next.
261		return None;
262	}
263
264	/// Remove a collider from a node.
265	fn remove_collider(&mut self, id: Id) -> Option<()> {
266		if self.is_branch() {
267			self.branch_remove_collider(id)
268		} else {
269			self.leaf_remove_collider(id)
270		}
271	}
272
273	/// Determine which child for a branch point (2)
274	fn which_child2(c: Vector, p: Vector) -> [bool; 3] {
275		[p.x < c.x, p.y < c.y, p.z < c.z]
276	}
277
278	/// Determine which child for a branch bbox, if there is one it fully
279	/// fits into.
280	fn which_child_bbox(c: Vector, mut p: BBox) -> Option<usize> {
281		if p.min.x >= c.x - ::std::f32::EPSILON && p.min.x <= c.x + ::std::f32::EPSILON {
282//			println!("MATCHED minX");
283			p.min.x = p.max.x;
284		}
285		if p.min.y >= c.y - ::std::f32::EPSILON && p.min.y <= c.y + ::std::f32::EPSILON {
286//			println!("MATCHED minY");
287			p.min.y = p.max.y;
288		}
289		if p.min.z >= c.z - ::std::f32::EPSILON && p.min.z <= c.z + ::std::f32::EPSILON {
290//			println!("MATCHED minZ");
291			p.min.z = p.max.z;
292		}
293		if p.max.x >= c.x - ::std::f32::EPSILON && p.max.x <= c.x + ::std::f32::EPSILON {
294//			println!("MATCHED maxX");
295			p.max.x = p.min.x;
296		}
297		if p.max.y >= c.y - ::std::f32::EPSILON && p.max.y <= c.y + ::std::f32::EPSILON {
298//			println!("MATCHED maxY");
299			p.max.y = p.min.y;
300		}
301		if p.max.z >= c.z - ::std::f32::EPSILON && p.max.z <= c.z + ::std::f32::EPSILON {
302//			println!("MATCHED maxZ");
303			p.max.z = p.min.z;
304		}
305
306		let min = Self::which_child2(c, p.min);
307		let max = Self::which_child2(c, p.max);
308
309		if max != min {
310			return None;
311		}
312
313		let a = Some(match (min[0], min[1], min[2]) {
314			(true,  true,  true)  => 0,
315			(true,  true,  false) => 1,
316			(true,  false, true)  => 2,
317			(true,  false, false) => 3,
318			(false, true,  true)  => 4,
319			(false, true,  false) => 5,
320			(false, false, true)  => 6,
321			(false, false, false) => 7,
322		});
323
324//		println!("c {:?} min {:?} max {:?} -> {:?}", c, p.min, p.max, a);
325		a
326	}
327
328	/// Calculate the center of a child node
329	fn child_center(ch: usize, c: Vector, h: f32) -> Vector {
330		match ch {
331			0 => Vector::new(c.x - h, c.y - h, c.z - h),
332			1 => Vector::new(c.x - h, c.y - h, c.z + h),
333			2 => Vector::new(c.x - h, c.y + h, c.z - h),
334			3 => Vector::new(c.x - h, c.y + h, c.z + h),
335			4 => Vector::new(c.x + h, c.y - h, c.z - h),
336			5 => Vector::new(c.x + h, c.y - h, c.z + h),
337			6 => Vector::new(c.x + h, c.y + h, c.z - h),
338			7 => Vector::new(c.x + h, c.y + h, c.z + h),
339			a => panic!("ch must be 0-7, not {}", a),
340		}
341	}
342
343	/// Calculate the bounding box of a child node
344	fn child_bcube(ch: usize, bcube: BCube) -> BCube {
345		assert!(bcube.half_len > 0.1);
346		let half_len = bcube.half_len / 2.0;
347		let center = Node::child_center(ch, bcube.center, half_len);
348		BCube { center: center, half_len: half_len }
349	}
350
351/*	/// Get an array containing the leaf children
352	fn branch_children(&self) -> [u32; 7] {
353		assert!(self.is_leaf());
354
355		[self.child[1], self.child[2], self.child[3], self.child[4],
356			self.child[5], self.child[6]]
357	}*/
358}
359
360impl<T> Octree<T> where T: Collider {
361	/// Create a new octree
362	pub fn new() -> Octree<T> {
363		let o = Octree {
364			colliders: vec![],
365			collider_garbage: vec![],
366			nodes: vec![],
367			garbage: vec![],
368			bcube: BCube::empty(),
369			root: Id::none(),
370			n_colliders: 0,
371		};
372
373		o
374	}
375
376	/// Clear the octree.
377	pub fn clear(&mut self) {
378		*self = Self::new();
379	}
380
381	/// Add a point in the octree
382	pub fn add(&mut self, point: T) -> Id {
383//		println!("ADD BEGIN");
384		// Add to colliders and get the id.
385		let id = if let Some(id) = self.collider_garbage.pop() {
386			unsafe {
387				::std::ptr::copy_nonoverlapping(&point,
388					&mut self.colliders[{ let id: usize = id.into(); id }], 1);
389			}
390			::std::mem::forget(point); // don't drop it, it's moved!
391			id
392		} else {
393			self.colliders.push(point);
394			Id(self.colliders.len() as u32)
395		};
396
397		// Find position in octree for this new collider.
398		match self.n_colliders {
399			0 => self.add_0(id),
400			_ => self.add_n(id),
401		}
402
403		// Increment number of colliders, and return id
404		self.n_colliders += 1;
405
406//		println!("ADD END {:?} to {}", id, self);
407//		println!("ADDED {}", {let i:usize = id.into();i});
408
409		id
410	}
411
412	/// Add a point when empty
413	fn add_0(&mut self, id: Id) {
414		// Number of colliders must be 0
415		assert!(self.n_colliders == 0);
416
417		// Clear the octree
418		self.nodes.clear();
419		self.garbage.clear();
420
421		// Make the root bcube contain the bbox of this first point.
422		self.bcube = self[id].bbox().into();
423
424//		println!("ADD_0 {:?} / {:?}", self.bcube, self[id].bbox());
425
426		// Build the branch and add a collider.
427		let i = self.new_branch();
428		self.nodes[{ let i: usize = i.into(); i }].branch_add_collider(id).unwrap();
429
430		// Set this branch as the root node.
431		self.root = i;
432	}
433
434	/// Add a point when not empty
435	fn add_n(&mut self, id: Id) {
436		// Must have colliders already in the octree.
437		assert!(self.n_colliders > 0);
438		// Get BBox
439		let bbox = self[id].bbox();
440
441		// While the bbox isn't within the root bcube, expand root bcube
442		while !bbox.collide_bcube(self.bcube) {
443			self.grow_root(bbox);
444//			println!("GROW {:?}", self.bcube);
445		}
446
447		// Add id inside the root bcube.
448		let bcube = self.bcube;
449		let root = self.root;
450		self.add_inside(id, root, bcube);
451
452//		println!("{}", self);
453	}
454
455	/// Grow the root node
456	fn grow_root(&mut self, bbox: BBox) {
457		// BBox can't collide with bcube when this function is called.
458		assert!(!bbox.collide_bcube(self.bcube));
459		assert!(self.nodes[{ let a: usize = self.root.into(); a }].is_branch());
460
461		// Get the old bcube center, to see which octant it goes in.
462		let old_bc = self.bcube;
463
464		// Extend bcube to attempt to accomodate for bbox.
465		// This function is limited to growing twice in size.
466		self.bcube.extend(bbox);
467
468		// Create new container branch for old root branch.
469		let ch = Node::which_child_bbox(self.bcube.center, old_bc.to_bbox()).unwrap();
470		let id = self.new_branch();
471		self.nodes[{ let a: usize = id.into(); a }].child[ch] = self.root;
472		self.root = id;
473
474//		println!("Extended: {}", self);
475	}
476
477	/// Add a point within the bounds
478	fn add_inside(&mut self, id: Id, node_id: Id, bcube: BCube) {
479		// Calculate bbox for this id.
480		let bbox = self[id].bbox();
481		// Convert node_id to usize for indexing.
482		let node_id: usize = node_id.into();
483
484		// BBox must collide with bcube when this function is called
485		assert!(bbox.collide_bcube(bcube));
486		// Must be a branch
487		assert!(self.nodes[node_id].is_branch());
488
489		// Attempt to add at root first.  Test is full
490		if self.nodes[node_id].branch_add_collider(id).is_none() {
491			// Attempt to push relative root colliders down the tree
492			for i in 8..=14 {
493				let collider = self.nodes[node_id].child[i];
494				if self.add_down(collider, node_id, bcube) {
495					// If it successfully pushed it the
496					// collider down the octree, remove it
497					// from it's old location.
498					self.nodes[node_id].child[i]
499						= Id::none();
500				}
501			}
502
503			// Attempt to push this collider (id) down the tree
504			if self.add_down(id, node_id, bcube) {
505				return;
506			}
507
508			// Try again, this time link if failed.
509			if self.nodes[node_id].branch_add_collider(id)
510				.is_none() // Is full, still!
511			{
512				let link_id = self.new_leaf();
513				self.nodes[node_id].child[LINK]
514					= link_id;
515			}
516		}
517	}
518
519	/// Move a collider down the tree, return true if it worked.
520	fn add_down(&mut self, id: Id, node_id: usize, bcube: BCube) -> bool {
521		// Calculate bbox for this id.
522		let bbox = self[id].bbox();
523
524		// can be put on a lower level.
525		if let Some(ch) = Node::which_child_bbox(bcube.center, bbox) {
526			let j = self.nodes[node_id].child[ch];
527			let bc = Node::child_bcube(ch, bcube);
528
529			if j.is_some() {
530				// already a branch here, add collider to it.
531				self.add_inside(id, j, bc);
532			} else {
533				// make a branch
534				let k = self.new_branch();
535				// set branch as the correct child
536				self.nodes[node_id].child[ch] = k;
537				// Add the collider
538				self.nodes[{ let k: usize = k.into(); k }]
539					.branch_add_collider(id)
540					.unwrap(); // shouldn't fail.
541			}
542			true
543		} else {
544			false
545		}
546	}
547
548	/// Add a new node
549	fn new_node(&mut self, n: Node) -> Id {
550		if let Some(i) = self.garbage.pop() {
551			let k: usize = i.into();
552			self.nodes[k] = n;
553			k.into()
554		} else {
555			self.nodes.push(n);
556			Id(self.nodes.len() as u32)
557		}
558	}
559
560	/// Add a new leaf node
561	fn new_leaf(&mut self) -> Id {
562		self.new_node(Node::new_leaf())
563	}
564
565	/// Add a new branch node
566	fn new_branch(&mut self) -> Id {
567		self.new_node(Node::new_branch())
568	}
569
570	/// Remove a point from the octree
571	pub fn remove(&mut self, id: Id) -> T {
572//		println!("REMOVE {}", {let i:usize = id.into();i});
573//		println!("REMOVE BEGIN {} from {}", { let a: usize = id.into(); a }, self);
574
575		// Must have colliders already in the octree.
576		assert!(self.n_colliders > 0);
577		// 
578		let bcube = self.bcube;
579		let root = self.root;
580		// Find and remove the collider Id from the octree.
581		let clear = self.remove_inside(id, root, bcube).is_some();
582		// Id is garbage now.
583		self.collider_garbage.push(id);
584		// Shrink root if: 1 branch, no nodes
585		loop {
586			let root: usize = self.root.into();
587			if let Some(ch) = self.nodes[root].branch_is_one() {
588				// Add root to garbage.
589				self.garbage.push(self.root);
590				// Set new root
591				self.root = self.nodes[root].child[ch];
592				//
593				self.bcube = Node::child_bcube(ch, self.bcube);
594			} else {
595				break;
596			}
597		}
598		// Decrement number of colliders
599		self.n_colliders -= 1;
600
601		// Return the memory by copy.
602		let mut ret = unsafe { ::std::mem::uninitialized() };
603
604		unsafe {
605			::std::ptr::copy_nonoverlapping(
606				&self.colliders[{ let id: usize = id.into(); id }], &mut ret, 1);
607		}
608
609		if clear {
610			assert_eq!(self.n_colliders, 0);
611			self.clear();
612		}
613
614//		println!("REMOVED {}", self);
615
616//		println!("REMOVE END");
617
618		ret
619	}
620
621	/// Remove an Id from the octree.
622	fn remove_inside(&mut self, id: Id, node_id: Id, bcube: BCube)
623		-> Option<Id>
624	{
625		// Calculate bbox for this id.
626		let bbox = self[id].bbox();
627		// Get node_id as usize
628		let node_id: usize = node_id.into();
629
630		// BBox must collide with bcube when this function is called
631		assert!(bbox.collide_bcube(bcube));
632		// Must be a branch
633		assert!(self.nodes[node_id].is_branch());
634
635		// Could be found on a lower level.
636//		println!("R-INSIDE {:?} / {:?}", bcube, bbox);
637		if let Some(ch) = Node::which_child_bbox(bcube.center, bbox) {
638//			println!("WCHBBR {}", ch);
639			let j = self.nodes[node_id].child[ch];
640
641			if j.is_some() {
642//				println!("SOM");
643
644				// Yes, there is a branch here, where the Id is!
645				// Remove it from inside this branch.
646				let bcube = Node::child_bcube(ch, bcube);
647
648				if let Some(rm)
649					= self.remove_inside(id, j, bcube)
650				{ // Remove empty branch
651					// Child branch should be the one
652					// removed
653					assert_eq!(j, rm);
654					// Add to garbage.
655					self.garbage.push(rm);
656					// Remove child branch.
657					self.nodes[node_id].child[ch] =
658						Id::none();
659				}
660
661				// If the node is empty, mark for removal.
662				if self.nodes[node_id].is_empty() {
663					Some(node_id.into())
664				} else {
665					None // nothing to be removed.
666				}
667			} else {
668//				println!("SON");
669				// No, we don't have to descend - it's here!
670				self.remove_from_branch(id, node_id)
671			}
672		} else {
673//			println!("NON");
674			// No, we can't descend - it's here!
675			self.remove_from_branch(id, node_id)
676		}
677	}
678
679	/// Remove from branch, including any links that may exist.
680	fn remove_from_branch(&mut self, id: Id, node_id: usize) -> Option<Id> {
681//		println!("RFB {} {}", node_id, {let a:usize=id.into();a});
682
683		// Remove the collider
684		if self.nodes[node_id].remove_collider(id)
685			.is_some() // Found and removed
686		{
687			// If the node is empty, mark for removal.
688			if self.nodes[node_id].is_empty() {
689				return Some(node_id.into());
690			} else {
691				return None;
692			}
693		}
694
695		// Couldn't Find it: Search Link Node
696		let node_id = self.nodes[node_id].link()
697			.unwrap(); // Shouldn't fail if not found yet.
698		let rm = self.remove_from_branch(id, node_id);
699
700		// If link leaf is now empty, remove.
701		if let Some(rm) = rm {
702			// Returned location should match LINK node location.
703			assert_eq!(rm, self.nodes[node_id].child[LINK]);
704			// Add to garbage.
705			self.garbage.push(rm);
706			// Remove Link.
707			self.nodes[node_id].child[LINK] = Id::none();
708		}
709
710		None // Don't remove this node
711	}
712}
713
714impl<T> ::std::ops::Index<Id> for Octree<T> where T: Collider {
715	type Output = T;
716
717	fn index<'a>(&'a self, index: Id) -> &'a T {
718		let index: usize = index.into();
719		&self.colliders[index]
720	}
721}
722
723impl<T> ::std::ops::IndexMut<Id> for Octree<T> where T: Collider {
724	fn index_mut<'a>(&'a mut self, index: Id) -> &'a mut T {
725		let index: usize = index.into();
726		&mut self.colliders[index]
727	}
728}
729
730impl<T> fmt::Display for Octree<T> where T: Collider {
731	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
732		if self.root.is_none() {
733			write!(f, "No Root\n")?;
734		} else {
735			let root: usize = self.root.into();
736			write!(f, "Root {}:{:?}\n", root, self.bcube)?;
737		}
738
739		for i in 0..self.nodes.len() {
740			let id: Id = i.into();
741			if !self.garbage.contains(&id) {
742				writeln!(f, "{}: {}", i, self.nodes[i])?;
743				write!(f, "{}: ", i)?;
744				for j in 8..=14 { // 8
745					let index = self.nodes[i].child[j];
746					if index.is_some() {
747						write!(f, "{:?},", self[index].bbox())?;
748					}
749				}
750				writeln!(f, "")?;
751			}
752		}
753
754		write!(f, "")
755	}
756}
757
758impl<T> fmt::Debug for Octree<T> where T: Collider {
759	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
760		if self.root.is_none() {
761			write!(f, "No Root\n")?;
762		} else {
763			let root: usize = self.root.into();
764			write!(f, "root {}\n", root)?;
765		}
766
767		for i in 0..self.nodes.len() {
768			let id: Id = i.into();
769			if !self.garbage.contains(&id) {
770				write!(f, "{}: {:?}\n", i, self.nodes[i])?;
771			}
772		}
773
774		write!(f, "")
775	}
776}