diff --git a/Cargo.lock b/Cargo.lock index 8a49600..45080d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "bitflags" @@ -14,6 +14,24 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "bnum" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50202def95bf36cb7d1d7a7962cea1c36a3f8ad42425e5d2b71d7acb8041b5b8" + +[[package]] +name = "fixed_wide" +version = "0.1.0" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "7a8d6e10c51c9df39ead915c62288afbc41d13e00368e526037e530ee5c58e13" +dependencies = [ + "arrayvec", + "bnum", + "paste", + "ratio_ops", +] + [[package]] name = "glam" version = "0.28.0" @@ -31,6 +49,23 @@ dependencies = [ "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]] name = "proc-macro2" version = "1.0.86" @@ -49,14 +84,23 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ratio_ops" +version = "0.1.0" +source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/" +checksum = "01239195d6afe0509e7e3511b716c0540251dfe7ece0a9a5a27116afb766c42c" + [[package]] name = "strafesnet_common" version = "0.4.1" dependencies = [ "arrayvec", "bitflags", + "fixed_wide", "glam", "id", + "linear_ops", + "ratio_ops", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a2072c3..8e50370 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,8 @@ authors = ["Rhys Lloyd "] [dependencies] arrayvec = "0.7.4" bitflags = "2.6.0" +fixed_wide = { version = "0.1.0", 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.28.0" id = { version = "0.1.0", registry = "strafesnet" } diff --git a/src/aabb.rs b/src/aabb.rs index 7494fc4..5e244d2 100644 --- a/src/aabb.rs +++ b/src/aabb.rs @@ -1,4 +1,4 @@ -use crate::integer::Planar64Vec3; +use crate::integer::{vec3,Planar64Vec3}; #[derive(Clone)] pub struct Aabb{ @@ -8,7 +8,7 @@ pub struct Aabb{ impl Default for Aabb{ 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; } 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{ self.max-self.min } 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 // pub fn area_weight(&self)->f32{ diff --git a/src/bvh.rs b/src/bvh.rs index c95e2e4..66d0b2e 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -126,9 +126,9 @@ fn generate_bvh_node(boxen:Vec<(T,Aabb)>,force:bool)->BvhNode{ let mut sort_z=Vec::with_capacity(n); for (i,(_,aabb)) in boxen.iter().enumerate(){ let center=aabb.center(); - 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.cmp(&tup1.1)); sort_y.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1)); diff --git a/src/gameplay_attributes.rs b/src/gameplay_attributes.rs index f600ab3..ff01731 100644 --- a/src/gameplay_attributes.rs +++ b/src/gameplay_attributes.rs @@ -38,10 +38,11 @@ impl Booster{ pub fn boost(&self,velocity:Planar64Vec3)->Planar64Vec3{ match self{ &Booster::Velocity(boost_velocity)=>velocity+boost_velocity, - &Booster::Energy{direction,energy}=>{ - let d=direction.dot(velocity); + &Booster::Energy{..}=>{ + todo!() + //let d=direction.dot(velocity); //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::Height(_)=>todo!(), diff --git a/src/gameplay_style.rs b/src/gameplay_style.rs index aec74c1..d56fa50 100644 --- a/src/gameplay_style.rs +++ b/src/gameplay_style.rs @@ -1,6 +1,6 @@ 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; #[derive(Clone,Debug)] @@ -65,19 +65,21 @@ impl JumpImpulse{ mass:Planar64, )->Planar64Vec3{ match self{ - &JumpImpulse::Time(time)=>velocity-*gravity*time, + &JumpImpulse::Time(time)=>velocity-(*gravity*time).map(|t|t.divide().fix_1()), &JumpImpulse::Height(height)=>{ //height==-v.y*v.y/(2*g.y); //use energy to determine max height - let g=gravity.length(); - let v_g=gravity.dot(velocity)/g; + let gg=gravity.length_squared(); + let g=gg.sqrt().fix_1(); + let v_g=gravity.dot(velocity); //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)=>{ //calculate energy - let e=gravity.dot(velocity); + //let e=gravity.dot(velocity); //add //you get the idea todo!() @@ -88,10 +90,10 @@ impl JumpImpulse{ 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 match self{ - &JumpImpulse::Time(time)=>gravity.length()*(time/2), - &JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt(), + &JumpImpulse::Time(time)=>(gravity.length().fix_1()*time/2).divide().fix_1(), + &JumpImpulse::Height(height)=>(gravity.length()*height*2).sqrt().fix_1(), &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, }; let j=boost_vel.dot(jump_dir); - if jrel_velocity, }; let j=boost_vel.dot(jump_dir); - if j{ @@ -154,9 +158,10 @@ impl JumpSettings{ None=>rel_velocity, }; let boost_dot=boost_vel.dot(jump_dir); - if boost_dotbooster.boost(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{ pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option{ let d=velocity.dot(control_dir); - match dSome(velocity+control_dir*self.air_accel_limit.map_or(self.mv-d,|limit|limit.min(self.mv-d))), + let mv=self.mv.fix_2(); + match dSome(velocity+(control_dir*self.air_accel_limit.map_or(mv-d,|limit|limit.fix_2().min(mv-d))).fix_1()), false=>None, } } @@ -283,7 +289,7 @@ pub struct PropulsionSettings{ } impl PropulsionSettings{ 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{ pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{ //TODO: fallible walk accel - let diff_len=target_diff.length(); + let diff_len=target_diff.length().fix_1(); let friction=if diff_lenPlanar64Vec3{ - if control_dir==Planar64Vec3::ZERO{ + if control_dir==crate::integer::vec3::ZERO{ return control_dir; } - let n=normal.length(); - let m=control_dir.length(); - let d=normal.dot(control_dir)/m; - if dbool{ //normal is not guaranteed to be unit length let ny=normal.dot(up); - let h=normal.length(); + let h=normal.length().fix_1(); //remember this is a normal vector - Planar64::ZEROPlanar64Vec3{ - if control_dir==Planar64Vec3::ZERO{ + if control_dir==crate::integer::vec3::ZERO{ return control_dir; } - let n=normal.length(); - let m=control_dir.length(); - let mut d=normal.dot(control_dir)/m; - if d< -self.dot*n{ - control_dir=Planar64Vec3::Y*m; - d=normal.y(); - }else if self.dot*nSelf{ Self{ - halfsize:Planar64Vec3::int(2,5,2)/2, + halfsize:int3(2,5,2)>>1, mesh:HitboxMesh::Cylinder, } } pub fn source()->Self{ Self{ - halfsize:Planar64Vec3::int(33,73,33)/2*VALVE_SCALE, + halfsize:((int3(33,73,33)>>1)*VALVE_SCALE).fix_1(), mesh:HitboxMesh::Box, } } } impl StyleModifiers{ - pub const RIGHT_DIR:Planar64Vec3=Planar64Vec3::X; - pub const UP_DIR:Planar64Vec3=Planar64Vec3::Y; - pub const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z; + pub const RIGHT_DIR:Planar64Vec3=crate::integer::vec3::X; + pub const UP_DIR:Planar64Vec3=crate::integer::vec3::Y; + pub const FORWARD_DIR:Planar64Vec3=crate::integer::vec3::NEG_Z; pub fn neo()->Self{ Self{ @@ -423,38 +434,38 @@ impl StyleModifiers{ strafe:Some(StrafeSettings{ enable:ControlsActivation::full_2d(), air_accel_limit:None, - mv:Planar64::int(3), + mv:int(3), tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(), }), jump:Some(JumpSettings{ - impulse:JumpImpulse::Energy(Planar64::int(512)), + impulse:JumpImpulse::Energy(int(512)), calculation:JumpCalculation::JumpThenBoost, limit_minimum:false, }), - gravity:Planar64Vec3::int(0,-80,0), - mass:Planar64::int(1), + gravity:int3(0,-80,0), + mass:int(1), rocket:None, walk:Some(WalkSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(16), - accel:Planar64::int(80), + topspeed:int(16), + accel:int(80), }, - static_friction:Planar64::int(2), - kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static - surf_dot:Planar64::int(3)/4, + static_friction:int(2), + kinetic_friction:int(3),//unrealistic: kinetic friction is typically lower than static + surf_dot:int(3)/4, }), ladder:Some(LadderSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(16), - accel:Planar64::int(160), + topspeed:int(16), + accel:int(160), }, - dot:(Planar64::int(1)/2).sqrt(), + dot:(int(1)/2).sqrt(), }), swim:Some(PropulsionSettings{ - magnitude:Planar64::int(12), + magnitude:int(12), }), 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{ enable:ControlsActivation::full_2d(), 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(), }), jump:Some(JumpSettings{ @@ -473,35 +484,35 @@ impl StyleModifiers{ calculation:JumpCalculation::Max, limit_minimum:true, }), - gravity:Planar64Vec3::int(0,-100,0), - mass:Planar64::int(1), + gravity:int3(0,-100,0), + mass:int(1), rocket:None, walk:Some(WalkSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(18), - accel:Planar64::int(90), + topspeed:int(18), + accel:int(90), }, - static_friction:Planar64::int(2), - kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static - surf_dot:Planar64::int(3)/4,// normal.y=0.75 + static_friction:int(2), + kinetic_friction:int(3),//unrealistic: kinetic friction is typically lower than static + surf_dot:int(3)/4,// normal.y=0.75 }), ladder:Some(LadderSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(18), - accel:Planar64::int(180), + topspeed:int(18), + accel:int(180), }, - dot:(Planar64::int(1)/2).sqrt(), + dot:(int(1)/2).sqrt(), }), swim:Some(PropulsionSettings{ - magnitude:Planar64::int(12), + magnitude:int(12), }), 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{ Self{ - gravity:Planar64Vec3::int(0,-50,0), + gravity:int3(0,-50,0), ..Self::roblox_bhop() } } @@ -509,7 +520,7 @@ impl StyleModifiers{ Self{ strafe:None, rocket:Some(PropulsionSettings{ - magnitude:Planar64::int(200), + magnitude:int(200), }), ..Self::roblox_bhop() } @@ -522,38 +533,38 @@ impl StyleModifiers{ strafe:Some(StrafeSettings{ enable:ControlsActivation::full_2d(), 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(), }), jump:Some(JumpSettings{ - impulse:JumpImpulse::Height(Planar64::int(52)*VALVE_SCALE), + impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()), calculation:JumpCalculation::JumpThenBoost, limit_minimum:true, }), - gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE, - mass:Planar64::int(1), + gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(), + mass:int(1), rocket:None, walk:Some(WalkSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(18),//? - accel:Planar64::int(90),//? + topspeed:int(18),//? + accel:int(90),//? }, - static_friction:Planar64::int(2),//? - kinetic_friction:Planar64::int(3),//? - surf_dot:Planar64::int(3)/4,// normal.y=0.75 + static_friction:int(2),//? + kinetic_friction:int(3),//? + surf_dot:int(3)/4,// normal.y=0.75 }), ladder:Some(LadderSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(18),//? - accel:Planar64::int(180),//? + topspeed:int(18),//? + accel:int(180),//? }, - dot:(Planar64::int(1)/2).sqrt(),//? + dot:(int(1)/2).sqrt(),//? }), swim:Some(PropulsionSettings{ - magnitude:Planar64::int(12),//? + magnitude:int(12),//? }), 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{ @@ -562,39 +573,39 @@ impl StyleModifiers{ controls_mask_state:Controls::all(), strafe:Some(StrafeSettings{ enable:ControlsActivation::full_2d(), - air_accel_limit:Some(Planar64::int(150)*66*VALVE_SCALE), - mv:Planar64::int(30)*VALVE_SCALE, + air_accel_limit:Some((int(150)*66*VALVE_SCALE).fix_1()), + mv:(int(30)*VALVE_SCALE).fix_1(), tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(), }), jump:Some(JumpSettings{ - impulse:JumpImpulse::Height(Planar64::int(52)*VALVE_SCALE), + impulse:JumpImpulse::Height((int(52)*VALVE_SCALE).fix_1()), calculation:JumpCalculation::JumpThenBoost, limit_minimum:true, }), - gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE, - mass:Planar64::int(1), + gravity:(int3(0,-800,0)*VALVE_SCALE).fix_1(), + mass:int(1), rocket:None, walk:Some(WalkSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(18),//? - accel:Planar64::int(90),//? + topspeed:int(18),//? + accel:int(90),//? }, - static_friction:Planar64::int(2),//? - kinetic_friction:Planar64::int(3),//? - surf_dot:Planar64::int(3)/4,// normal.y=0.75 + static_friction:int(2),//? + kinetic_friction:int(3),//? + surf_dot:int(3)/4,// normal.y=0.75 }), ladder:Some(LadderSettings{ accelerate:AccelerateSettings{ - topspeed:Planar64::int(18),//? - accel:Planar64::int(180),//? + topspeed:int(18),//? + accel:int(180),//? }, - dot:(Planar64::int(1)/2).sqrt(),//? + dot:(int(1)/2).sqrt(),//? }), swim:Some(PropulsionSettings{ - magnitude:Planar64::int(12),//? + magnitude:int(12),//? }), 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(), } } } diff --git a/src/integer.rs b/src/integer.rs index 377a097..887e1cf 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -1,3 +1,6 @@ +pub use fixed_wide::fixed::{Fixed,Fix}; +pub use ratio_ops::ratio::{Ratio,Divide}; + //integer units #[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)] pub struct Time(i64); @@ -38,11 +41,26 @@ impl Time{ pub const fn nanos(self)->i64{ self.0 } + #[inline] + pub const fn to_ratio(self)->Ratio{ + Ratio::new(Planar64::raw(self.0),Planar64::raw(1_000_000_000)) + } } impl From for Time{ #[inline] 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 From> for Time + where + Num:core::ops::Mul, + N1:Divide, + T1:Fix, +{ + #[inline] + fn from(value:Ratio)->Self{ + Time((value*Planar64::raw(1_000_000_000)).divide().fix().to_raw()) } } impl std::fmt::Display for Time{ @@ -63,34 +81,81 @@ impl std::ops::Neg for Time{ Time(-self.0) } } -impl std::ops::Add