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)]
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
// }
}

View File

@ -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);

View File

@ -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{

View File

@ -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);