Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
81f6a405cf | |||
522f9f6668 | |||
d02df2f83e | |||
ed78807a9f | |||
b419f2a321 | |||
92e333fcbe |
68
Cargo.lock
generated
68
Cargo.lock
generated
@ -4,9 +4,9 @@ version = 3
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.4"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
@ -15,10 +15,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glam"
|
name = "bnum"
|
||||||
version = "0.28.0"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
|
checksum = "50202def95bf36cb7d1d7a7962cea1c36a3f8ad42425e5d2b71d7acb8041b5b8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixed_wide"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||||
|
checksum = "d9c2cf115b3785ede870fada07e8b1aeba3378345b4ca86fe3c772ecabc05c0f"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"bnum",
|
||||||
|
"paste",
|
||||||
|
"ratio_ops",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.29.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c28091a37a5d09b555cb6628fd954da299b536433834f5b8e59eba78e0cbbf8a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "id"
|
name = "id"
|
||||||
@ -31,6 +49,23 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linear_ops"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||||
|
checksum = "b2e6977ac24f47086d8a7a2d4ae1c720e86dfdc8407cf5e34c18bfa01053c456"
|
||||||
|
dependencies = [
|
||||||
|
"fixed_wide",
|
||||||
|
"paste",
|
||||||
|
"ratio_ops",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
@ -42,28 +77,37 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.36"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ratio_ops"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||||
|
checksum = "01239195d6afe0509e7e3511b716c0540251dfe7ece0a9a5a27116afb766c42c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strafesnet_common"
|
name = "strafesnet_common"
|
||||||
version = "0.4.1"
|
version = "0.5.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"fixed_wide",
|
||||||
"glam",
|
"glam",
|
||||||
"id",
|
"id",
|
||||||
|
"linear_ops",
|
||||||
|
"ratio_ops",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.72"
|
version = "2.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -72,6 +116,6 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "strafesnet_common"
|
name = "strafesnet_common"
|
||||||
version = "0.4.1"
|
version = "0.5.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://git.itzana.me/StrafesNET/common"
|
repository = "https://git.itzana.me/StrafesNET/common"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
@ -12,5 +12,8 @@ authors = ["Rhys Lloyd <krakow20@gmail.com>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
arrayvec = "0.7.4"
|
arrayvec = "0.7.4"
|
||||||
bitflags = "2.6.0"
|
bitflags = "2.6.0"
|
||||||
glam = "0.28.0"
|
fixed_wide = { version = "0.1.1", registry = "strafesnet", features = ["deferred-division","zeroes","wide-mul"] }
|
||||||
|
linear_ops = { version = "0.1.0", registry = "strafesnet", features = ["deferred-division","named-fields"] }
|
||||||
|
ratio_ops = { version = "0.1.0", registry = "strafesnet" }
|
||||||
|
glam = "0.29.0"
|
||||||
id = { version = "0.1.0", registry = "strafesnet" }
|
id = { version = "0.1.0", registry = "strafesnet" }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::integer::Planar64Vec3;
|
use crate::integer::{vec3,Planar64Vec3};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Aabb{
|
pub struct Aabb{
|
||||||
@ -8,7 +8,7 @@ pub struct Aabb{
|
|||||||
|
|
||||||
impl Default for Aabb{
|
impl Default for Aabb{
|
||||||
fn default()->Self{
|
fn default()->Self{
|
||||||
Self{min:Planar64Vec3::MAX,max:Planar64Vec3::MIN}
|
Self{min:vec3::MAX,max:vec3::MIN}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,13 +35,14 @@ impl Aabb{
|
|||||||
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()
|
let bvec=self.min.lt(aabb.max)&aabb.min.lt(self.max);
|
||||||
|
bvec.all()
|
||||||
}
|
}
|
||||||
pub fn size(&self)->Planar64Vec3{
|
pub fn size(&self)->Planar64Vec3{
|
||||||
self.max-self.min
|
self.max-self.min
|
||||||
}
|
}
|
||||||
pub fn center(&self)->Planar64Vec3{
|
pub fn center(&self)->Planar64Vec3{
|
||||||
self.min.midpoint(self.max)
|
self.min+(self.max-self.min)>>1
|
||||||
}
|
}
|
||||||
//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{
|
||||||
|
@ -126,9 +126,9 @@ fn generate_bvh_node<T>(boxen:Vec<(T,Aabb)>,force:bool)->BvhNode<T>{
|
|||||||
let mut sort_z=Vec::with_capacity(n);
|
let mut sort_z=Vec::with_capacity(n);
|
||||||
for (i,(_,aabb)) in boxen.iter().enumerate(){
|
for (i,(_,aabb)) in boxen.iter().enumerate(){
|
||||||
let center=aabb.center();
|
let center=aabb.center();
|
||||||
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.cmp(&tup1.1));
|
sort_x.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
||||||
sort_y.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
sort_y.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
||||||
|
@ -38,10 +38,11 @@ impl Booster{
|
|||||||
pub fn boost(&self,velocity:Planar64Vec3)->Planar64Vec3{
|
pub fn boost(&self,velocity:Planar64Vec3)->Planar64Vec3{
|
||||||
match self{
|
match self{
|
||||||
&Booster::Velocity(boost_velocity)=>velocity+boost_velocity,
|
&Booster::Velocity(boost_velocity)=>velocity+boost_velocity,
|
||||||
&Booster::Energy{direction,energy}=>{
|
&Booster::Energy{..}=>{
|
||||||
let d=direction.dot(velocity);
|
todo!()
|
||||||
|
//let d=direction.dot(velocity);
|
||||||
//TODO: think about negative
|
//TODO: think about negative
|
||||||
velocity+direction.with_length((d*d+energy).sqrt()-d)
|
//velocity+direction.with_length((d*d+energy).sqrt()-d)
|
||||||
},
|
},
|
||||||
Booster::AirTime(_)=>todo!(),
|
Booster::AirTime(_)=>todo!(),
|
||||||
Booster::Height(_)=>todo!(),
|
Booster::Height(_)=>todo!(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const VALVE_SCALE:Planar64=Planar64::raw(1<<28);// 1/16
|
const VALVE_SCALE:Planar64=Planar64::raw(1<<28);// 1/16
|
||||||
|
|
||||||
use crate::integer::{Time,Ratio64,Planar64,Planar64Vec3};
|
use crate::integer::{int,vec3::int as int3,Time,Ratio64,Planar64,Planar64Vec3};
|
||||||
use crate::controls_bitflag::Controls;
|
use crate::controls_bitflag::Controls;
|
||||||
|
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
@ -65,19 +65,21 @@ impl JumpImpulse{
|
|||||||
mass:Planar64,
|
mass:Planar64,
|
||||||
)->Planar64Vec3{
|
)->Planar64Vec3{
|
||||||
match self{
|
match self{
|
||||||
&JumpImpulse::Time(time)=>velocity-*gravity*time,
|
&JumpImpulse::Time(time)=>velocity-(*gravity*time).map(|t|t.divide().fix_1()),
|
||||||
&JumpImpulse::Height(height)=>{
|
&JumpImpulse::Height(height)=>{
|
||||||
//height==-v.y*v.y/(2*g.y);
|
//height==-v.y*v.y/(2*g.y);
|
||||||
//use energy to determine max height
|
//use energy to determine max height
|
||||||
let g=gravity.length();
|
let gg=gravity.length_squared();
|
||||||
let v_g=gravity.dot(velocity)/g;
|
let g=gg.sqrt().fix_1();
|
||||||
|
let v_g=gravity.dot(velocity);
|
||||||
//do it backwards
|
//do it backwards
|
||||||
velocity-gravity.with_length((v_g*v_g+height*g*2).sqrt()+v_g)
|
let radicand=v_g*v_g+(g*height*2).fix_4();
|
||||||
|
velocity-(*gravity*(radicand.sqrt().fix_2()+v_g)/gg).divide().fix_1()
|
||||||
},
|
},
|
||||||
&JumpImpulse::Linear(jump_speed)=>velocity+jump_dir.with_length(jump_speed),
|
&JumpImpulse::Linear(jump_speed)=>velocity+(jump_dir*jump_speed/jump_dir.length()).divide().fix_1(),
|
||||||
&JumpImpulse::Energy(energy)=>{
|
&JumpImpulse::Energy(energy)=>{
|
||||||
//calculate energy
|
//calculate energy
|
||||||
let e=gravity.dot(velocity);
|
//let e=gravity.dot(velocity);
|
||||||
//add
|
//add
|
||||||
//you get the idea
|
//you get the idea
|
||||||
todo!()
|
todo!()
|
||||||
@ -88,10 +90,10 @@ impl JumpImpulse{
|
|||||||
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
|
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
|
||||||
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
|
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
|
||||||
match self{
|
match self{
|
||||||
&JumpImpulse::Time(time)=>gravity.length()*(time/2),
|
&JumpImpulse::Time(time)=>(gravity.length().fix_1()*time/2).divide().fix_1(),
|
||||||
&JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt(),
|
&JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt().fix_1(),
|
||||||
&JumpImpulse::Linear(deltav)=>deltav,
|
&JumpImpulse::Linear(deltav)=>deltav,
|
||||||
&JumpImpulse::Energy(energy)=>(energy*2/mass).sqrt(),
|
&JumpImpulse::Energy(energy)=>(energy.sqrt()*2/mass.sqrt()).divide().fix_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,9 +125,10 @@ impl JumpSettings{
|
|||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
let j=boost_vel.dot(jump_dir);
|
let j=boost_vel.dot(jump_dir);
|
||||||
if j<jump_speed{
|
let js=jump_speed.fix_2();
|
||||||
|
if j<js{
|
||||||
//weak booster: just do a regular jump
|
//weak booster: just do a regular jump
|
||||||
boost_vel+jump_dir.with_length(jump_speed-j)
|
boost_vel+jump_dir.with_length(js-j).divide().fix_1()
|
||||||
}else{
|
}else{
|
||||||
//activate booster normally, jump does nothing
|
//activate booster normally, jump does nothing
|
||||||
boost_vel
|
boost_vel
|
||||||
@ -138,12 +141,13 @@ impl JumpSettings{
|
|||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
let j=boost_vel.dot(jump_dir);
|
let j=boost_vel.dot(jump_dir);
|
||||||
if j<jump_speed{
|
let js=jump_speed.fix_2();
|
||||||
|
if j<js{
|
||||||
//speed in direction of jump cannot be lower than amount
|
//speed in direction of jump cannot be lower than amount
|
||||||
boost_vel+jump_dir.with_length(jump_speed-j)
|
boost_vel+jump_dir.with_length(js-j).divide().fix_1()
|
||||||
}else{
|
}else{
|
||||||
//boost and jump add together
|
//boost and jump add together
|
||||||
boost_vel+jump_dir.with_length(jump_speed)
|
boost_vel+jump_dir.with_length(js).divide().fix_1()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(false,JumpCalculation::Max)=>{
|
(false,JumpCalculation::Max)=>{
|
||||||
@ -154,9 +158,10 @@ impl JumpSettings{
|
|||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
let boost_dot=boost_vel.dot(jump_dir);
|
let boost_dot=boost_vel.dot(jump_dir);
|
||||||
if boost_dot<jump_speed{
|
let js=jump_speed.fix_2();
|
||||||
|
if boost_dot<js{
|
||||||
//weak boost is extended to jump speed
|
//weak boost is extended to jump speed
|
||||||
boost_vel+jump_dir.with_length(jump_speed-boost_dot)
|
boost_vel+jump_dir.with_length(js-boost_dot).divide().fix_1()
|
||||||
}else{
|
}else{
|
||||||
//activate booster normally, jump does nothing
|
//activate booster normally, jump does nothing
|
||||||
boost_vel
|
boost_vel
|
||||||
@ -168,7 +173,7 @@ impl JumpSettings{
|
|||||||
Some(booster)=>booster.boost(rel_velocity),
|
Some(booster)=>booster.boost(rel_velocity),
|
||||||
None=>rel_velocity,
|
None=>rel_velocity,
|
||||||
};
|
};
|
||||||
boost_vel+jump_dir.with_length(jump_speed)
|
boost_vel+jump_dir.with_length(jump_speed).divide().fix_1()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,8 +266,9 @@ pub struct StrafeSettings{
|
|||||||
impl StrafeSettings{
|
impl StrafeSettings{
|
||||||
pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option<Planar64Vec3>{
|
pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option<Planar64Vec3>{
|
||||||
let d=velocity.dot(control_dir);
|
let d=velocity.dot(control_dir);
|
||||||
match d<self.mv{
|
let mv=self.mv.fix_2();
|
||||||
true=>Some(velocity+control_dir*self.air_accel_limit.map_or(self.mv-d,|limit|limit.min(self.mv-d))),
|
match d<mv{
|
||||||
|
true=>Some(velocity+(control_dir*self.air_accel_limit.map_or(mv-d,|limit|limit.fix_2().min(mv-d))).fix_1()),
|
||||||
false=>None,
|
false=>None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,7 +289,7 @@ pub struct PropulsionSettings{
|
|||||||
}
|
}
|
||||||
impl PropulsionSettings{
|
impl PropulsionSettings{
|
||||||
pub fn acceleration(&self,control_dir:Planar64Vec3)->Planar64Vec3{
|
pub fn acceleration(&self,control_dir:Planar64Vec3)->Planar64Vec3{
|
||||||
control_dir*self.magnitude
|
(control_dir*self.magnitude).fix_1()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,38 +309,40 @@ pub struct WalkSettings{
|
|||||||
impl WalkSettings{
|
impl WalkSettings{
|
||||||
pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
|
pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
|
||||||
//TODO: fallible walk accel
|
//TODO: fallible walk accel
|
||||||
let diff_len=target_diff.length();
|
let diff_len=target_diff.length().fix_1();
|
||||||
let friction=if diff_len<self.accelerate.topspeed{
|
let friction=if diff_len<self.accelerate.topspeed{
|
||||||
self.static_friction
|
self.static_friction
|
||||||
}else{
|
}else{
|
||||||
self.kinetic_friction
|
self.kinetic_friction
|
||||||
};
|
};
|
||||||
self.accelerate.accel.min(-Planar64Vec3::Y.dot(gravity)*friction)
|
self.accelerate.accel.min((-gravity.y*friction).fix_1())
|
||||||
}
|
}
|
||||||
pub fn get_walk_target_velocity(&self,control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
pub fn get_walk_target_velocity(&self,control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
||||||
if control_dir==Planar64Vec3::ZERO{
|
if control_dir==crate::integer::vec3::ZERO{
|
||||||
return control_dir;
|
return control_dir;
|
||||||
}
|
}
|
||||||
let n=normal.length();
|
let nn=normal.length_squared();
|
||||||
let m=control_dir.length();
|
let mm=control_dir.length_squared();
|
||||||
let d=normal.dot(control_dir)/m;
|
let nnmm=nn*mm;
|
||||||
if d<n{
|
let d=normal.dot(control_dir);
|
||||||
|
let dd=d*d;
|
||||||
|
if dd<nnmm{
|
||||||
let cr=normal.cross(control_dir);
|
let cr=normal.cross(control_dir);
|
||||||
if cr==Planar64Vec3::ZERO{
|
if cr==crate::integer::vec3::ZERO_2{
|
||||||
Planar64Vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
}else{
|
}else{
|
||||||
cr.cross(normal)*(self.accelerate.topspeed/(n*(n*n-d*d).sqrt()*m))
|
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().fix_1()
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
Planar64Vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn is_slope_walkable(&self,normal:Planar64Vec3,up:Planar64Vec3)->bool{
|
pub fn is_slope_walkable(&self,normal:Planar64Vec3,up:Planar64Vec3)->bool{
|
||||||
//normal is not guaranteed to be unit length
|
//normal is not guaranteed to be unit length
|
||||||
let ny=normal.dot(up);
|
let ny=normal.dot(up);
|
||||||
let h=normal.length();
|
let h=normal.length().fix_1();
|
||||||
//remember this is a normal vector
|
//remember this is a normal vector
|
||||||
Planar64::ZERO<ny&&h*self.surf_dot<ny
|
ny.is_positive()&&h*self.surf_dot<ny
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,32 +359,35 @@ impl LadderSettings{
|
|||||||
self.accelerate.accel
|
self.accelerate.accel
|
||||||
}
|
}
|
||||||
pub fn get_ladder_target_velocity(&self,mut control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
pub fn get_ladder_target_velocity(&self,mut control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
||||||
if control_dir==Planar64Vec3::ZERO{
|
if control_dir==crate::integer::vec3::ZERO{
|
||||||
return control_dir;
|
return control_dir;
|
||||||
}
|
}
|
||||||
let n=normal.length();
|
let nn=normal.length_squared();
|
||||||
let m=control_dir.length();
|
let mm=control_dir.length_squared();
|
||||||
let mut d=normal.dot(control_dir)/m;
|
let nnmm=nn*mm;
|
||||||
if d< -self.dot*n{
|
let d=normal.dot(control_dir);
|
||||||
control_dir=Planar64Vec3::Y*m;
|
let mut dd=d*d;
|
||||||
d=normal.y();
|
if (self.dot*self.dot*nnmm).fix_4()<dd{
|
||||||
}else if self.dot*n<d{
|
if d.is_negative(){
|
||||||
control_dir=Planar64Vec3::NEG_Y*m;
|
control_dir=Planar64Vec3::new([Planar64::ZERO,mm.fix_1(),Planar64::ZERO]);
|
||||||
d=-normal.y();
|
}else{
|
||||||
|
control_dir=Planar64Vec3::new([Planar64::ZERO,-mm.fix_1(),Planar64::ZERO]);
|
||||||
|
}
|
||||||
|
dd=(normal.y*normal.y).fix_4();
|
||||||
}
|
}
|
||||||
//n=d if you are standing on top of a ladder and press E.
|
//n=d if you are standing on top of a ladder and press E.
|
||||||
//two fixes:
|
//two fixes:
|
||||||
//- ladder movement is not allowed on walkable surfaces
|
//- ladder movement is not allowed on walkable surfaces
|
||||||
//- fix the underlying issue
|
//- fix the underlying issue
|
||||||
if d.get().unsigned_abs()<n.get().unsigned_abs(){
|
if dd<nnmm{
|
||||||
let cr=normal.cross(control_dir);
|
let cr=normal.cross(control_dir);
|
||||||
if cr==Planar64Vec3::ZERO{
|
if cr==crate::integer::vec3::ZERO_2{
|
||||||
Planar64Vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
}else{
|
}else{
|
||||||
cr.cross(normal)*(self.accelerate.topspeed/(n*(n*n-d*d).sqrt()))
|
(cr.cross(normal)*self.accelerate.topspeed/((nn*(nnmm-dd)).sqrt())).divide().fix_1()
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
Planar64Vec3::ZERO
|
crate::integer::vec3::ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,22 +410,22 @@ pub struct Hitbox{
|
|||||||
impl Hitbox{
|
impl Hitbox{
|
||||||
pub fn roblox()->Self{
|
pub fn roblox()->Self{
|
||||||
Self{
|
Self{
|
||||||
halfsize:Planar64Vec3::int(2,5,2)/2,
|
halfsize:int3(2,5,2)>>1,
|
||||||
mesh:HitboxMesh::Cylinder,
|
mesh:HitboxMesh::Cylinder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn source()->Self{
|
pub fn source()->Self{
|
||||||
Self{
|
Self{
|
||||||
halfsize:Planar64Vec3::int(33,73,33)/2*VALVE_SCALE,
|
halfsize:((int3(33,73,33)>>1)*VALVE_SCALE).fix_1(),
|
||||||
mesh:HitboxMesh::Box,
|
mesh:HitboxMesh::Box,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyleModifiers{
|
impl StyleModifiers{
|
||||||
pub const RIGHT_DIR:Planar64Vec3=Planar64Vec3::X;
|
pub const RIGHT_DIR:Planar64Vec3=crate::integer::vec3::X;
|
||||||
pub const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
pub const UP_DIR:Planar64Vec3=crate::integer::vec3::Y;
|
||||||
pub const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
pub const FORWARD_DIR:Planar64Vec3=crate::integer::vec3::NEG_Z;
|
||||||
|
|
||||||
pub fn neo()->Self{
|
pub fn neo()->Self{
|
||||||
Self{
|
Self{
|
||||||
@ -423,38 +434,38 @@ impl StyleModifiers{
|
|||||||
strafe:Some(StrafeSettings{
|
strafe:Some(StrafeSettings{
|
||||||
enable:ControlsActivation::full_2d(),
|
enable:ControlsActivation::full_2d(),
|
||||||
air_accel_limit:None,
|
air_accel_limit:None,
|
||||||
mv:Planar64::int(3),
|
mv:int(3),
|
||||||
tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump:Some(JumpSettings{
|
jump:Some(JumpSettings{
|
||||||
impulse:JumpImpulse::Energy(Planar64::int(512)),
|
impulse:JumpImpulse::Energy(int(512)),
|
||||||
calculation:JumpCalculation::JumpThenBoost,
|
calculation:JumpCalculation::JumpThenBoost,
|
||||||
limit_minimum:false,
|
limit_minimum:false,
|
||||||
}),
|
}),
|
||||||
gravity:Planar64Vec3::int(0,-80,0),
|
gravity:int3(0,-80,0),
|
||||||
mass:Planar64::int(1),
|
mass:int(1),
|
||||||
rocket:None,
|
rocket:None,
|
||||||
walk:Some(WalkSettings{
|
walk:Some(WalkSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(16),
|
topspeed:int(16),
|
||||||
accel:Planar64::int(80),
|
accel:int(80),
|
||||||
},
|
},
|
||||||
static_friction:Planar64::int(2),
|
static_friction:int(2),
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
kinetic_friction:int(3),//unrealistic: kinetic friction is typically lower than static
|
||||||
surf_dot:Planar64::int(3)/4,
|
surf_dot:int(3)/4,
|
||||||
}),
|
}),
|
||||||
ladder:Some(LadderSettings{
|
ladder:Some(LadderSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(16),
|
topspeed:int(16),
|
||||||
accel:Planar64::int(160),
|
accel:int(160),
|
||||||
},
|
},
|
||||||
dot:(Planar64::int(1)/2).sqrt(),
|
dot:(int(1)/2).sqrt(),
|
||||||
}),
|
}),
|
||||||
swim:Some(PropulsionSettings{
|
swim:Some(PropulsionSettings{
|
||||||
magnitude:Planar64::int(12),
|
magnitude:int(12),
|
||||||
}),
|
}),
|
||||||
hitbox:Hitbox::roblox(),
|
hitbox:Hitbox::roblox(),
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
camera_offset:int3(0,2,0),//4.5-2.5=2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,7 +476,7 @@ impl StyleModifiers{
|
|||||||
strafe:Some(StrafeSettings{
|
strafe:Some(StrafeSettings{
|
||||||
enable:ControlsActivation::full_2d(),
|
enable:ControlsActivation::full_2d(),
|
||||||
air_accel_limit:None,
|
air_accel_limit:None,
|
||||||
mv:Planar64::int(27)/10,
|
mv:int(27)/10,
|
||||||
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump:Some(JumpSettings{
|
jump:Some(JumpSettings{
|
||||||
@ -473,35 +484,35 @@ impl StyleModifiers{
|
|||||||
calculation:JumpCalculation::Max,
|
calculation:JumpCalculation::Max,
|
||||||
limit_minimum:true,
|
limit_minimum:true,
|
||||||
}),
|
}),
|
||||||
gravity:Planar64Vec3::int(0,-100,0),
|
gravity:int3(0,-100,0),
|
||||||
mass:Planar64::int(1),
|
mass:int(1),
|
||||||
rocket:None,
|
rocket:None,
|
||||||
walk:Some(WalkSettings{
|
walk:Some(WalkSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(18),
|
topspeed:int(18),
|
||||||
accel:Planar64::int(90),
|
accel:int(90),
|
||||||
},
|
},
|
||||||
static_friction:Planar64::int(2),
|
static_friction:int(2),
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
kinetic_friction:int(3),//unrealistic: kinetic friction is typically lower than static
|
||||||
surf_dot:Planar64::int(3)/4,// normal.y=0.75
|
surf_dot:int(3)/4,// normal.y=0.75
|
||||||
}),
|
}),
|
||||||
ladder:Some(LadderSettings{
|
ladder:Some(LadderSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(18),
|
topspeed:int(18),
|
||||||
accel:Planar64::int(180),
|
accel:int(180),
|
||||||
},
|
},
|
||||||
dot:(Planar64::int(1)/2).sqrt(),
|
dot:(int(1)/2).sqrt(),
|
||||||
}),
|
}),
|
||||||
swim:Some(PropulsionSettings{
|
swim:Some(PropulsionSettings{
|
||||||
magnitude:Planar64::int(12),
|
magnitude:int(12),
|
||||||
}),
|
}),
|
||||||
hitbox:Hitbox::roblox(),
|
hitbox:Hitbox::roblox(),
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
camera_offset:int3(0,2,0),//4.5-2.5=2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn roblox_surf()->Self{
|
pub fn roblox_surf()->Self{
|
||||||
Self{
|
Self{
|
||||||
gravity:Planar64Vec3::int(0,-50,0),
|
gravity:int3(0,-50,0),
|
||||||
..Self::roblox_bhop()
|
..Self::roblox_bhop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,7 +520,7 @@ impl StyleModifiers{
|
|||||||
Self{
|
Self{
|
||||||
strafe:None,
|
strafe:None,
|
||||||
rocket:Some(PropulsionSettings{
|
rocket:Some(PropulsionSettings{
|
||||||
magnitude:Planar64::int(200),
|
magnitude:int(200),
|
||||||
}),
|
}),
|
||||||
..Self::roblox_bhop()
|
..Self::roblox_bhop()
|
||||||
}
|
}
|
||||||
@ -522,38 +533,38 @@ impl StyleModifiers{
|
|||||||
strafe:Some(StrafeSettings{
|
strafe:Some(StrafeSettings{
|
||||||
enable:ControlsActivation::full_2d(),
|
enable:ControlsActivation::full_2d(),
|
||||||
air_accel_limit:Some(Planar64::raw(150<<28)*100),
|
air_accel_limit:Some(Planar64::raw(150<<28)*100),
|
||||||
mv:Planar64::raw(30)*VALVE_SCALE,
|
mv:(Planar64::raw(30)*VALVE_SCALE).fix_1(),
|
||||||
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump:Some(JumpSettings{
|
jump:Some(JumpSettings{
|
||||||
impulse:JumpImpulse::Height(Planar64::int(52)*VALVE_SCALE),
|
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()),
|
||||||
calculation:JumpCalculation::JumpThenBoost,
|
calculation:JumpCalculation::JumpThenBoost,
|
||||||
limit_minimum:true,
|
limit_minimum:true,
|
||||||
}),
|
}),
|
||||||
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
|
gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(),
|
||||||
mass:Planar64::int(1),
|
mass:int(1),
|
||||||
rocket:None,
|
rocket:None,
|
||||||
walk:Some(WalkSettings{
|
walk:Some(WalkSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(18),//?
|
topspeed:int(18),//?
|
||||||
accel:Planar64::int(90),//?
|
accel:int(90),//?
|
||||||
},
|
},
|
||||||
static_friction:Planar64::int(2),//?
|
static_friction:int(2),//?
|
||||||
kinetic_friction:Planar64::int(3),//?
|
kinetic_friction:int(3),//?
|
||||||
surf_dot:Planar64::int(3)/4,// normal.y=0.75
|
surf_dot:int(3)/4,// normal.y=0.75
|
||||||
}),
|
}),
|
||||||
ladder:Some(LadderSettings{
|
ladder:Some(LadderSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(18),//?
|
topspeed:int(18),//?
|
||||||
accel:Planar64::int(180),//?
|
accel:int(180),//?
|
||||||
},
|
},
|
||||||
dot:(Planar64::int(1)/2).sqrt(),//?
|
dot:(int(1)/2).sqrt(),//?
|
||||||
}),
|
}),
|
||||||
swim:Some(PropulsionSettings{
|
swim:Some(PropulsionSettings{
|
||||||
magnitude:Planar64::int(12),//?
|
magnitude:int(12),//?
|
||||||
}),
|
}),
|
||||||
hitbox:Hitbox::source(),
|
hitbox:Hitbox::source(),
|
||||||
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)*VALVE_SCALE,
|
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).fix_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn source_surf()->Self{
|
pub fn source_surf()->Self{
|
||||||
@ -562,39 +573,39 @@ impl StyleModifiers{
|
|||||||
controls_mask_state:Controls::all(),
|
controls_mask_state:Controls::all(),
|
||||||
strafe:Some(StrafeSettings{
|
strafe:Some(StrafeSettings{
|
||||||
enable:ControlsActivation::full_2d(),
|
enable:ControlsActivation::full_2d(),
|
||||||
air_accel_limit:Some(Planar64::int(150)*66*VALVE_SCALE),
|
air_accel_limit:Some((int(150)*66*VALVE_SCALE).fix_1()),
|
||||||
mv:Planar64::int(30)*VALVE_SCALE,
|
mv:(int(30)*VALVE_SCALE).fix_1(),
|
||||||
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump:Some(JumpSettings{
|
jump:Some(JumpSettings{
|
||||||
impulse:JumpImpulse::Height(Planar64::int(52)*VALVE_SCALE),
|
impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()),
|
||||||
calculation:JumpCalculation::JumpThenBoost,
|
calculation:JumpCalculation::JumpThenBoost,
|
||||||
limit_minimum:true,
|
limit_minimum:true,
|
||||||
}),
|
}),
|
||||||
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
|
gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(),
|
||||||
mass:Planar64::int(1),
|
mass:int(1),
|
||||||
rocket:None,
|
rocket:None,
|
||||||
walk:Some(WalkSettings{
|
walk:Some(WalkSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(18),//?
|
topspeed:int(18),//?
|
||||||
accel:Planar64::int(90),//?
|
accel:int(90),//?
|
||||||
},
|
},
|
||||||
static_friction:Planar64::int(2),//?
|
static_friction:int(2),//?
|
||||||
kinetic_friction:Planar64::int(3),//?
|
kinetic_friction:int(3),//?
|
||||||
surf_dot:Planar64::int(3)/4,// normal.y=0.75
|
surf_dot:int(3)/4,// normal.y=0.75
|
||||||
}),
|
}),
|
||||||
ladder:Some(LadderSettings{
|
ladder:Some(LadderSettings{
|
||||||
accelerate:AccelerateSettings{
|
accelerate:AccelerateSettings{
|
||||||
topspeed:Planar64::int(18),//?
|
topspeed:int(18),//?
|
||||||
accel:Planar64::int(180),//?
|
accel:int(180),//?
|
||||||
},
|
},
|
||||||
dot:(Planar64::int(1)/2).sqrt(),//?
|
dot:(int(1)/2).sqrt(),//?
|
||||||
}),
|
}),
|
||||||
swim:Some(PropulsionSettings{
|
swim:Some(PropulsionSettings{
|
||||||
magnitude:Planar64::int(12),//?
|
magnitude:int(12),//?
|
||||||
}),
|
}),
|
||||||
hitbox:Hitbox::source(),
|
hitbox:Hitbox::source(),
|
||||||
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)*VALVE_SCALE,
|
camera_offset:((int3(0,64,0)-(int3(0,73,0)>>1))*VALVE_SCALE).fix_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
854
src/integer.rs
854
src/integer.rs
@ -1,3 +1,6 @@
|
|||||||
|
pub use fixed_wide::fixed::{Fixed,Fix};
|
||||||
|
pub use ratio_ops::ratio::{Ratio,Divide};
|
||||||
|
|
||||||
//integer units
|
//integer units
|
||||||
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
|
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
|
||||||
pub struct Time(i64);
|
pub struct Time(i64);
|
||||||
@ -38,11 +41,26 @@ impl Time{
|
|||||||
pub const fn nanos(self)->i64{
|
pub const fn nanos(self)->i64{
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn to_ratio(self)->Ratio<Planar64,Planar64>{
|
||||||
|
Ratio::new(Planar64::raw(self.0),Planar64::raw(1_000_000_000))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl From<Planar64> for Time{
|
impl From<Planar64> for Time{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(value:Planar64)->Self{
|
fn from(value:Planar64)->Self{
|
||||||
Time((((value.0 as i128)*1_000_000_000)>>32) as i64)
|
Time((value*Planar64::raw(1_000_000_000)).fix_1().to_raw())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Num,Den,N1,T1> From<Ratio<Num,Den>> for Time
|
||||||
|
where
|
||||||
|
Num:core::ops::Mul<Planar64,Output=N1>,
|
||||||
|
N1:Divide<Den,Output=T1>,
|
||||||
|
T1:Fix<Planar64>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn from(value:Ratio<Num,Den>)->Self{
|
||||||
|
Time((value*Planar64::raw(1_000_000_000)).divide().fix().to_raw())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for Time{
|
impl std::fmt::Display for Time{
|
||||||
@ -63,34 +81,81 @@ impl std::ops::Neg for Time{
|
|||||||
Time(-self.0)
|
Time(-self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::ops::Add<Time> for Time{
|
macro_rules! impl_time_additive_operator {
|
||||||
|
($trait:ty, $method:ident) => {
|
||||||
|
impl $trait for Time{
|
||||||
type Output=Time;
|
type Output=Time;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self,rhs:Self)->Self::Output {
|
fn $method(self,rhs:Self)->Self::Output {
|
||||||
Time(self.0+rhs.0)
|
Time(self.0.$method(rhs.0))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
impl std::ops::Sub<Time> for Time{
|
|
||||||
type Output=Time;
|
|
||||||
#[inline]
|
|
||||||
fn sub(self,rhs:Self)->Self::Output {
|
|
||||||
Time(self.0-rhs.0)
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
impl std::ops::Mul<Time> for Time{
|
impl_time_additive_operator!(core::ops::Add,add);
|
||||||
type Output=Time;
|
impl_time_additive_operator!(core::ops::Sub,sub);
|
||||||
|
impl_time_additive_operator!(core::ops::Rem,rem);
|
||||||
|
macro_rules! impl_time_additive_assign_operator {
|
||||||
|
($trait:ty, $method:ident) => {
|
||||||
|
impl $trait for Time{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self,rhs:Time)->Self::Output{
|
fn $method(&mut self,rhs:Self){
|
||||||
Self((((self.0 as i128)*(rhs.0 as i128))/1_000_000_000) as i64)
|
self.0.$method(rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
impl_time_additive_assign_operator!(core::ops::AddAssign,add_assign);
|
||||||
|
impl_time_additive_assign_operator!(core::ops::SubAssign,sub_assign);
|
||||||
|
impl_time_additive_assign_operator!(core::ops::RemAssign,rem_assign);
|
||||||
|
impl std::ops::Mul for Time{
|
||||||
|
type Output=Ratio<fixed_wide::fixed::Fixed<2,64>,fixed_wide::fixed::Fixed<2,64>>;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self,rhs:Self)->Self::Output{
|
||||||
|
Ratio::new(Fixed::raw(self.0)*Fixed::raw(rhs.0),Fixed::raw_digit(1_000_000_000i64.pow(2)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::ops::Div<i64> for Time{
|
impl std::ops::Div<i64> for Time{
|
||||||
type Output=Time;
|
type Output=Time;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self,rhs:i64)->Self::Output {
|
fn div(self,rhs:i64)->Self::Output{
|
||||||
Time(self.0/rhs)
|
Time(self.0/rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl std::ops::Mul<i64> for Time{
|
||||||
|
type Output=Time;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self,rhs:i64)->Self::Output{
|
||||||
|
Time(self.0*rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl core::ops::Mul<Time> for Planar64{
|
||||||
|
type Output=Ratio<Fixed<2,64>,Planar64>;
|
||||||
|
fn mul(self,rhs:Time)->Self::Output{
|
||||||
|
Ratio::new(self*Fixed::raw(rhs.0),Planar64::raw(1_000_000_000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn time_from_planar64(){
|
||||||
|
let a:Time=Planar64::from(1).into();
|
||||||
|
assert_eq!(a,Time::ONE_SECOND);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn time_from_ratio(){
|
||||||
|
let a:Time=Ratio::new(Planar64::from(1),Planar64::from(1)).into();
|
||||||
|
assert_eq!(a,Time::ONE_SECOND);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn time_squared(){
|
||||||
|
let a=Time::from_secs(2);
|
||||||
|
assert_eq!(a*a,Ratio::new(Fixed::<2,64>::raw_digit(1_000_000_000i64.pow(2))*4,Fixed::<2,64>::raw_digit(1_000_000_000i64.pow(2))));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn time_times_planar64(){
|
||||||
|
let a=Time::from_secs(2);
|
||||||
|
let b=Planar64::from(2);
|
||||||
|
assert_eq!(b*a,Ratio::new(Fixed::<2,64>::raw_digit(1_000_000_000*(1<<32))<<2,Fixed::<1,32>::raw_digit(1_000_000_000)));
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
const fn gcd(mut a:u64,mut b:u64)->u64{
|
const fn gcd(mut a:u64,mut b:u64)->u64{
|
||||||
@ -309,6 +374,7 @@ impl std::ops::Mul<i64> for Ratio64Vec2{
|
|||||||
#[derive(Clone,Copy,Hash)]
|
#[derive(Clone,Copy,Hash)]
|
||||||
pub struct Angle32(i32);
|
pub struct Angle32(i32);
|
||||||
impl Angle32{
|
impl Angle32{
|
||||||
|
const ANGLE32_TO_FLOAT64_RADIANS:f64=std::f64::consts::PI/((1i64<<31) as f64);
|
||||||
pub const FRAC_PI_2:Self=Self(1<<30);
|
pub const FRAC_PI_2:Self=Self(1<<30);
|
||||||
pub const NEG_FRAC_PI_2:Self=Self(-1<<30);
|
pub const NEG_FRAC_PI_2:Self=Self(-1<<30);
|
||||||
pub const PI:Self=Self(-1<<31);
|
pub const PI:Self=Self(-1<<31);
|
||||||
@ -347,24 +413,36 @@ impl Angle32{
|
|||||||
.wrapping_add(midpoint)
|
.wrapping_add(midpoint)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn cos_sin(&self)->(Planar64,Planar64){
|
||||||
/*
|
/*
|
||||||
#[inline]
|
//cordic
|
||||||
pub fn cos(&self)->Unit32{
|
let a=self.0 as u32;
|
||||||
//TODO: fix this rounding towards 0
|
//initialize based on the quadrant
|
||||||
Unit32(unsafe{((self.0 as f64*ANGLE32_TO_FLOAT64_RADIANS).cos()*UNIT32_ONE_FLOAT64).to_int_unchecked()})
|
let (mut x,mut y)=match (a&(1<<31)!=0,a&(1<<30)!=0){
|
||||||
|
(false,false)=>( 1i64<<32, 0i64 ),//TR
|
||||||
|
(false,true )=>( 0i64 , 1i64<<32),//TL
|
||||||
|
(true ,false)=>(-1i64<<32, 0i64 ),//BL
|
||||||
|
(true ,true )=>( 0i64 ,-1i64<<32),//BR
|
||||||
|
};
|
||||||
|
println!("x={} y={}",Planar64::raw(x),Planar64::raw(y));
|
||||||
|
for i in 0..30{
|
||||||
|
if a&(1<<(29-i))!=0{
|
||||||
|
(x,y)=(x-(y>>i),y+(x>>i));
|
||||||
}
|
}
|
||||||
#[inline]
|
println!("i={i} t={} x={} y={}",(a&(1<<(29-i))!=0) as u8,Planar64::raw(x),Planar64::raw(y));
|
||||||
pub fn sin(&self)->Unit32{
|
|
||||||
//TODO: fix this rounding towards 0
|
|
||||||
Unit32(unsafe{((self.0 as f64*ANGLE32_TO_FLOAT64_RADIANS).sin()*UNIT32_ONE_FLOAT64).to_int_unchecked()})
|
|
||||||
}
|
}
|
||||||
|
//don't forget the gain
|
||||||
|
(Planar64::raw(x),Planar64::raw(y))
|
||||||
*/
|
*/
|
||||||
|
let (s,c)=(self.0 as f64*Self::ANGLE32_TO_FLOAT64_RADIANS).sin_cos();
|
||||||
|
(Planar64::raw((c*((1u64<<32) as f64)) as i64),Planar64::raw((s*((1u64<<32) as f64)) as i64))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const ANGLE32_TO_FLOAT64_RADIANS:f64=std::f64::consts::PI/((1i64<<31) as f64);
|
|
||||||
impl Into<f32> for Angle32{
|
impl Into<f32> for Angle32{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self)->f32{
|
fn into(self)->f32{
|
||||||
(self.0 as f64*ANGLE32_TO_FLOAT64_RADIANS) as f32
|
(self.0 as f64*Self::ANGLE32_TO_FLOAT64_RADIANS) as f32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::ops::Neg for Angle32{
|
impl std::ops::Neg for Angle32{
|
||||||
@ -402,6 +480,26 @@ impl std::ops::Mul<Angle32> for Angle32{
|
|||||||
Angle32(self.0.wrapping_mul(rhs.0))
|
Angle32(self.0.wrapping_mul(rhs.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn angle_sin_cos(){
|
||||||
|
fn close_enough(lhs:Planar64,rhs:Planar64)->bool{
|
||||||
|
(lhs-rhs).abs()<Planar64::EPSILON*4
|
||||||
|
}
|
||||||
|
fn test_angle(f:f64){
|
||||||
|
let a=Angle32((f/Angle32::ANGLE32_TO_FLOAT64_RADIANS) as i32);
|
||||||
|
println!("a={:#034b}",a.0);
|
||||||
|
let (c,s)=a.cos_sin();
|
||||||
|
let h=(s*s+c*c).sqrt();
|
||||||
|
println!("cordic s={} c={}",(s/h).divide(),(c/h).divide());
|
||||||
|
let (fs,fc)=f.sin_cos();
|
||||||
|
println!("float s={} c={}",fs,fc);
|
||||||
|
assert!(close_enough((c/h).divide().fix_1(),Planar64::raw((fc*((1u64<<32) as f64)) as i64)));
|
||||||
|
assert!(close_enough((s/h).divide().fix_1(),Planar64::raw((fs*((1u64<<32) as f64)) as i64)));
|
||||||
|
}
|
||||||
|
test_angle(1.0);
|
||||||
|
test_angle(std::f64::consts::PI/4.0);
|
||||||
|
test_angle(std::f64::consts::PI/8.0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unit type unused for now, may revive it for map files
|
/* Unit type unused for now, may revive it for map files
|
||||||
///[-1.0,1.0] = [-2^30,2^30]
|
///[-1.0,1.0] = [-2^30,2^30]
|
||||||
@ -427,668 +525,140 @@ impl TryFrom<[f32;3]> for Unit32Vec3{
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
pub type Planar64TryFromFloatError=fixed_wide::fixed::FixedFromFloatError;
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,Ord,PartialEq,PartialOrd)]
|
pub type Planar64=fixed_wide::types::I32F32;
|
||||||
pub struct Planar64(i64);
|
pub type Planar64Vec3=linear_ops::types::Vector3<Planar64>;
|
||||||
impl Planar64{
|
pub type Planar64Mat3=linear_ops::types::Matrix3<Planar64>;
|
||||||
pub const ZERO:Self=Self(0);
|
pub mod vec3{
|
||||||
pub const ONE:Self=Self(1<<32);
|
use super::*;
|
||||||
pub const MAX:Self=Self(i64::MAX);
|
pub use linear_ops::types::Vector3;
|
||||||
pub const MIN:Self=Self(i64::MIN);
|
pub const MIN:Planar64Vec3=Planar64Vec3::new([Planar64::MIN;3]);
|
||||||
|
pub const MAX:Planar64Vec3=Planar64Vec3::new([Planar64::MAX;3]);
|
||||||
|
pub const ZERO:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO;3]);
|
||||||
|
pub const ZERO_2:linear_ops::types::Vector3<Fixed::<2,64>>=linear_ops::types::Vector3::new([Fixed::<2,64>::ZERO;3]);
|
||||||
|
pub const X:Planar64Vec3=Planar64Vec3::new([Planar64::ONE,Planar64::ZERO,Planar64::ZERO]);
|
||||||
|
pub const Y:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ONE,Planar64::ZERO]);
|
||||||
|
pub const Z:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ZERO,Planar64::ONE]);
|
||||||
|
pub const ONE:Planar64Vec3=Planar64Vec3::new([Planar64::ONE,Planar64::ONE,Planar64::ONE]);
|
||||||
|
pub const NEG_X:Planar64Vec3=Planar64Vec3::new([Planar64::NEG_ONE,Planar64::ZERO,Planar64::ZERO]);
|
||||||
|
pub const NEG_Y:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::NEG_ONE,Planar64::ZERO]);
|
||||||
|
pub const NEG_Z:Planar64Vec3=Planar64Vec3::new([Planar64::ZERO,Planar64::ZERO,Planar64::NEG_ONE]);
|
||||||
|
pub const NEG_ONE:Planar64Vec3=Planar64Vec3::new([Planar64::NEG_ONE,Planar64::NEG_ONE,Planar64::NEG_ONE]);
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn int(num:i32)->Self{
|
pub const fn int(x:i32,y:i32,z:i32)->Planar64Vec3{
|
||||||
Self(Self::ONE.0*num as i64)
|
Planar64Vec3::new([Planar64::raw((x as i64)<<32),Planar64::raw((y as i64)<<32),Planar64::raw((z as i64)<<32)])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn raw(num:i64)->Self{
|
pub fn raw_array(array:[i64;3])->Planar64Vec3{
|
||||||
Self(num)
|
Planar64Vec3::new(array.map(Planar64::raw))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn get(&self)->i64{
|
pub fn raw_xyz(x:i64,y:i64,z:i64)->Planar64Vec3{
|
||||||
self.0
|
Planar64Vec3::new([Planar64::raw(x),Planar64::raw(y),Planar64::raw(z)])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn abs(self)->Self{
|
pub fn try_from_f32_array([x,y,z]:[f32;3])->Result<Planar64Vec3,Planar64TryFromFloatError>{
|
||||||
Self(self.0.abs())
|
Ok(Planar64Vec3::new([
|
||||||
}
|
try_from_f32(x)?,
|
||||||
#[inline]
|
try_from_f32(y)?,
|
||||||
pub fn sqrt(&self)->Self{
|
try_from_f32(z)?,
|
||||||
const BITS:i32=64;
|
]))
|
||||||
const FRAC:i32=32;
|
|
||||||
let pow=(((BITS-FRAC-(self.0.leading_zeros() as i32)+1)>>1)+FRAC)-1;
|
|
||||||
let mut result=Self::ZERO;
|
|
||||||
let wide_self=(self.0 as i128)<<FRAC;
|
|
||||||
for i in (0..=pow).rev(){
|
|
||||||
let new_result=Self::raw(result.0|1<<i);
|
|
||||||
match wide_self.cmp(&((new_result.0 as i128)*(new_result.0 as i128))){
|
|
||||||
core::cmp::Ordering::Less=>(),
|
|
||||||
core::cmp::Ordering::Equal=>return new_result,
|
|
||||||
core::cmp::Ordering::Greater=>result=new_result,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn signum_i64(&self)->i64{
|
|
||||||
((self.0&(1<<63)!=0) as i64)*2-1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const PLANAR64_ONE_FLOAT32:f32=(1u64<<32) as f32;
|
|
||||||
const PLANAR64_CONVERT_TO_FLOAT32:f32=1.0/PLANAR64_ONE_FLOAT32;
|
|
||||||
const PLANAR64_ONE_FLOAT64:f64=(1u64<<32) as f64;
|
|
||||||
impl Into<f32> for Planar64{
|
|
||||||
#[inline]
|
|
||||||
fn into(self)->f32{
|
|
||||||
self.0 as f32*PLANAR64_CONVERT_TO_FLOAT32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<Ratio64> for Planar64{
|
|
||||||
#[inline]
|
|
||||||
fn from(ratio:Ratio64)->Self{
|
|
||||||
Self((((ratio.num as i128)<<32)/(ratio.den as i128)) as i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Planar64TryFromFloatError{
|
|
||||||
Nan,
|
|
||||||
Infinite,
|
|
||||||
Subnormal,
|
|
||||||
HighlyNegativeExponent,
|
|
||||||
HighlyPositiveExponent,
|
|
||||||
}
|
|
||||||
impl TryFrom<f32> for Planar64{
|
|
||||||
type Error=Planar64TryFromFloatError;
|
|
||||||
#[inline]
|
|
||||||
fn try_from(value:f32)->Result<Self,Self::Error>{
|
|
||||||
match value.classify(){
|
|
||||||
std::num::FpCategory::Nan=>Err(Self::Error::Nan),
|
|
||||||
std::num::FpCategory::Infinite=>Err(Self::Error::Infinite),
|
|
||||||
std::num::FpCategory::Zero=>Ok(Self::ZERO),
|
|
||||||
std::num::FpCategory::Subnormal
|
|
||||||
|std::num::FpCategory::Normal=>{
|
|
||||||
let planar=value*PLANAR64_ONE_FLOAT32;
|
|
||||||
if planar<(i64::MIN as f32)||(i64::MAX as f32)<planar{
|
|
||||||
Err(Self::Error::HighlyPositiveExponent)
|
|
||||||
}else{
|
|
||||||
Ok(Planar64(unsafe{planar.to_int_unchecked()}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<f64> for Planar64{
|
|
||||||
type Error=Planar64TryFromFloatError;
|
|
||||||
#[inline]
|
|
||||||
fn try_from(value:f64)->Result<Self,Self::Error>{
|
|
||||||
match value.classify(){
|
|
||||||
std::num::FpCategory::Nan=>Err(Self::Error::Nan),
|
|
||||||
std::num::FpCategory::Infinite=>Err(Self::Error::Infinite),
|
|
||||||
std::num::FpCategory::Zero=>Ok(Self::ZERO),
|
|
||||||
std::num::FpCategory::Subnormal
|
|
||||||
|std::num::FpCategory::Normal=>{
|
|
||||||
let planar=value*PLANAR64_ONE_FLOAT64;
|
|
||||||
if planar<(i64::MIN as f64)||(i64::MAX as f64)<planar{
|
|
||||||
Err(Self::Error::HighlyPositiveExponent)
|
|
||||||
}else{
|
|
||||||
Ok(Planar64(unsafe{planar.to_int_unchecked()}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::fmt::Display for Planar64{
|
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
|
||||||
write!(f,"{:.3}",
|
|
||||||
Into::<f32>::into(*self),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Neg for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn neg(self)->Self::Output{
|
|
||||||
Planar64(-self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Add<Planar64> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
|
||||||
Planar64(self.0+rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::AddAssign<Planar64> for Planar64{
|
|
||||||
#[inline]
|
|
||||||
fn add_assign(&mut self,rhs:Self){
|
|
||||||
*self=*self+rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Sub<Planar64> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn sub(self, rhs: Self) -> Self::Output {
|
|
||||||
Planar64(self.0-rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<i64> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, rhs: i64) -> Self::Output {
|
|
||||||
Planar64(self.0*rhs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<Planar64> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
|
||||||
Planar64(((self.0 as i128*rhs.0 as i128)>>32) as i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<Time> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self,rhs:Time)->Self::Output{
|
|
||||||
Planar64(((self.0 as i128*rhs.0 as i128)/1_000_000_000) as i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Div<i64> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn div(self, rhs: i64) -> Self::Output {
|
|
||||||
Planar64(self.0/rhs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Div<Planar64> for Planar64{
|
|
||||||
type Output=Planar64;
|
|
||||||
#[inline]
|
|
||||||
fn div(self, rhs: Planar64) -> Self::Output {
|
|
||||||
Planar64((((self.0 as i128)<<32)/(rhs.0 as i128)) as i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// impl PartialOrd<i64> for Planar64{
|
|
||||||
// fn partial_cmp(&self, other: &i64) -> Option<std::cmp::Ordering> {
|
|
||||||
// self.0.partial_cmp(other)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
|
||||||
#[derive(Clone,Copy,Debug,Default,Hash,Eq,PartialEq)]
|
|
||||||
pub struct Planar64Vec3(glam::I64Vec3);
|
|
||||||
impl Planar64Vec3{
|
|
||||||
pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO);
|
|
||||||
pub const ONE:Self=Self::int(1,1,1);
|
|
||||||
pub const X:Self=Self::int(1,0,0);
|
|
||||||
pub const Y:Self=Self::int(0,1,0);
|
|
||||||
pub const Z:Self=Self::int(0,0,1);
|
|
||||||
pub const NEG_X:Self=Self::int(-1,0,0);
|
|
||||||
pub const NEG_Y:Self=Self::int(0,-1,0);
|
|
||||||
pub const NEG_Z:Self=Self::int(0,0,-1);
|
|
||||||
pub const MIN:Self=Planar64Vec3(glam::I64Vec3::MIN);
|
|
||||||
pub const MAX:Self=Planar64Vec3(glam::I64Vec3::MAX);
|
|
||||||
#[inline]
|
|
||||||
pub const fn new(x:Planar64,y:Planar64,z:Planar64)->Self{
|
|
||||||
Self(glam::i64vec3(x.0,y.0,z.0))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn get(self)->glam::I64Vec3{
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn int(x:i32,y:i32,z:i32)->Self{
|
|
||||||
Self(glam::i64vec3((x as i64)<<32,(y as i64)<<32,(z as i64)<<32))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn raw_xyz(x:i64,y:i64,z:i64)->Self{
|
|
||||||
Self(glam::i64vec3(x,y,z))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn raw_array(xyz:[i64;3])->Self{
|
|
||||||
Self(glam::I64Vec3::from_array(xyz))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn raw(xyz:glam::I64Vec3)->Self{
|
|
||||||
Self(xyz)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn x(&self)->Planar64{
|
|
||||||
Planar64(self.0.x)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn y(&self)->Planar64{
|
|
||||||
Planar64(self.0.y)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const 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)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn dot(&self,rhs:Self)->Planar64{
|
|
||||||
Planar64(((
|
|
||||||
(self.0.x as i128)*(rhs.0.x as i128)+
|
|
||||||
(self.0.y as i128)*(rhs.0.y as i128)+
|
|
||||||
(self.0.z as i128)*(rhs.0.z as i128)
|
|
||||||
)>>32) as i64)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn dot128(&self,rhs:Self)->i128{
|
|
||||||
(self.0.x as i128)*(rhs.0.x as i128)+
|
|
||||||
(self.0.y as i128)*(rhs.0.y as i128)+
|
|
||||||
(self.0.z as i128)*(rhs.0.z as i128)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn cross(&self,rhs:Self)->Planar64Vec3{
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
(((self.0.y as i128)*(rhs.0.z as i128)-(self.0.z as i128)*(rhs.0.y as i128))>>32) as i64,
|
|
||||||
(((self.0.z as i128)*(rhs.0.x as i128)-(self.0.x as i128)*(rhs.0.z as i128))>>32) as i64,
|
|
||||||
(((self.0.x as i128)*(rhs.0.y as i128)-(self.0.y as i128)*(rhs.0.x as i128))>>32) as i64,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn length(&self)->Planar64{
|
|
||||||
let radicand=(self.0.x as i128)*(self.0.x as i128)+(self.0.y as i128)*(self.0.y as i128)+(self.0.z as i128)*(self.0.z as i128);
|
|
||||||
Planar64(unsafe{(radicand as f64).sqrt().to_int_unchecked()})
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn with_length(&self,length:Planar64)->Self{
|
|
||||||
let radicand=(self.0.x as i128)*(self.0.x as i128)+(self.0.y as i128)*(self.0.y as i128)+(self.0.z as i128)*(self.0.z as i128);
|
|
||||||
let self_length:i128=unsafe{(radicand as f64).sqrt().to_int_unchecked()};
|
|
||||||
//self.0*length/self_length
|
|
||||||
Planar64Vec3(
|
|
||||||
glam::i64vec3(
|
|
||||||
((self.0.x as i128)*(length.0 as i128)/self_length) as i64,
|
|
||||||
((self.0.y as i128)*(length.0 as i128)/self_length) as i64,
|
|
||||||
((self.0.z as i128)*(length.0 as i128)/self_length) as i64,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Into<glam::Vec3> for Planar64Vec3{
|
|
||||||
#[inline]
|
|
||||||
fn into(self)->glam::Vec3{
|
|
||||||
glam::vec3(
|
|
||||||
self.0.x as f32,
|
|
||||||
self.0.y as f32,
|
|
||||||
self.0.z as f32,
|
|
||||||
)*PLANAR64_CONVERT_TO_FLOAT32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<[f32;3]> for Planar64Vec3{
|
|
||||||
type Error=Planar64TryFromFloatError;
|
|
||||||
#[inline]
|
|
||||||
fn try_from(value:[f32;3])->Result<Self,Self::Error>{
|
|
||||||
Ok(Self(glam::i64vec3(
|
|
||||||
Planar64::try_from(value[0])?.0,
|
|
||||||
Planar64::try_from(value[1])?.0,
|
|
||||||
Planar64::try_from(value[2])?.0,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<glam::Vec3A> for Planar64Vec3{
|
|
||||||
type Error=Planar64TryFromFloatError;
|
|
||||||
#[inline]
|
|
||||||
fn try_from(value:glam::Vec3A)->Result<Self,Self::Error>{
|
|
||||||
Ok(Self(glam::i64vec3(
|
|
||||||
Planar64::try_from(value.x)?.0,
|
|
||||||
Planar64::try_from(value.y)?.0,
|
|
||||||
Planar64::try_from(value.z)?.0,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::fmt::Display for Planar64Vec3{
|
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
|
||||||
write!(f,"{:.3},{:.3},{:.3}",
|
|
||||||
Into::<f32>::into(self.x()),Into::<f32>::into(self.y()),Into::<f32>::into(self.z()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Neg for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn neg(self)->Self::Output{
|
|
||||||
Planar64Vec3(-self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Add<Planar64Vec3> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn add(self,rhs:Planar64Vec3) -> Self::Output {
|
|
||||||
Planar64Vec3(self.0+rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::AddAssign<Planar64Vec3> for Planar64Vec3{
|
|
||||||
#[inline]
|
|
||||||
fn add_assign(&mut self,rhs:Planar64Vec3){
|
|
||||||
*self=*self+rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Sub<Planar64Vec3> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn sub(self,rhs:Planar64Vec3) -> Self::Output {
|
|
||||||
Planar64Vec3(self.0-rhs.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::SubAssign<Planar64Vec3> for Planar64Vec3{
|
|
||||||
#[inline]
|
|
||||||
fn sub_assign(&mut self,rhs:Planar64Vec3){
|
|
||||||
*self=*self-rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<Planar64Vec3> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, rhs: Planar64Vec3) -> Self::Output {
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
(((self.0.x as i128)*(rhs.0.x as i128))>>32) as i64,
|
|
||||||
(((self.0.y as i128)*(rhs.0.y as i128))>>32) as i64,
|
|
||||||
(((self.0.z as i128)*(rhs.0.z as i128))>>32) as i64
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<Planar64> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, rhs: Planar64) -> Self::Output {
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
(((self.0.x as i128)*(rhs.0 as i128))>>32) as i64,
|
|
||||||
(((self.0.y as i128)*(rhs.0 as i128))>>32) as i64,
|
|
||||||
(((self.0.z as i128)*(rhs.0 as i128))>>32) as i64
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<i64> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self,rhs:i64)->Self::Output {
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
self.0.x*rhs,
|
|
||||||
self.0.y*rhs,
|
|
||||||
self.0.z*rhs
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<Time> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self,rhs:Time)->Self::Output{
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
(((self.0.x as i128)*(rhs.0 as i128))/1_000_000_000) as i64,
|
|
||||||
(((self.0.y as i128)*(rhs.0 as i128))/1_000_000_000) as i64,
|
|
||||||
(((self.0.z as i128)*(rhs.0 as i128))/1_000_000_000) as i64
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Div<Planar64> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn div(self,rhs:Planar64)->Self::Output{
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
(((self.0.x as i128)<<32)/(rhs.0 as i128)) as i64,
|
|
||||||
(((self.0.y as i128)<<32)/(rhs.0 as i128)) as i64,
|
|
||||||
(((self.0.z as i128)<<32)/(rhs.0 as i128)) as i64,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Div<i64> for Planar64Vec3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn div(self,rhs:i64)->Self::Output{
|
|
||||||
Planar64Vec3(glam::i64vec3(
|
|
||||||
self.0.x/rhs,
|
|
||||||
self.0.y/rhs,
|
|
||||||
self.0.z/rhs,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
#[inline]
|
||||||
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
pub fn int(value:i32)->Planar64{
|
||||||
pub struct Planar64Mat3{
|
Planar64::from(value)
|
||||||
pub x_axis:Planar64Vec3,
|
|
||||||
pub y_axis:Planar64Vec3,
|
|
||||||
pub z_axis:Planar64Vec3,
|
|
||||||
}
|
}
|
||||||
impl Default for Planar64Mat3{
|
#[inline]
|
||||||
#[inline]
|
pub fn try_from_f32(value:f32)->Result<Planar64,Planar64TryFromFloatError>{
|
||||||
fn default() -> Self {
|
let result:Result<Planar64,_>=value.try_into();
|
||||||
Self{
|
match result{
|
||||||
x_axis:Planar64Vec3::X,
|
Ok(ok)=>Ok(ok),
|
||||||
y_axis:Planar64Vec3::Y,
|
Err(e)=>e.underflow_to_zero(),
|
||||||
z_axis:Planar64Vec3::Z,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Planar64Mat3{
|
pub mod mat3{
|
||||||
|
use super::*;
|
||||||
|
pub use linear_ops::types::Matrix3;
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_cols(x_axis:Planar64Vec3,y_axis:Planar64Vec3,z_axis:Planar64Vec3)->Self{
|
pub const fn identity()->Planar64Mat3{
|
||||||
Self{
|
Planar64Mat3::new([
|
||||||
x_axis,
|
[Planar64::ONE,Planar64::ZERO,Planar64::ZERO],
|
||||||
y_axis,
|
[Planar64::ZERO,Planar64::ONE,Planar64::ZERO],
|
||||||
z_axis,
|
[Planar64::ZERO,Planar64::ZERO,Planar64::ONE],
|
||||||
}
|
])
|
||||||
}
|
|
||||||
pub const fn int_from_cols_array(array:[i32;9])->Self{
|
|
||||||
Self{
|
|
||||||
x_axis:Planar64Vec3::int(array[0],array[1],array[2]),
|
|
||||||
y_axis:Planar64Vec3::int(array[3],array[4],array[5]),
|
|
||||||
z_axis:Planar64Vec3::int(array[6],array[7],array[8]),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_diagonal(diagonal:Planar64Vec3)->Self{
|
pub fn from_diagonal(diag:Planar64Vec3)->Planar64Mat3{
|
||||||
Self{
|
Planar64Mat3::new([
|
||||||
x_axis:Planar64Vec3::raw_xyz(diagonal.0.x,0,0),
|
[diag.x,Planar64::ZERO,Planar64::ZERO],
|
||||||
y_axis:Planar64Vec3::raw_xyz(0,diagonal.0.y,0),
|
[Planar64::ZERO,diag.y,Planar64::ZERO],
|
||||||
z_axis:Planar64Vec3::raw_xyz(0,0,diagonal.0.z),
|
[Planar64::ZERO,Planar64::ZERO,diag.z],
|
||||||
}
|
])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rotation_yx(yaw:Angle32,pitch:Angle32)->Self{
|
pub fn from_rotation_yx(x:Angle32,y:Angle32)->Planar64Mat3{
|
||||||
let xtheta=yaw.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
let (xc,xs)=x.cos_sin();
|
||||||
let (xs,xc)=xtheta.sin_cos();
|
let (yc,ys)=y.cos_sin();
|
||||||
let (xc,xs)=(xc*PLANAR64_ONE_FLOAT64,xs*PLANAR64_ONE_FLOAT64);
|
Planar64Mat3::from_cols([
|
||||||
let ytheta=pitch.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
Planar64Vec3::new([xc,Planar64::ZERO,-xs]),
|
||||||
let (ys,yc)=ytheta.sin_cos();
|
Planar64Vec3::new([(xs*ys).fix_1(),yc,(xc*ys).fix_1()]),
|
||||||
let (yc,ys)=(yc*PLANAR64_ONE_FLOAT64,ys*PLANAR64_ONE_FLOAT64);
|
Planar64Vec3::new([(xs*yc).fix_1(),-ys,(xc*yc).fix_1()]),
|
||||||
//TODO: fix this rounding towards 0
|
])
|
||||||
let (xc,xs):(i64,i64)=(unsafe{xc.to_int_unchecked()},unsafe{xs.to_int_unchecked()});
|
|
||||||
let (yc,ys):(i64,i64)=(unsafe{yc.to_int_unchecked()},unsafe{ys.to_int_unchecked()});
|
|
||||||
Self::from_cols(
|
|
||||||
Planar64Vec3(glam::i64vec3(xc,0,-xs)),
|
|
||||||
Planar64Vec3(glam::i64vec3(((xs as i128*ys as i128)>>32) as i64,yc,((xc as i128*ys as i128)>>32) as i64)),
|
|
||||||
Planar64Vec3(glam::i64vec3(((xs as i128*yc as i128)>>32) as i64,-ys,((xc as i128*yc as i128)>>32) as i64)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rotation_y(angle:Angle32)->Self{
|
pub fn from_rotation_y(y:Angle32)->Planar64Mat3{
|
||||||
let theta=angle.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
let (c,s)=y.cos_sin();
|
||||||
let (s,c)=theta.sin_cos();
|
Planar64Mat3::from_cols([
|
||||||
let (c,s)=(c*PLANAR64_ONE_FLOAT64,s*PLANAR64_ONE_FLOAT64);
|
Planar64Vec3::new([c,Planar64::ZERO,-s]),
|
||||||
//TODO: fix this rounding towards 0
|
vec3::Y,
|
||||||
let (c,s):(i64,i64)=(unsafe{c.to_int_unchecked()},unsafe{s.to_int_unchecked()});
|
Planar64Vec3::new([s,Planar64::ZERO,c]),
|
||||||
Self::from_cols(
|
])
|
||||||
Planar64Vec3(glam::i64vec3(c,0,-s)),
|
|
||||||
Planar64Vec3::Y,
|
|
||||||
Planar64Vec3(glam::i64vec3(s,0,c)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn inverse(&self)->Self{
|
pub fn try_from_f32_array_2d([x_axis,y_axis,z_axis]:[[f32;3];3])->Result<Planar64Mat3,Planar64TryFromFloatError>{
|
||||||
let det=(
|
Ok(Planar64Mat3::new([
|
||||||
-self.x_axis.0.z as i128*self.y_axis.0.y as i128*self.z_axis.0.x as i128
|
vec3::try_from_f32_array(x_axis)?.to_array(),
|
||||||
+self.x_axis.0.y as i128*self.y_axis.0.z as i128*self.z_axis.0.x as i128
|
vec3::try_from_f32_array(y_axis)?.to_array(),
|
||||||
+self.x_axis.0.z as i128*self.y_axis.0.x as i128*self.z_axis.0.y as i128
|
vec3::try_from_f32_array(z_axis)?.to_array(),
|
||||||
-self.x_axis.0.x as i128*self.y_axis.0.z as i128*self.z_axis.0.y as i128
|
]))
|
||||||
-self.x_axis.0.y as i128*self.y_axis.0.x as i128*self.z_axis.0.z as i128
|
|
||||||
+self.x_axis.0.x as i128*self.y_axis.0.y as i128*self.z_axis.0.z as i128
|
|
||||||
)>>32;
|
|
||||||
Self{
|
|
||||||
x_axis:Planar64Vec3::raw_xyz((((-(self.y_axis.0.z as i128*self.z_axis.0.y as i128)+self.y_axis.0.y as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((self.x_axis.0.z as i128*self.z_axis.0.y as i128-self.x_axis.0.y as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((-(self.x_axis.0.z as i128*self.y_axis.0.y as i128)+self.x_axis.0.y as i128*self.y_axis.0.z as i128)<<32)/det) as i64),
|
|
||||||
y_axis:Planar64Vec3::raw_xyz((((self.y_axis.0.z as i128*self.z_axis.0.x as i128-self.y_axis.0.x as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((-(self.x_axis.0.z as i128*self.z_axis.0.x as i128)+self.x_axis.0.x as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((self.x_axis.0.z as i128*self.y_axis.0.x as i128-self.x_axis.0.x as i128*self.y_axis.0.z as i128)<<32)/det) as i64),
|
|
||||||
z_axis:Planar64Vec3::raw_xyz((((-(self.y_axis.0.y as i128*self.z_axis.0.x as i128)+self.y_axis.0.x as i128*self.z_axis.0.y as i128)<<32)/det) as i64,(((self.x_axis.0.y as i128*self.z_axis.0.x as i128-self.x_axis.0.x as i128*self.z_axis.0.y as i128)<<32)/det) as i64,(((-(self.x_axis.0.y as i128*self.y_axis.0.x as i128)+self.x_axis.0.x as i128*self.y_axis.0.y as i128)<<32)/det) as i64),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn inverse_times_det(&self)->Self{
|
|
||||||
Self{
|
|
||||||
x_axis:Planar64Vec3::raw_xyz(((-(self.y_axis.0.z as i128*self.z_axis.0.y as i128)+self.y_axis.0.y as i128*self.z_axis.0.z as i128)>>32) as i64,((self.x_axis.0.z as i128*self.z_axis.0.y as i128-self.x_axis.0.y as i128*self.z_axis.0.z as i128)>>32) as i64,((-(self.x_axis.0.z as i128*self.y_axis.0.y as i128)+self.x_axis.0.y as i128*self.y_axis.0.z as i128)>>32) as i64),
|
|
||||||
y_axis:Planar64Vec3::raw_xyz(((self.y_axis.0.z as i128*self.z_axis.0.x as i128-self.y_axis.0.x as i128*self.z_axis.0.z as i128)>>32) as i64,((-(self.x_axis.0.z as i128*self.z_axis.0.x as i128)+self.x_axis.0.x as i128*self.z_axis.0.z as i128)>>32) as i64,((self.x_axis.0.z as i128*self.y_axis.0.x as i128-self.x_axis.0.x as i128*self.y_axis.0.z as i128)>>32) as i64),
|
|
||||||
z_axis:Planar64Vec3::raw_xyz(((-(self.y_axis.0.y as i128*self.z_axis.0.x as i128)+self.y_axis.0.x as i128*self.z_axis.0.y as i128)>>32) as i64,((self.x_axis.0.y as i128*self.z_axis.0.x as i128-self.x_axis.0.x as i128*self.z_axis.0.y as i128)>>32) as i64,((-(self.x_axis.0.y as i128*self.y_axis.0.x as i128)+self.x_axis.0.x as i128*self.y_axis.0.y as i128)>>32) as i64),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn transpose(&self)->Self{
|
|
||||||
Self{
|
|
||||||
x_axis:Planar64Vec3::raw_xyz(self.x_axis.0.x,self.y_axis.0.x,self.z_axis.0.x),
|
|
||||||
y_axis:Planar64Vec3::raw_xyz(self.x_axis.0.y,self.y_axis.0.y,self.z_axis.0.y),
|
|
||||||
z_axis:Planar64Vec3::raw_xyz(self.x_axis.0.z,self.y_axis.0.z,self.z_axis.0.z),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub const fn determinant(&self)->Planar64{
|
|
||||||
Planar64(((
|
|
||||||
-self.x_axis.0.z as i128*self.y_axis.0.y as i128*self.z_axis.0.x as i128
|
|
||||||
+self.x_axis.0.y as i128*self.y_axis.0.z as i128*self.z_axis.0.x as i128
|
|
||||||
+self.x_axis.0.z as i128*self.y_axis.0.x as i128*self.z_axis.0.y as i128
|
|
||||||
-self.x_axis.0.x as i128*self.y_axis.0.z as i128*self.z_axis.0.y as i128
|
|
||||||
-self.x_axis.0.y as i128*self.y_axis.0.x as i128*self.z_axis.0.z as i128
|
|
||||||
+self.x_axis.0.x as i128*self.y_axis.0.y as i128*self.z_axis.0.z as i128
|
|
||||||
)>>64) as i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Into<glam::Mat3> for Planar64Mat3{
|
|
||||||
#[inline]
|
|
||||||
fn into(self)->glam::Mat3{
|
|
||||||
glam::Mat3::from_cols(
|
|
||||||
self.x_axis.into(),
|
|
||||||
self.y_axis.into(),
|
|
||||||
self.z_axis.into(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<glam::Mat3A> for Planar64Mat3{
|
|
||||||
type Error=Planar64TryFromFloatError;
|
|
||||||
#[inline]
|
|
||||||
fn try_from(value:glam::Mat3A)->Result<Self,Self::Error>{
|
|
||||||
Ok(Self{
|
|
||||||
x_axis:Planar64Vec3::try_from(value.x_axis)?,
|
|
||||||
y_axis:Planar64Vec3::try_from(value.y_axis)?,
|
|
||||||
z_axis:Planar64Vec3::try_from(value.z_axis)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::fmt::Display for Planar64Mat3{
|
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
|
||||||
write!(f,"\n{:.3},{:.3},{:.3}\n{:.3},{:.3},{:.3}\n{:.3},{:.3},{:.3}",
|
|
||||||
Into::<f32>::into(self.x_axis.x()),Into::<f32>::into(self.x_axis.y()),Into::<f32>::into(self.x_axis.z()),
|
|
||||||
Into::<f32>::into(self.y_axis.x()),Into::<f32>::into(self.y_axis.y()),Into::<f32>::into(self.y_axis.z()),
|
|
||||||
Into::<f32>::into(self.z_axis.x()),Into::<f32>::into(self.z_axis.y()),Into::<f32>::into(self.z_axis.z()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Mul<Planar64Vec3> for Planar64Mat3{
|
|
||||||
type Output=Planar64Vec3;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self,rhs:Planar64Vec3) -> Self::Output {
|
|
||||||
self.x_axis*rhs.x()
|
|
||||||
+self.y_axis*rhs.y()
|
|
||||||
+self.z_axis*rhs.z()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::ops::Div<i64> for Planar64Mat3{
|
|
||||||
type Output=Planar64Mat3;
|
|
||||||
#[inline]
|
|
||||||
fn div(self,rhs:i64)->Self::Output{
|
|
||||||
Planar64Mat3{
|
|
||||||
x_axis:self.x_axis/rhs,
|
|
||||||
y_axis:self.y_axis/rhs,
|
|
||||||
z_axis:self.z_axis/rhs,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
|
||||||
#[derive(Clone,Copy,Default,Hash,Eq,PartialEq)]
|
#[derive(Clone,Copy,Default,Hash,Eq,PartialEq)]
|
||||||
pub struct Planar64Affine3{
|
pub struct Planar64Affine3{
|
||||||
pub matrix3:Planar64Mat3,//includes scale above 1
|
pub matrix3:Planar64Mat3,//includes scale above 1
|
||||||
pub translation:Planar64Vec3,
|
pub translation:Planar64Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Planar64Affine3{
|
impl Planar64Affine3{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(matrix3:Planar64Mat3,translation:Planar64Vec3)->Self{
|
pub const fn new(matrix3:Planar64Mat3,translation:Planar64Vec3)->Self{
|
||||||
Self{matrix3,translation}
|
Self{matrix3,translation}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_point3(&self,point:Planar64Vec3) -> Planar64Vec3{
|
pub fn transform_point3(&self,point:Planar64Vec3)->vec3::Vector3<Fixed<2,64>>{
|
||||||
Planar64Vec3(
|
self.translation.fix_2()+self.matrix3*point
|
||||||
self.translation.0
|
|
||||||
+(self.matrix3.x_axis*point.x()).0
|
|
||||||
+(self.matrix3.y_axis*point.y()).0
|
|
||||||
+(self.matrix3.z_axis*point.z()).0
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Into<glam::Mat4> for Planar64Affine3{
|
impl Into<glam::Mat4> for Planar64Affine3{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self)->glam::Mat4{
|
fn into(self)->glam::Mat4{
|
||||||
|
let matrix3=self.matrix3.to_array().map(|row|row.map(Into::<f32>::into));
|
||||||
|
let translation=self.translation.to_array().map(Into::<f32>::into);
|
||||||
glam::Mat4::from_cols_array(&[
|
glam::Mat4::from_cols_array(&[
|
||||||
self.matrix3.x_axis.0.x as f32,self.matrix3.x_axis.0.y as f32,self.matrix3.x_axis.0.z as f32,0.0,
|
matrix3[0][0],matrix3[0][1],matrix3[0][2],0.0,
|
||||||
self.matrix3.y_axis.0.x as f32,self.matrix3.y_axis.0.y as f32,self.matrix3.y_axis.0.z as f32,0.0,
|
matrix3[1][0],matrix3[1][1],matrix3[1][2],0.0,
|
||||||
self.matrix3.z_axis.0.x as f32,self.matrix3.z_axis.0.y as f32,self.matrix3.z_axis.0.z as f32,0.0,
|
matrix3[2][0],matrix3[2][1],matrix3[2][2],0.0,
|
||||||
self.translation.0.x as f32,self.translation.0.y as f32,self.translation.0.z as f32,PLANAR64_ONE_FLOAT32
|
translation[0],translation[1],translation[2],1.0
|
||||||
])*PLANAR64_CONVERT_TO_FLOAT32
|
])
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<glam::Affine3A> for Planar64Affine3{
|
|
||||||
type Error=Planar64TryFromFloatError;
|
|
||||||
fn try_from(value: glam::Affine3A)->Result<Self, Self::Error> {
|
|
||||||
Ok(Self{
|
|
||||||
matrix3:Planar64Mat3::try_from(value.matrix3)?,
|
|
||||||
translation:Planar64Vec3::try_from(value.translation)?
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::fmt::Display for Planar64Affine3{
|
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
|
||||||
write!(f,"translation: {:.3},{:.3},{:.3}\nmatrix3:\n{:.3},{:.3},{:.3}\n{:.3},{:.3},{:.3}\n{:.3},{:.3},{:.3}",
|
|
||||||
Into::<f32>::into(self.translation.x()),Into::<f32>::into(self.translation.y()),Into::<f32>::into(self.translation.z()),
|
|
||||||
Into::<f32>::into(self.matrix3.x_axis.x()),Into::<f32>::into(self.matrix3.x_axis.y()),Into::<f32>::into(self.matrix3.x_axis.z()),
|
|
||||||
Into::<f32>::into(self.matrix3.y_axis.x()),Into::<f32>::into(self.matrix3.y_axis.y()),Into::<f32>::into(self.matrix3.y_axis.z()),
|
|
||||||
Into::<f32>::into(self.matrix3.z_axis.x()),Into::<f32>::into(self.matrix3.z_axis.y()),Into::<f32>::into(self.matrix3.z_axis.z()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqrt(){
|
fn test_sqrt(){
|
||||||
let r=Planar64::int(400);
|
let r=int(400);
|
||||||
assert_eq!(1717986918400,r.get());
|
assert_eq!(r,Planar64::raw(1717986918400));
|
||||||
let s=r.sqrt();
|
let s=r.sqrt();
|
||||||
assert_eq!(85899345920,s.get());
|
assert_eq!(s,Planar64::raw(85899345920));
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ pub mod aabb;
|
|||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod mouse;
|
pub mod mouse;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod zeroes;
|
|
||||||
pub mod integer;
|
pub mod integer;
|
||||||
pub mod physics;
|
pub mod physics;
|
||||||
pub mod updatable;
|
pub mod updatable;
|
||||||
|
10
src/timer.rs
10
src/timer.rs
@ -283,19 +283,19 @@ mod test{
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_timerfixed_scaled(){
|
fn test_timerfixed_scaled(){
|
||||||
//create a paused timer that reads 0s
|
//create a paused timer that reads 0s
|
||||||
let timer=TimerFixed::<Scaled,Paused>::new(sec!(0),sec!(0));
|
let timer=TimerFixed::<Scaled,Paused>::from_state(Scaled{scale:0.5f32.try_into().unwrap(),offset:sec!(0)});
|
||||||
//the paused timer at 1 second should read 0s
|
//the paused timer at 1 second should read 0s
|
||||||
assert_eq!(timer.time(sec!(1)),sec!(0));
|
assert_eq!(timer.time(sec!(1)),sec!(0));
|
||||||
|
|
||||||
//unpause it after one second
|
//unpause it after one second
|
||||||
let timer=timer.into_unpaused(sec!(1));
|
let timer=timer.into_unpaused(sec!(1));
|
||||||
//the timer at 6 seconds should read 5s
|
//the timer at 6 seconds should read 2.5s
|
||||||
assert_eq!(timer.time(sec!(6)),sec!(5));
|
assert_eq!(timer.time(sec!(6)),Time::from_millis(2500));
|
||||||
|
|
||||||
//pause the timer after 11 seconds
|
//pause the timer after 11 seconds
|
||||||
let timer=timer.into_paused(sec!(11));
|
let timer=timer.into_paused(sec!(11));
|
||||||
//the paused timer at 20 seconds should read 10s
|
//the paused timer at 20 seconds should read 5s
|
||||||
assert_eq!(timer.time(sec!(20)),sec!(10));
|
assert_eq!(timer.time(sec!(20)),sec!(5));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_timer()->Result<(),Error>{
|
fn test_timer()->Result<(),Error>{
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
//find roots of polynomials
|
|
||||||
use arrayvec::ArrayVec;
|
|
||||||
use crate::integer::Planar64;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn zeroes2(a0:Planar64,a1:Planar64,a2:Planar64)->ArrayVec<Planar64,2>{
|
|
||||||
if a2==Planar64::ZERO{
|
|
||||||
return zeroes1(a0,a1);
|
|
||||||
}
|
|
||||||
let radicand=a1.get() as i128*a1.get() as i128-a2.get() as i128*a0.get() as i128*4;
|
|
||||||
if 0<radicand{
|
|
||||||
//start with f64 sqrt
|
|
||||||
//failure case: 2^63 < sqrt(2^127)
|
|
||||||
let planar_radicand=Planar64::raw(unsafe{(radicand as f64).sqrt().to_int_unchecked()});
|
|
||||||
//TODO: one or two newtons
|
|
||||||
//sort roots ascending and avoid taking the difference of large numbers
|
|
||||||
match (Planar64::ZERO<a2,Planar64::ZERO<a1){
|
|
||||||
(true, true )=>[(-a1-planar_radicand)/(a2*2),(a0*2)/(-a1-planar_radicand)].into(),
|
|
||||||
(true, false)=>[(a0*2)/(-a1+planar_radicand),(-a1+planar_radicand)/(a2*2)].into(),
|
|
||||||
(false,true )=>[(a0*2)/(-a1-planar_radicand),(-a1-planar_radicand)/(a2*2)].into(),
|
|
||||||
(false,false)=>[(-a1+planar_radicand)/(a2*2),(a0*2)/(-a1+planar_radicand)].into(),
|
|
||||||
}
|
|
||||||
}else if radicand==0{
|
|
||||||
return ArrayVec::from_iter([a1/(a2*-2)]);
|
|
||||||
}else{
|
|
||||||
return ArrayVec::new_const();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn zeroes1(a0:Planar64,a1:Planar64)->ArrayVec<Planar64,2>{
|
|
||||||
if a1==Planar64::ZERO{
|
|
||||||
return ArrayVec::new_const();
|
|
||||||
}else{
|
|
||||||
let q=((-a0.get() as i128)<<32)/(a1.get() as i128);
|
|
||||||
if i64::MIN as i128<=q&&q<=i64::MAX as i128{
|
|
||||||
return ArrayVec::from_iter([Planar64::raw(q as i64)]);
|
|
||||||
}else{
|
|
||||||
return ArrayVec::new_const();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user