common: Ray
This commit is contained in:
parent
510aef07a8
commit
b0e0bda101
@ -1,4 +1,6 @@
|
|||||||
use strafesnet_common::integer::{self,vec3::{self,Vector3},Fixed,Planar64,Planar64Vec3,Ratio};
|
use strafesnet_common::integer::vec3::{self,Vector3};
|
||||||
|
use strafesnet_common::integer::{Fixed,Planar64Vec3,Ratio};
|
||||||
|
use strafesnet_common::ray::Ray;
|
||||||
|
|
||||||
// This algorithm is based on Lua code
|
// This algorithm is based on Lua code
|
||||||
// written by Trey Reynolds in 2021
|
// written by Trey Reynolds in 2021
|
||||||
@ -12,24 +14,6 @@ type Conts<'a>=arrayvec::ArrayVec<&'a Contact,4>;
|
|||||||
// hack to allow comparing ratios to zero
|
// hack to allow comparing ratios to zero
|
||||||
const RATIO_ZERO:Ratio<Fixed<1,32>,Fixed<1,32>>=Ratio::new(Fixed::ZERO,Fixed::EPSILON);
|
const RATIO_ZERO:Ratio<Fixed<1,32>,Fixed<1,32>>=Ratio::new(Fixed::ZERO,Fixed::EPSILON);
|
||||||
|
|
||||||
struct Ray{
|
|
||||||
origin:Planar64Vec3,
|
|
||||||
direction:Planar64Vec3,
|
|
||||||
}
|
|
||||||
impl Ray{
|
|
||||||
fn extrapolate<Num,Den,N1,T1>(&self,t:Ratio<Num,Den>)->Planar64Vec3
|
|
||||||
where
|
|
||||||
Num:Copy,
|
|
||||||
Den:Copy,
|
|
||||||
Num:core::ops::Mul<Planar64,Output=N1>,
|
|
||||||
Planar64:core::ops::Mul<Den,Output=N1>,
|
|
||||||
N1:integer::Divide<Den,Output=T1>,
|
|
||||||
T1:integer::Fix<Planar64>,
|
|
||||||
{
|
|
||||||
self.origin+self.direction.map(|elem|(t*elem).divide().fix())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Information about a contact restriction
|
/// Information about a contact restriction
|
||||||
pub struct Contact{
|
pub struct Contact{
|
||||||
pub position:Planar64Vec3,
|
pub position:Planar64Vec3,
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use fixed_wide::fixed::Fixed;
|
|
||||||
use linear_ops::types::Vector3;
|
|
||||||
|
|
||||||
use crate::aabb::Aabb;
|
use crate::aabb::Aabb;
|
||||||
use crate::integer::{Ratio,Planar64,Planar64Vec3};
|
use crate::ray::Ray;
|
||||||
|
use crate::integer::{Ratio,Planar64};
|
||||||
use crate::instruction::{InstructionCollector,TimedInstruction};
|
use crate::instruction::{InstructionCollector,TimedInstruction};
|
||||||
|
|
||||||
//da algaritum
|
//da algaritum
|
||||||
@ -18,103 +16,94 @@ use crate::instruction::{InstructionCollector,TimedInstruction};
|
|||||||
//sort the centerpoints on each axis (3 lists)
|
//sort the centerpoints on each axis (3 lists)
|
||||||
//bv is put into octant based on whether it is upper or lower in each list
|
//bv is put into octant based on whether it is upper or lower in each list
|
||||||
|
|
||||||
pub struct Ray{
|
|
||||||
pub origin:Planar64Vec3,
|
pub fn intersect_aabb(ray:&Ray,aabb:&Aabb)->Option<Ratio<Planar64,Planar64>>{
|
||||||
pub direction:Planar64Vec3,
|
// n.(o+d*t)==n.p
|
||||||
}
|
// n.o + n.d * t == n.p
|
||||||
impl Ray{
|
// t == (n.p - n.o)/n.d
|
||||||
pub fn extrapolate(&self,t:Ratio<Planar64,Planar64>)->Ratio<Vector3<Fixed<2,64>>,Planar64>{
|
let mut hit=None;
|
||||||
// o+d*t
|
match ray.direction.x.cmp(&Planar64::ZERO){
|
||||||
(self.origin*t.den+self.direction*t.num)/t.den
|
Ordering::Less=>{
|
||||||
|
let rel_min=aabb.min()-ray.origin;
|
||||||
|
let rel_max=aabb.max()-ray.origin;
|
||||||
|
let dy=rel_max.x*ray.direction.y;
|
||||||
|
let dz=rel_max.x*ray.direction.z;
|
||||||
|
// x is negative, so inequalities are flipped
|
||||||
|
if rel_min.y*ray.direction.x>dy&&dy>rel_max.y*ray.direction.x
|
||||||
|
&&rel_min.z*ray.direction.x>dz&&dz>rel_max.z*ray.direction.x{
|
||||||
|
let t=rel_max.x/ray.direction.x;
|
||||||
|
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ordering::Equal=>(),
|
||||||
|
Ordering::Greater=>{
|
||||||
|
let rel_min=aabb.min()-ray.origin;
|
||||||
|
let rel_max=aabb.max()-ray.origin;
|
||||||
|
let dy=rel_min.x*ray.direction.y;
|
||||||
|
let dz=rel_min.x*ray.direction.z;
|
||||||
|
// x is positive, so inequalities are normal
|
||||||
|
if rel_min.y*ray.direction.x<dy&&dy<rel_max.y*ray.direction.x
|
||||||
|
&&rel_min.z*ray.direction.x<dz&&dz<rel_max.z*ray.direction.x{
|
||||||
|
let t=rel_min.x/ray.direction.x;
|
||||||
|
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
pub fn intersect_aabb(&self,aabb:&Aabb)->Option<Ratio<Planar64,Planar64>>{
|
match ray.direction.z.cmp(&Planar64::ZERO){
|
||||||
// n.(o+d*t)==n.p
|
Ordering::Less=>{
|
||||||
// n.o + n.d * t == n.p
|
let rel_min=aabb.min()-ray.origin;
|
||||||
// t == (n.p - n.o)/n.d
|
let rel_max=aabb.max()-ray.origin;
|
||||||
let mut hit=None;
|
let dx=rel_max.z*ray.direction.x;
|
||||||
match self.direction.x.cmp(&Planar64::ZERO){
|
let dy=rel_max.z*ray.direction.y;
|
||||||
Ordering::Less=>{
|
// z is negative, so inequalities are flipped
|
||||||
let rel_min=aabb.min()-self.origin;
|
if rel_min.x*ray.direction.z>dx&&dx>rel_max.x*ray.direction.z
|
||||||
let rel_max=aabb.max()-self.origin;
|
&&rel_min.y*ray.direction.z>dy&&dy>rel_max.y*ray.direction.z{
|
||||||
let dy=rel_max.x*self.direction.y;
|
let t=rel_max.z/ray.direction.z;
|
||||||
let dz=rel_max.x*self.direction.z;
|
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
||||||
// x is negative, so inequalities are flipped
|
}
|
||||||
if rel_min.y*self.direction.x>dy&&dy>rel_max.y*self.direction.x
|
},
|
||||||
&&rel_min.z*self.direction.x>dz&&dz>rel_max.z*self.direction.x{
|
Ordering::Equal=>(),
|
||||||
let t=rel_max.x/self.direction.x;
|
Ordering::Greater=>{
|
||||||
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
let rel_min=aabb.min()-ray.origin;
|
||||||
}
|
let rel_max=aabb.max()-ray.origin;
|
||||||
},
|
let dx=rel_min.z*ray.direction.x;
|
||||||
Ordering::Equal=>(),
|
let dy=rel_min.z*ray.direction.y;
|
||||||
Ordering::Greater=>{
|
// z is positive, so inequalities are normal
|
||||||
let rel_min=aabb.min()-self.origin;
|
if rel_min.x*ray.direction.z<dx&&dx<rel_max.x*ray.direction.z
|
||||||
let rel_max=aabb.max()-self.origin;
|
&&rel_min.y*ray.direction.z<dy&&dy<rel_max.y*ray.direction.z{
|
||||||
let dy=rel_min.x*self.direction.y;
|
let t=rel_min.z/ray.direction.z;
|
||||||
let dz=rel_min.x*self.direction.z;
|
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
||||||
// x is positive, so inequalities are normal
|
}
|
||||||
if rel_min.y*self.direction.x<dy&&dy<rel_max.y*self.direction.x
|
},
|
||||||
&&rel_min.z*self.direction.x<dz&&dz<rel_max.z*self.direction.x{
|
|
||||||
let t=rel_min.x/self.direction.x;
|
|
||||||
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
match self.direction.z.cmp(&Planar64::ZERO){
|
|
||||||
Ordering::Less=>{
|
|
||||||
let rel_min=aabb.min()-self.origin;
|
|
||||||
let rel_max=aabb.max()-self.origin;
|
|
||||||
let dx=rel_max.z*self.direction.x;
|
|
||||||
let dy=rel_max.z*self.direction.y;
|
|
||||||
// z is negative, so inequalities are flipped
|
|
||||||
if rel_min.x*self.direction.z>dx&&dx>rel_max.x*self.direction.z
|
|
||||||
&&rel_min.y*self.direction.z>dy&&dy>rel_max.y*self.direction.z{
|
|
||||||
let t=rel_max.z/self.direction.z;
|
|
||||||
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ordering::Equal=>(),
|
|
||||||
Ordering::Greater=>{
|
|
||||||
let rel_min=aabb.min()-self.origin;
|
|
||||||
let rel_max=aabb.max()-self.origin;
|
|
||||||
let dx=rel_min.z*self.direction.x;
|
|
||||||
let dy=rel_min.z*self.direction.y;
|
|
||||||
// z is positive, so inequalities are normal
|
|
||||||
if rel_min.x*self.direction.z<dx&&dx<rel_max.x*self.direction.z
|
|
||||||
&&rel_min.y*self.direction.z<dy&&dy<rel_max.y*self.direction.z{
|
|
||||||
let t=rel_min.z/self.direction.z;
|
|
||||||
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
match self.direction.y.cmp(&Planar64::ZERO){
|
|
||||||
Ordering::Less=>{
|
|
||||||
let rel_min=aabb.min()-self.origin;
|
|
||||||
let rel_max=aabb.max()-self.origin;
|
|
||||||
let dz=rel_max.y*self.direction.z;
|
|
||||||
let dx=rel_max.y*self.direction.x;
|
|
||||||
// y is negative, so inequalities are flipped
|
|
||||||
if rel_min.z*self.direction.y>dz&&dz>rel_max.z*self.direction.y
|
|
||||||
&&rel_min.x*self.direction.y>dx&&dx>rel_max.x*self.direction.y{
|
|
||||||
let t=rel_max.y/self.direction.y;
|
|
||||||
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Ordering::Equal=>(),
|
|
||||||
Ordering::Greater=>{
|
|
||||||
let rel_min=aabb.min()-self.origin;
|
|
||||||
let rel_max=aabb.max()-self.origin;
|
|
||||||
let dz=rel_min.y*self.direction.z;
|
|
||||||
let dx=rel_min.y*self.direction.x;
|
|
||||||
// y is positive, so inequalities are normal
|
|
||||||
if rel_min.z*self.direction.y<dz&&dz<rel_max.z*self.direction.y
|
|
||||||
&&rel_min.x*self.direction.y<dx&&dx<rel_max.x*self.direction.y{
|
|
||||||
let t=rel_min.y/self.direction.y;
|
|
||||||
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
hit
|
|
||||||
}
|
}
|
||||||
|
match ray.direction.y.cmp(&Planar64::ZERO){
|
||||||
|
Ordering::Less=>{
|
||||||
|
let rel_min=aabb.min()-ray.origin;
|
||||||
|
let rel_max=aabb.max()-ray.origin;
|
||||||
|
let dz=rel_max.y*ray.direction.z;
|
||||||
|
let dx=rel_max.y*ray.direction.x;
|
||||||
|
// y is negative, so inequalities are flipped
|
||||||
|
if rel_min.z*ray.direction.y>dz&&dz>rel_max.z*ray.direction.y
|
||||||
|
&&rel_min.x*ray.direction.y>dx&&dx>rel_max.x*ray.direction.y{
|
||||||
|
let t=rel_max.y/ray.direction.y;
|
||||||
|
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ordering::Equal=>(),
|
||||||
|
Ordering::Greater=>{
|
||||||
|
let rel_min=aabb.min()-ray.origin;
|
||||||
|
let rel_max=aabb.max()-ray.origin;
|
||||||
|
let dz=rel_min.y*ray.direction.z;
|
||||||
|
let dx=rel_min.y*ray.direction.x;
|
||||||
|
// y is positive, so inequalities are normal
|
||||||
|
if rel_min.z*ray.direction.y<dz&&dz<rel_max.z*ray.direction.y
|
||||||
|
&&rel_min.x*ray.direction.y<dx&&dx<rel_max.x*ray.direction.y{
|
||||||
|
let t=rel_min.y/ray.direction.y;
|
||||||
|
hit=Some(hit.map_or(t,|best_t|t.min(best_t)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
hit
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RecursiveContent<N,L>{
|
pub enum RecursiveContent<N,L>{
|
||||||
@ -171,7 +160,7 @@ impl<L> BvhNode<L>{
|
|||||||
child.populate_nodes(collector,nodes,ray,start_time,f);
|
child.populate_nodes(collector,nodes,ray,start_time,f);
|
||||||
}else{
|
}else{
|
||||||
// Am I an upcoming superstar?
|
// Am I an upcoming superstar?
|
||||||
if let Some(t)=ray.intersect_aabb(&child.aabb){
|
if let Some(t)=intersect_aabb(ray,&child.aabb){
|
||||||
if start_time.lt_ratio(t)&&t.lt_ratio(collector.time()){
|
if start_time.lt_ratio(t)&&t.lt_ratio(collector.time()){
|
||||||
nodes.insert(t,child);
|
nodes.insert(t,child);
|
||||||
}
|
}
|
||||||
@ -212,7 +201,7 @@ impl<L> BvhNode<L>{
|
|||||||
// break open the node and predict collisions with the child nodes
|
// break open the node and predict collisions with the child nodes
|
||||||
RecursiveContent::Branch(children)=>for child in children{
|
RecursiveContent::Branch(children)=>for child in children{
|
||||||
// Am I an upcoming superstar?
|
// Am I an upcoming superstar?
|
||||||
if let Some(t)=ray.intersect_aabb(&child.aabb){
|
if let Some(t)=intersect_aabb(ray,&child.aabb){
|
||||||
if t<collector.time(){
|
if t<collector.time(){
|
||||||
nodes.insert(t,child);
|
nodes.insert(t,child);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod bvh;
|
pub mod bvh;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
|
pub mod ray;
|
||||||
pub mod run;
|
pub mod run;
|
||||||
pub mod aabb;
|
pub mod aabb;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
|
20
lib/common/src/ray.rs
Normal file
20
lib/common/src/ray.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use ratio_ops::ratio::Ratio;
|
||||||
|
use crate::integer::{self,Planar64,Planar64Vec3};
|
||||||
|
|
||||||
|
pub struct Ray{
|
||||||
|
pub origin:Planar64Vec3,
|
||||||
|
pub direction:Planar64Vec3,
|
||||||
|
}
|
||||||
|
impl Ray{
|
||||||
|
pub fn extrapolate<Num,Den,N1,T1>(&self,t:Ratio<Num,Den>)->Planar64Vec3
|
||||||
|
where
|
||||||
|
Num:Copy,
|
||||||
|
Den:Copy,
|
||||||
|
Num:core::ops::Mul<Planar64,Output=N1>,
|
||||||
|
Planar64:core::ops::Mul<Den,Output=N1>,
|
||||||
|
N1:integer::Divide<Den,Output=T1>,
|
||||||
|
T1:integer::Fix<Planar64>,
|
||||||
|
{
|
||||||
|
self.origin+self.direction.map(|elem|(t*elem).divide().fix())
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user