From 43a0eef5d180409ed4d6c73f4c11d336bcb1baf2 Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Wed, 11 Oct 2023 22:09:40 -0700
Subject: [PATCH] implement aabb & bvh

---
 src/aabb.rs    | 104 ++++++++++++++++++++++++-------------------------
 src/bvh.rs     |  10 ++---
 src/integer.rs |  31 ++++++++++++++-
 src/physics.rs |  18 ++++-----
 4 files changed, 94 insertions(+), 69 deletions(-)

diff --git a/src/aabb.rs b/src/aabb.rs
index c027d93..14e7844 100644
--- a/src/aabb.rs
+++ b/src/aabb.rs
@@ -1,3 +1,5 @@
+use crate::integer::Planar64Vec3;
+
 #[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
 pub enum AabbFace{
 	Right,//+X
@@ -8,84 +10,80 @@ pub enum AabbFace{
 	Front,
 }
 #[derive(Clone)]
-pub struct Aabb {
-	pub min: glam::Vec3,
-	pub max: glam::Vec3,
+pub struct Aabb{
+	pub min:Planar64Vec3,
+	pub max:Planar64Vec3,
 }
 
 impl Default for Aabb {
-	fn default() -> Self {
-		Aabb::new()
+	fn default()->Self {
+		Self{min:Planar64Vec3::MAX,max:Planar64Vec3::MIN}
 	}
 }
 
-impl Aabb {
-	const VERTEX_DATA: [glam::Vec3; 8] = [
-		glam::vec3(1., -1., -1.),
-		glam::vec3(1., 1., -1.),
-		glam::vec3(1., 1., 1.),
-		glam::vec3(1., -1., 1.),
-		glam::vec3(-1., -1., 1.),
-		glam::vec3(-1., 1., 1.),
-		glam::vec3(-1., 1., -1.),
-		glam::vec3(-1., -1., -1.),
+impl Aabb{
+	const VERTEX_DATA:[Planar64Vec3;8]=[
+		Planar64Vec3::int( 1,-1,-1),
+		Planar64Vec3::int( 1, 1,-1),
+		Planar64Vec3::int( 1, 1, 1),
+		Planar64Vec3::int( 1,-1, 1),
+		Planar64Vec3::int(-1,-1, 1),
+		Planar64Vec3::int(-1, 1, 1),
+		Planar64Vec3::int(-1, 1,-1),
+		Planar64Vec3::int(-1,-1,-1),
 	];
 
-	pub fn new() -> Self {
-		Self {min: glam::Vec3::INFINITY,max: glam::Vec3::NEG_INFINITY}
-	}
-
-	pub fn grow(&mut self, point:glam::Vec3){
+	pub fn grow(&mut self,point:Planar64Vec3){
 		self.min=self.min.min(point);
 		self.max=self.max.max(point);
 	}
-	pub fn join(&mut self, aabb:&Aabb){
+	pub fn join(&mut self,aabb:&Aabb){
 		self.min=self.min.min(aabb.min);
 		self.max=self.max.max(aabb.max);
 	}
-	pub fn inflate(&mut self, hs:glam::Vec3){
+	pub fn inflate(&mut self,hs:Planar64Vec3){
 		self.min-=hs;
 		self.max+=hs;
 	}
 	pub fn intersects(&self,aabb:&Aabb)->bool{
 		(self.min.cmplt(aabb.max)&aabb.min.cmplt(self.max)).all()
 	}
-	pub fn normal(face:AabbFace) -> glam::Vec3 {
+	pub fn normal(face:AabbFace)->Planar64Vec3{
 		match face {
-			AabbFace::Right => glam::vec3(1.,0.,0.),
-			AabbFace::Top => glam::vec3(0.,1.,0.),
-			AabbFace::Back => glam::vec3(0.,0.,1.),
-			AabbFace::Left => glam::vec3(-1.,0.,0.),
-			AabbFace::Bottom => glam::vec3(0.,-1.,0.),
-			AabbFace::Front => glam::vec3(0.,0.,-1.),
+			AabbFace::Right=>Planar64Vec3::int(1,0,0),
+			AabbFace::Top=>Planar64Vec3::int(0,1,0),
+			AabbFace::Back=>Planar64Vec3::int(0,0,1),
+			AabbFace::Left=>Planar64Vec3::int(-1,0,0),
+			AabbFace::Bottom=>Planar64Vec3::int(0,-1,0),
+			AabbFace::Front=>Planar64Vec3::int(0,0,-1),
 		}
 	}
-	pub fn unit_vertices() -> [glam::Vec3;8] {
+	pub fn unit_vertices()->[Planar64Vec3;8] {
 		return Self::VERTEX_DATA;
 	}
-	pub fn face(&self,face:AabbFace) -> Aabb {
-		let mut aabb=self.clone();
-		//in this implementation face = worldspace aabb face
-		match face {
-			AabbFace::Right => aabb.min.x=aabb.max.x,
-			AabbFace::Top => aabb.min.y=aabb.max.y,
-			AabbFace::Back => aabb.min.z=aabb.max.z,
-			AabbFace::Left => aabb.max.x=aabb.min.x,
-			AabbFace::Bottom => aabb.max.y=aabb.min.y,
-			AabbFace::Front => aabb.max.z=aabb.min.z,
-		}
-		return aabb;
-	}
-	pub fn center(&self)->glam::Vec3{
-		return (self.min+self.max)/2.0
+	// pub fn face(&self,face:AabbFace)->Aabb {
+	// 	let mut aabb=self.clone();
+	// 	//in this implementation face = worldspace aabb face
+	// 	match face {
+	// 		AabbFace::Right => aabb.min.x=aabb.max.x,
+	// 		AabbFace::Top => aabb.min.y=aabb.max.y,
+	// 		AabbFace::Back => aabb.min.z=aabb.max.z,
+	// 		AabbFace::Left => aabb.max.x=aabb.min.x,
+	// 		AabbFace::Bottom => aabb.max.y=aabb.min.y,
+	// 		AabbFace::Front => aabb.max.z=aabb.min.z,
+	// 	}
+	// 	return aabb;
+	// }
+	pub fn center(&self)->Planar64Vec3{
+		return self.min.midpoint(self.max)
 	}
 	//probably use floats for area & volume because we don't care about precision
-	pub fn area_weight(&self)->f32{
-		let d=self.max-self.min;
-		d.x*d.y+d.y*d.z+d.z*d.x
-	}
-	pub fn volume(&self)->f32{
-		let d=self.max-self.min;
-		d.x*d.y*d.z
-	}
+	// pub fn area_weight(&self)->f32{
+	// 	let d=self.max-self.min;
+	// 	d.x*d.y+d.y*d.z+d.z*d.x
+	// }
+	// pub fn volume(&self)->f32{
+	// 	let d=self.max-self.min;
+	// 	d.x*d.y*d.z
+	// }
 }
\ No newline at end of file
diff --git a/src/bvh.rs b/src/bvh.rs
index b79ecc0..4196bd7 100644
--- a/src/bvh.rs
+++ b/src/bvh.rs
@@ -36,7 +36,7 @@ pub fn generate_bvh(boxen:Vec<Aabb>)->BvhNode{
 fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
 	let n=boxen.len();
 	if n<20{
-		let mut aabb=Aabb::new();
+		let mut aabb=Aabb::default();
 		let models=boxen.into_iter().map(|b|{aabb.join(&b.1);b.0 as u32}).collect();
 		BvhNode{
 			children:Vec::new(),
@@ -51,9 +51,9 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
 		for (i,aabb) in boxen.iter(){
 			let center=aabb.center();
 			octant.insert(*i,0);
-			sort_x.push((*i,center.x));
-			sort_y.push((*i,center.y));
-			sort_z.push((*i,center.z));
+			sort_x.push((*i,center.x()));
+			sort_y.push((*i,center.y()));
+			sort_z.push((*i,center.z()));
 		}
 		sort_x.sort_by(|tup0,tup1|tup0.1.partial_cmp(&tup1.1).unwrap());
 		sort_y.sort_by(|tup0,tup1|tup0.1.partial_cmp(&tup1.1).unwrap());
@@ -92,7 +92,7 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
 			};
 			list_list[list_id].push((i,aabb));
 		}
-		let mut aabb=Aabb::new();
+		let mut aabb=Aabb::default();
 		let children=list_list.into_iter().map(|b|{
 			let node=generate_bvh_node(b);
 			aabb.join(&node.aabb);
diff --git a/src/integer.rs b/src/integer.rs
index c6551a7..7a82656 100644
--- a/src/integer.rs
+++ b/src/integer.rs
@@ -228,7 +228,7 @@ pub struct Unit64Mat3{
 
 
 ///[-1.0,1.0] = [-2^32,2^32]
-#[derive(Clone,Copy,Hash,PartialEq,PartialOrd)]
+#[derive(Clone,Copy,Hash,Eq,Ord,PartialEq,PartialOrd)]
 pub struct Planar64(i64);
 impl Planar64{
 	pub const ZERO:Self=Self(0);
@@ -303,7 +303,7 @@ impl std::ops::Div<Planar64> for Planar64{
 
 
 ///[-1.0,1.0] = [-2^32,2^32]
-#[derive(Clone,Copy,Hash)]
+#[derive(Clone,Copy,Hash,Eq,PartialEq)]
 pub struct Planar64Vec3(glam::I64Vec3);
 impl Planar64Vec3{
 	pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO);
@@ -314,6 +314,8 @@ impl Planar64Vec3{
 	pub const NEG_X:Self=Planar64Vec3(glam::I64Vec3::NEG_X);
 	pub const NEG_Y:Self=Planar64Vec3(glam::I64Vec3::NEG_Y);
 	pub const NEG_Z:Self=Planar64Vec3(glam::I64Vec3::NEG_Z);
+	pub const MIN:Self=Planar64Vec3(glam::I64Vec3::MIN);
+	pub const MAX:Self=Planar64Vec3(glam::I64Vec3::MAX);
 	pub fn int(x:i32,y:i32,z:i32)->Self{
 		Self(glam::i64vec3((x as i64)<<32,(y as i64)<<32,(z as i64)<<32))
 	}
@@ -329,6 +331,31 @@ impl Planar64Vec3{
 	pub fn z(&self)->Planar64{
 		Planar64(self.0.z)
 	}
+	#[inline]
+	pub fn min(self,rhs:Self)->Self{
+		Self(glam::i64vec3(
+			self.0.x.min(rhs.0.x),
+			self.0.y.min(rhs.0.y),
+			self.0.z.min(rhs.0.z),
+		))
+	}
+	#[inline]
+	pub fn max(self,rhs:Self)->Self{
+		Self(glam::i64vec3(
+			self.0.x.max(rhs.0.x),
+			self.0.y.max(rhs.0.y),
+			self.0.z.max(rhs.0.z),
+		))
+	}
+	#[inline]
+	pub fn midpoint(self,rhs:Self)->Self{
+		Self((self.0+rhs.0)/2)
+	}
+	#[inline]
+	pub fn cmplt(self,rhs:Self)->glam::BVec3{
+		self.0.cmplt(rhs.0)
+	}
+
 }
 impl Into<glam::Vec3> for Planar64Vec3{
 	fn into(self)->glam::Vec3{
diff --git a/src/physics.rs b/src/physics.rs
index ed524dc..881be82 100644
--- a/src/physics.rs
+++ b/src/physics.rs
@@ -338,7 +338,7 @@ pub struct ModelPhysics {
 
 impl ModelPhysics {
 	fn from_model_transform_attributes(model:&crate::model::IndexedModel,transform:&glam::Affine3A,attributes:PhysicsCollisionAttributes)->Self{
-		let mut aabb=TreyMesh::new();
+		let mut aabb=TreyMesh::default();
 		for indexed_vertex in &model.unique_vertices {
 			aabb.grow(transform.transform_point3(Planar64Vec3::from_array(model.unique_pos[indexed_vertex.pos as usize])));
 		}
@@ -361,9 +361,9 @@ impl ModelPhysics {
 	pub fn mesh(&self) -> &TreyMesh {
 		return &self.mesh;
 	}
-	pub fn face_mesh(&self,face:TreyMeshFace)->TreyMesh{
-		self.mesh.face(face)
-	}
+	// pub fn face_mesh(&self,face:TreyMeshFace)->TreyMesh{
+	// 	self.mesh.face(face)
+	// }
 	pub fn face_normal(&self,face:TreyMeshFace) -> Planar64Vec3 {
 		TreyMesh::normal(face)//this is wrong for scale
 	}
@@ -381,9 +381,9 @@ impl RelativeCollision {
 	pub fn model<'a>(&self,models:&'a Vec<ModelPhysics>)->Option<&'a ModelPhysics>{
 		models.get(self.model as usize)
 	}
-	pub fn mesh(&self,models:&Vec<ModelPhysics>) -> TreyMesh {
-		return self.model(models).unwrap().face_mesh(self.face).clone()
-	}
+	// pub fn mesh(&self,models:&Vec<ModelPhysics>) -> TreyMesh {
+	// 	return self.model(models).unwrap().face_mesh(self.face).clone()
+	// }
 	pub fn normal(&self,models:&Vec<ModelPhysics>) -> Planar64Vec3 {
 		return self.model(models).unwrap().face_normal(self.face)
 	}
@@ -745,7 +745,7 @@ impl PhysicsState {
 		}
 	}
 	fn mesh(&self) -> TreyMesh {
-		let mut aabb=TreyMesh::new();
+		let mut aabb=TreyMesh::default();
 		for vertex in TreyMesh::unit_vertices(){
 			aabb.grow(self.body.position+self.style.hitbox_halfsize*vertex);
 		}
@@ -1038,7 +1038,7 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
 		// 	collector.collect(self.predict_collision_end2(self.time,time_limit,collision_data));
 		// }
 		//check for collision start instructions (against every part in the game with no optimization!!)
-		let mut aabb=crate::aabb::Aabb::new();
+		let mut aabb=crate::aabb::Aabb::default();
 		aabb.grow(self.body.extrapolated_position(self.time));
 		aabb.grow(self.body.extrapolated_position(time_limit));
 		aabb.inflate(self.style.hitbox_halfsize);