From 43a0eef5d180409ed4d6c73f4c11d336bcb1baf2 Mon Sep 17 00:00:00 2001 From: Quaternions 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)->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 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 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)->Option<&'a ModelPhysics>{ models.get(self.model as usize) } - pub fn mesh(&self,models:&Vec) -> TreyMesh { - return self.model(models).unwrap().face_mesh(self.face).clone() - } + // pub fn mesh(&self,models:&Vec) -> TreyMesh { + // return self.model(models).unwrap().face_mesh(self.face).clone() + // } pub fn normal(&self,models:&Vec) -> 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 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);