implement aabb & bvh

This commit is contained in:
Quaternions 2023-10-11 22:09:40 -07:00
parent 76cd82967a
commit 43a0eef5d1
4 changed files with 94 additions and 69 deletions

View File

@ -1,3 +1,5 @@
use crate::integer::Planar64Vec3;
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)] #[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
pub enum AabbFace{ pub enum AabbFace{
Right,//+X Right,//+X
@ -9,33 +11,29 @@ pub enum AabbFace{
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Aabb{ pub struct Aabb{
pub min: glam::Vec3, pub min:Planar64Vec3,
pub max: glam::Vec3, pub max:Planar64Vec3,
} }
impl Default for Aabb { impl Default for Aabb {
fn default()->Self { fn default()->Self {
Aabb::new() Self{min:Planar64Vec3::MAX,max:Planar64Vec3::MIN}
} }
} }
impl Aabb{ impl Aabb{
const VERTEX_DATA: [glam::Vec3; 8] = [ const VERTEX_DATA:[Planar64Vec3;8]=[
glam::vec3(1., -1., -1.), Planar64Vec3::int( 1,-1,-1),
glam::vec3(1., 1., -1.), Planar64Vec3::int( 1, 1,-1),
glam::vec3(1., 1., 1.), Planar64Vec3::int( 1, 1, 1),
glam::vec3(1., -1., 1.), Planar64Vec3::int( 1,-1, 1),
glam::vec3(-1., -1., 1.), Planar64Vec3::int(-1,-1, 1),
glam::vec3(-1., 1., 1.), Planar64Vec3::int(-1, 1, 1),
glam::vec3(-1., 1., -1.), Planar64Vec3::int(-1, 1,-1),
glam::vec3(-1., -1., -1.), Planar64Vec3::int(-1,-1,-1),
]; ];
pub fn new() -> Self { pub fn grow(&mut self,point:Planar64Vec3){
Self {min: glam::Vec3::INFINITY,max: glam::Vec3::NEG_INFINITY}
}
pub fn grow(&mut self, point:glam::Vec3){
self.min=self.min.min(point); self.min=self.min.min(point);
self.max=self.max.max(point); self.max=self.max.max(point);
} }
@ -43,49 +41,49 @@ impl Aabb {
self.min=self.min.min(aabb.min); self.min=self.min.min(aabb.min);
self.max=self.max.max(aabb.max); 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.min-=hs;
self.max+=hs; self.max+=hs;
} }
pub fn intersects(&self,aabb:&Aabb)->bool{ pub fn intersects(&self,aabb:&Aabb)->bool{
(self.min.cmplt(aabb.max)&aabb.min.cmplt(self.max)).all() (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 { match face {
AabbFace::Right => glam::vec3(1.,0.,0.), AabbFace::Right=>Planar64Vec3::int(1,0,0),
AabbFace::Top => glam::vec3(0.,1.,0.), AabbFace::Top=>Planar64Vec3::int(0,1,0),
AabbFace::Back => glam::vec3(0.,0.,1.), AabbFace::Back=>Planar64Vec3::int(0,0,1),
AabbFace::Left => glam::vec3(-1.,0.,0.), AabbFace::Left=>Planar64Vec3::int(-1,0,0),
AabbFace::Bottom => glam::vec3(0.,-1.,0.), AabbFace::Bottom=>Planar64Vec3::int(0,-1,0),
AabbFace::Front => glam::vec3(0.,0.,-1.), AabbFace::Front=>Planar64Vec3::int(0,0,-1),
} }
} }
pub fn unit_vertices() -> [glam::Vec3;8] { pub fn unit_vertices()->[Planar64Vec3;8] {
return Self::VERTEX_DATA; return Self::VERTEX_DATA;
} }
pub fn face(&self,face:AabbFace) -> Aabb { // pub fn face(&self,face:AabbFace)->Aabb {
let mut aabb=self.clone(); // let mut aabb=self.clone();
//in this implementation face = worldspace aabb face // //in this implementation face = worldspace aabb face
match face { // match face {
AabbFace::Right => aabb.min.x=aabb.max.x, // AabbFace::Right => aabb.min.x=aabb.max.x,
AabbFace::Top => aabb.min.y=aabb.max.y, // AabbFace::Top => aabb.min.y=aabb.max.y,
AabbFace::Back => aabb.min.z=aabb.max.z, // AabbFace::Back => aabb.min.z=aabb.max.z,
AabbFace::Left => aabb.max.x=aabb.min.x, // AabbFace::Left => aabb.max.x=aabb.min.x,
AabbFace::Bottom => aabb.max.y=aabb.min.y, // AabbFace::Bottom => aabb.max.y=aabb.min.y,
AabbFace::Front => aabb.max.z=aabb.min.z, // AabbFace::Front => aabb.max.z=aabb.min.z,
} // }
return aabb; // return aabb;
} // }
pub fn center(&self)->glam::Vec3{ pub fn center(&self)->Planar64Vec3{
return (self.min+self.max)/2.0 return self.min.midpoint(self.max)
} }
//probably use floats for area & volume because we don't care about precision //probably use floats for area & volume because we don't care about precision
pub fn area_weight(&self)->f32{ // pub fn area_weight(&self)->f32{
let d=self.max-self.min; // let d=self.max-self.min;
d.x*d.y+d.y*d.z+d.z*d.x // d.x*d.y+d.y*d.z+d.z*d.x
} // }
pub fn volume(&self)->f32{ // pub fn volume(&self)->f32{
let d=self.max-self.min; // let d=self.max-self.min;
d.x*d.y*d.z // d.x*d.y*d.z
} // }
} }

View File

@ -36,7 +36,7 @@ pub fn generate_bvh(boxen:Vec<Aabb>)->BvhNode{
fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
let n=boxen.len(); let n=boxen.len();
if n<20{ 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(); let models=boxen.into_iter().map(|b|{aabb.join(&b.1);b.0 as u32}).collect();
BvhNode{ BvhNode{
children:Vec::new(), children:Vec::new(),
@ -51,9 +51,9 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
for (i,aabb) in boxen.iter(){ for (i,aabb) in boxen.iter(){
let center=aabb.center(); let center=aabb.center();
octant.insert(*i,0); octant.insert(*i,0);
sort_x.push((*i,center.x)); sort_x.push((*i,center.x()));
sort_y.push((*i,center.y)); sort_y.push((*i,center.y()));
sort_z.push((*i,center.z)); sort_z.push((*i,center.z()));
} }
sort_x.sort_by(|tup0,tup1|tup0.1.partial_cmp(&tup1.1).unwrap()); 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()); 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)); 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 children=list_list.into_iter().map(|b|{
let node=generate_bvh_node(b); let node=generate_bvh_node(b);
aabb.join(&node.aabb); aabb.join(&node.aabb);

View File

@ -228,7 +228,7 @@ pub struct Unit64Mat3{
///[-1.0,1.0] = [-2^32,2^32] ///[-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); pub struct Planar64(i64);
impl Planar64{ impl Planar64{
pub const ZERO:Self=Self(0); 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] ///[-1.0,1.0] = [-2^32,2^32]
#[derive(Clone,Copy,Hash)] #[derive(Clone,Copy,Hash,Eq,PartialEq)]
pub struct Planar64Vec3(glam::I64Vec3); pub struct Planar64Vec3(glam::I64Vec3);
impl Planar64Vec3{ impl Planar64Vec3{
pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO); 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_X:Self=Planar64Vec3(glam::I64Vec3::NEG_X);
pub const NEG_Y:Self=Planar64Vec3(glam::I64Vec3::NEG_Y); pub const NEG_Y:Self=Planar64Vec3(glam::I64Vec3::NEG_Y);
pub const NEG_Z:Self=Planar64Vec3(glam::I64Vec3::NEG_Z); 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{ 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)) 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{ pub fn z(&self)->Planar64{
Planar64(self.0.z) 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{ impl Into<glam::Vec3> for Planar64Vec3{
fn into(self)->glam::Vec3{ fn into(self)->glam::Vec3{

View File

@ -338,7 +338,7 @@ pub struct ModelPhysics {
impl ModelPhysics { impl ModelPhysics {
fn from_model_transform_attributes(model:&crate::model::IndexedModel,transform:&glam::Affine3A,attributes:PhysicsCollisionAttributes)->Self{ 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 { for indexed_vertex in &model.unique_vertices {
aabb.grow(transform.transform_point3(Planar64Vec3::from_array(model.unique_pos[indexed_vertex.pos as usize]))); 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 { pub fn mesh(&self) -> &TreyMesh {
return &self.mesh; return &self.mesh;
} }
pub fn face_mesh(&self,face:TreyMeshFace)->TreyMesh{ // pub fn face_mesh(&self,face:TreyMeshFace)->TreyMesh{
self.mesh.face(face) // self.mesh.face(face)
} // }
pub fn face_normal(&self,face:TreyMeshFace) -> Planar64Vec3 { pub fn face_normal(&self,face:TreyMeshFace) -> Planar64Vec3 {
TreyMesh::normal(face)//this is wrong for scale 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>{ pub fn model<'a>(&self,models:&'a Vec<ModelPhysics>)->Option<&'a ModelPhysics>{
models.get(self.model as usize) models.get(self.model as usize)
} }
pub fn mesh(&self,models:&Vec<ModelPhysics>) -> TreyMesh { // pub fn mesh(&self,models:&Vec<ModelPhysics>) -> TreyMesh {
return self.model(models).unwrap().face_mesh(self.face).clone() // return self.model(models).unwrap().face_mesh(self.face).clone()
} // }
pub fn normal(&self,models:&Vec<ModelPhysics>) -> Planar64Vec3 { pub fn normal(&self,models:&Vec<ModelPhysics>) -> Planar64Vec3 {
return self.model(models).unwrap().face_normal(self.face) return self.model(models).unwrap().face_normal(self.face)
} }
@ -745,7 +745,7 @@ impl PhysicsState {
} }
} }
fn mesh(&self) -> TreyMesh { fn mesh(&self) -> TreyMesh {
let mut aabb=TreyMesh::new(); let mut aabb=TreyMesh::default();
for vertex in TreyMesh::unit_vertices(){ for vertex in TreyMesh::unit_vertices(){
aabb.grow(self.body.position+self.style.hitbox_halfsize*vertex); 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)); // 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!!) //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(self.time));
aabb.grow(self.body.extrapolated_position(time_limit)); aabb.grow(self.body.extrapolated_position(time_limit));
aabb.inflate(self.style.hitbox_halfsize); aabb.inflate(self.style.hitbox_halfsize);