forked from StrafesNET/strafe-project
Compare commits
1 Commits
the-wrong-
...
deduplicat
Author | SHA1 | Date | |
---|---|---|---|
e9bf4db43e |
@ -404,12 +404,11 @@ impl TryFrom<[f32;3]> for Unit32Vec3{
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy,Debug,Hash,Eq,Ord,PartialEq,PartialOrd)]
|
#[derive(Clone,Copy,Hash,Eq,Ord,PartialEq,PartialOrd)]
|
||||||
pub struct Planar64(i64);
|
pub struct Planar64(i64);
|
||||||
impl Planar64{
|
impl Planar64{
|
||||||
pub const ZERO:Self=Self(0);
|
pub const ZERO:Self=Self(0);
|
||||||
pub const ONE:Self=Self(1<<32);
|
pub const ONE:Self=Self(1<<32);
|
||||||
pub const FRAC_1_SQRT2:Self=Self(3_037_000_500);
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn int(num:i32)->Self{
|
pub const fn int(num:i32)->Self{
|
||||||
Self(Self::ONE.0*num as i64)
|
Self(Self::ONE.0*num as i64)
|
||||||
@ -532,14 +531,7 @@ impl std::ops::Mul<Planar64> for Planar64{
|
|||||||
type Output=Planar64;
|
type Output=Planar64;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
Planar64(((self.0 as i128*rhs.0 as i128)>>32) as i64)
|
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{
|
impl std::ops::Div<i64> for Planar64{
|
||||||
@ -564,7 +556,7 @@ impl std::ops::Div<Planar64> for Planar64{
|
|||||||
|
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy,Debug,Default,Hash,Eq,PartialEq)]
|
#[derive(Clone,Copy,Default,Hash,Eq,PartialEq)]
|
||||||
pub struct Planar64Vec3(glam::I64Vec3);
|
pub struct Planar64Vec3(glam::I64Vec3);
|
||||||
impl Planar64Vec3{
|
impl Planar64Vec3{
|
||||||
pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO);
|
pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO);
|
||||||
@ -582,10 +574,6 @@ impl Planar64Vec3{
|
|||||||
Self(glam::i64vec3((x as i64)<<32,(y as i64)<<32,(z as i64)<<32))
|
Self(glam::i64vec3((x as i64)<<32,(y as i64)<<32,(z as i64)<<32))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn raw(x:i64,y:i64,z:i64)->Self{
|
|
||||||
Self(glam::i64vec3(x,y,z))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn x(&self)->Planar64{
|
pub fn x(&self)->Planar64{
|
||||||
Planar64(self.0.x)
|
Planar64(self.0.x)
|
||||||
}
|
}
|
||||||
@ -630,14 +618,6 @@ impl Planar64Vec3{
|
|||||||
)>>32) as i64)
|
)>>32) as i64)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
/* pub fn cross(&self,rhs:Self)->Planar64Vec3{
|
|
||||||
Planar64Vec3(((
|
|
||||||
(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 fn length(&self)->Planar64{
|
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);
|
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()})
|
Planar64(unsafe{(radicand as f64).sqrt().to_int_unchecked()})
|
||||||
@ -828,23 +808,6 @@ impl Planar64Mat3{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rotation_yx(yaw:Angle32,pitch:Angle32)->Self{
|
|
||||||
let xtheta=yaw.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
|
||||||
let (xs,xc)=xtheta.sin_cos();
|
|
||||||
let (xc,xs)=(xc*PLANAR64_ONE_FLOAT64,xs*PLANAR64_ONE_FLOAT64);
|
|
||||||
let ytheta=pitch.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
|
||||||
let (ys,yc)=ytheta.sin_cos();
|
|
||||||
let (yc,ys)=(yc*PLANAR64_ONE_FLOAT64,ys*PLANAR64_ONE_FLOAT64);
|
|
||||||
//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]
|
|
||||||
pub fn from_rotation_y(angle:Angle32)->Self{
|
pub fn from_rotation_y(angle:Angle32)->Self{
|
||||||
let theta=angle.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
let theta=angle.0 as f64*ANGLE32_TO_FLOAT64_RADIANS;
|
||||||
let (s,c)=theta.sin_cos();
|
let (s,c)=theta.sin_cos();
|
||||||
|
@ -49,19 +49,9 @@ fn get_attributes(name:&str,can_collide:bool,velocity:Planar64Vec3,force_interse
|
|||||||
let mut intersecting=crate::model::IntersectingAttributes::default();
|
let mut intersecting=crate::model::IntersectingAttributes::default();
|
||||||
let mut contacting=crate::model::ContactingAttributes::default();
|
let mut contacting=crate::model::ContactingAttributes::default();
|
||||||
let mut force_can_collide=can_collide;
|
let mut force_can_collide=can_collide;
|
||||||
const GRAVITY:Planar64Vec3=Planar64Vec3::int(0,-100,0);
|
|
||||||
match name{
|
match name{
|
||||||
"Water"=>{
|
"Water"=>intersecting.water=Some(crate::model::IntersectingWater{density:Planar64::ONE,viscosity:Planar64::ONE/10,current:velocity}),
|
||||||
force_can_collide=false;
|
"Accelerator"=>{force_can_collide=false;intersecting.accelerator=Some(crate::model::IntersectingAccelerator{acceleration:velocity})},
|
||||||
//TODO: read stupid CustomPhysicalProperties
|
|
||||||
intersecting.water=Some(crate::model::IntersectingWater{density:Planar64::ONE,viscosity:Planar64::ONE/10,current:velocity});
|
|
||||||
},
|
|
||||||
"Accelerator"=>{
|
|
||||||
//although the new game supports collidable accelerators, this is a roblox compatability map loader
|
|
||||||
force_can_collide=false;
|
|
||||||
general.accelerator=Some(crate::model::GameMechanicAccelerator{acceleration:velocity});
|
|
||||||
},
|
|
||||||
"SetVelocity"=>general.trajectory=Some(crate::model::GameMechanicSetTrajectory::Velocity(velocity)),
|
|
||||||
"MapFinish"=>{force_can_collide=false;general.zone=Some(crate::model::GameMechanicZone{mode_id:0,behaviour:crate::model::ZoneBehaviour::Finish})},
|
"MapFinish"=>{force_can_collide=false;general.zone=Some(crate::model::GameMechanicZone{mode_id:0,behaviour:crate::model::ZoneBehaviour::Finish})},
|
||||||
"MapAnticheat"=>{force_can_collide=false;general.zone=Some(crate::model::GameMechanicZone{mode_id:0,behaviour:crate::model::ZoneBehaviour::Anitcheat})},
|
"MapAnticheat"=>{force_can_collide=false;general.zone=Some(crate::model::GameMechanicZone{mode_id:0,behaviour:crate::model::ZoneBehaviour::Anitcheat})},
|
||||||
"Platform"=>general.teleport_behaviour=Some(crate::model::TeleportBehaviour::StageElement(crate::model::GameMechanicStageElement{
|
"Platform"=>general.teleport_behaviour=Some(crate::model::TeleportBehaviour::StageElement(crate::model::GameMechanicStageElement{
|
||||||
@ -82,28 +72,12 @@ fn get_attributes(name:&str,can_collide:bool,velocity:Planar64Vec3,force_interse
|
|||||||
},
|
},
|
||||||
behaviour:match &captures[2]{
|
behaviour:match &captures[2]{
|
||||||
"Spawn"|"SpawnAt"=>crate::model::StageElementBehaviour::SpawnAt,
|
"Spawn"|"SpawnAt"=>crate::model::StageElementBehaviour::SpawnAt,
|
||||||
//cancollide false so you don't hit the side
|
|
||||||
//NOT a decoration
|
|
||||||
"Trigger"=>{force_can_collide=false;crate::model::StageElementBehaviour::Trigger},
|
"Trigger"=>{force_can_collide=false;crate::model::StageElementBehaviour::Trigger},
|
||||||
"Teleport"=>{force_can_collide=false;crate::model::StageElementBehaviour::Teleport},
|
"Teleport"=>{force_can_collide=false;crate::model::StageElementBehaviour::Teleport},
|
||||||
"Platform"=>crate::model::StageElementBehaviour::Platform,
|
"Platform"=>crate::model::StageElementBehaviour::Platform,
|
||||||
_=>panic!("regex1[2] messed up bad"),
|
_=>panic!("regex1[2] messed up bad"),
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}else if let Some(captures)=lazy_regex::regex!(r"^(Force)?(Jump)(\d+)$")
|
|
||||||
.captures(other){
|
|
||||||
general.teleport_behaviour=Some(crate::model::TeleportBehaviour::StageElement(crate::model::GameMechanicStageElement{
|
|
||||||
mode_id:0,
|
|
||||||
stage_id:0,
|
|
||||||
force:match captures.get(1){
|
|
||||||
Some(m)=>m.as_str()=="Force",
|
|
||||||
None=>false,
|
|
||||||
},
|
|
||||||
behaviour:match &captures[2]{
|
|
||||||
"Jump"=>crate::model::StageElementBehaviour::JumpLimit(captures[3].parse::<u32>().unwrap()),
|
|
||||||
_=>panic!("regex4[1] messed up bad"),
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}else if let Some(captures)=lazy_regex::regex!(r"^Bonus(Finish|Anticheat)(\d+)$")
|
}else if let Some(captures)=lazy_regex::regex!(r"^Bonus(Finish|Anticheat)(\d+)$")
|
||||||
.captures(other){
|
.captures(other){
|
||||||
force_can_collide=false;
|
force_can_collide=false;
|
||||||
@ -112,46 +86,39 @@ fn get_attributes(name:&str,can_collide:bool,velocity:Planar64Vec3,force_interse
|
|||||||
"Anticheat"=>general.zone=Some(crate::model::GameMechanicZone{mode_id:captures[2].parse::<u32>().unwrap(),behaviour:crate::model::ZoneBehaviour::Anitcheat}),
|
"Anticheat"=>general.zone=Some(crate::model::GameMechanicZone{mode_id:captures[2].parse::<u32>().unwrap(),behaviour:crate::model::ZoneBehaviour::Anitcheat}),
|
||||||
_=>panic!("regex2[1] messed up bad"),
|
_=>panic!("regex2[1] messed up bad"),
|
||||||
}
|
}
|
||||||
}else if let Some(captures)=lazy_regex::regex!(r"^(WormholeIn)(\d+)$")
|
|
||||||
.captures(other){
|
|
||||||
force_can_collide=false;
|
|
||||||
match &captures[1]{
|
|
||||||
"WormholeIn"=>general.teleport_behaviour=Some(crate::model::TeleportBehaviour::Wormhole(crate::model::GameMechanicWormhole{destination_model_id:captures[2].parse::<u32>().unwrap()})),
|
|
||||||
_=>panic!("regex3[1] messed up bad"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//need some way to skip this
|
//need some way to skip this
|
||||||
if velocity!=Planar64Vec3::ZERO{
|
if velocity!=Planar64Vec3::ZERO{
|
||||||
//assume all vertical boosters are targetting a height
|
general.booster=Some(crate::model::GameMechanicBooster{velocity});
|
||||||
let vg=velocity.dot(GRAVITY);
|
|
||||||
if Planar64::ZERO<=vg{
|
|
||||||
//weird down booster
|
|
||||||
general.booster=Some(crate::model::GameMechanicBooster::Velocity(velocity));
|
|
||||||
}else{
|
|
||||||
println!("set attr");
|
|
||||||
let gg=GRAVITY.dot(GRAVITY);
|
|
||||||
let height=-vg*gg.sqrt().sqrt()*Planar64::FRAC_1_SQRT2/gg;//vi/sqrt(-2*a)=d
|
|
||||||
let v=velocity-GRAVITY*(vg/gg);
|
|
||||||
//if we are adding zero SO BE IT, the check to see if the vectors are parallel is too sensitive
|
|
||||||
general.booster=Some(crate::model::GameMechanicBooster::Velocity(v));
|
|
||||||
general.trajectory=Some(crate::model::GameMechanicSetTrajectory::Height(height));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
match force_can_collide{
|
match force_can_collide{
|
||||||
true=>{
|
true=>{
|
||||||
match name{
|
match name{
|
||||||
"Bounce"=>contacting.contact_behaviour=Some(crate::model::ContactingBehaviour::Elastic(u32::MAX)),
|
"Bounce"=>contacting.elasticity=Some(u32::MAX),
|
||||||
"Surf"=>contacting.contact_behaviour=Some(crate::model::ContactingBehaviour::Surf),
|
"Surf"=>contacting.surf=Some(crate::model::ContactingSurf{}),
|
||||||
"Ladder"=>contacting.contact_behaviour=Some(crate::model::ContactingBehaviour::Ladder(crate::model::ContactingLadder{sticky:true})),
|
"Ladder"=>contacting.ladder=Some(crate::model::ContactingLadder{sticky:true}),
|
||||||
_=>(),
|
other=>{
|
||||||
|
if let Some(captures)=lazy_regex::regex!(r"^(Jump|WormholeIn)(\d+)$")
|
||||||
|
.captures(other){
|
||||||
|
match &captures[1]{
|
||||||
|
"Jump"=>general.jump_limit=Some(crate::model::GameMechanicJumpLimit{count:captures[2].parse::<u32>().unwrap()}),
|
||||||
|
"WormholeIn"=>general.teleport_behaviour=Some(crate::model::TeleportBehaviour::Wormhole(crate::model::GameMechanicWormhole{destination_model_id:captures[2].parse::<u32>().unwrap()})),
|
||||||
|
_=>panic!("regex3[1] messed up bad"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
crate::model::CollisionAttributes::Contact{contacting,general}
|
crate::model::CollisionAttributes::Contact{contacting,general}
|
||||||
},
|
},
|
||||||
false=>if force_intersecting
|
false=>if force_intersecting
|
||||||
||general.any()
|
||general.jump_limit.is_some()
|
||||||
||intersecting.any()
|
||general.booster.is_some()
|
||||||
|
||general.zone.is_some()
|
||||||
|
||general.teleport_behaviour.is_some()
|
||||||
|
||intersecting.water.is_some()
|
||||||
|
||intersecting.accelerator.is_some()
|
||||||
{
|
{
|
||||||
crate::model::CollisionAttributes::Intersect{intersecting,general}
|
crate::model::CollisionAttributes::Intersect{intersecting,general}
|
||||||
}else{
|
}else{
|
||||||
|
91
src/main.rs
91
src/main.rs
@ -234,10 +234,6 @@ impl GlobalState{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
//skip pushing a model if all instances are invisible
|
|
||||||
if instances.len()==0{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//check each group, if it's using a new texture then make a new clone of the model
|
//check each group, if it's using a new texture then make a new clone of the model
|
||||||
let id=unique_texture_models.len();
|
let id=unique_texture_models.len();
|
||||||
let mut unique_textures=Vec::new();
|
let mut unique_textures=Vec::new();
|
||||||
@ -305,24 +301,27 @@ impl GlobalState{
|
|||||||
model_instance_list.push((model_id,instance_id));
|
model_instance_list.push((model_id,instance_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//populate a hashset of models selected for transposition
|
//populate a hashmap of models selected for transposition
|
||||||
//construct transposed models
|
|
||||||
let mut selected_model_instances=std::collections::HashSet::new();
|
let mut selected_model_instances=std::collections::HashSet::new();
|
||||||
for (texture,unique_color) in unique_texture_color.into_iter(){
|
for (texture,unique_color) in unique_texture_color.into_iter(){
|
||||||
for (color,model_instance_list) in unique_color.into_iter(){
|
for (color,model_instance_list) in unique_color.into_iter(){
|
||||||
//world transforming one model does not meet the definition of deduplicaiton
|
|
||||||
if 1<model_instance_list.len(){
|
if 1<model_instance_list.len(){
|
||||||
//create model
|
//create model
|
||||||
let mut unique_pos=Vec::new();
|
let mut unique_pos=Vec::new();
|
||||||
let mut pos_id_from=std::collections::HashMap::new();
|
let mut pos_id_from=std::collections::HashMap::new();
|
||||||
|
let mut map_pos_id=std::collections::HashMap::new();
|
||||||
let mut unique_tex=Vec::new();
|
let mut unique_tex=Vec::new();
|
||||||
let mut tex_id_from=std::collections::HashMap::new();
|
let mut tex_id_from=std::collections::HashMap::new();
|
||||||
|
let mut map_tex_id=std::collections::HashMap::new();
|
||||||
let mut unique_normal=Vec::new();
|
let mut unique_normal=Vec::new();
|
||||||
let mut normal_id_from=std::collections::HashMap::new();
|
let mut normal_id_from=std::collections::HashMap::new();
|
||||||
|
let mut map_normal_id=std::collections::HashMap::new();
|
||||||
let mut unique_color=Vec::new();
|
let mut unique_color=Vec::new();
|
||||||
let mut color_id_from=std::collections::HashMap::new();
|
let mut color_id_from=std::collections::HashMap::new();
|
||||||
|
let mut map_color_id=std::collections::HashMap::new();
|
||||||
let mut unique_vertices=Vec::new();
|
let mut unique_vertices=Vec::new();
|
||||||
let mut vertex_id_from=std::collections::HashMap::new();
|
let mut vertex_id_from=std::collections::HashMap::new();
|
||||||
|
let mut map_vertex_id=std::collections::HashMap::new();
|
||||||
|
|
||||||
let mut polys=Vec::new();
|
let mut polys=Vec::new();
|
||||||
//transform instance vertices
|
//transform instance vertices
|
||||||
@ -333,73 +332,78 @@ impl GlobalState{
|
|||||||
let model=&unique_texture_models[model_id];
|
let model=&unique_texture_models[model_id];
|
||||||
let instance=&model.instances[instance_id];
|
let instance=&model.instances[instance_id];
|
||||||
//just hash word slices LOL
|
//just hash word slices LOL
|
||||||
let map_pos_id:Vec<u32>=model.unique_pos.iter().map(|untransformed_pos|{
|
for (old_pos_id,untransformed_pos) in model.unique_pos.iter().enumerate(){
|
||||||
let pos=instance.transform.transform_point3(glam::Vec3::from_array(untransformed_pos.clone())).to_array();
|
let pos=instance.transform.transform_point3(glam::Vec3::from_array(untransformed_pos.clone())).to_array();
|
||||||
let h=pos.map(|v|bytemuck::cast::<f32,u32>(v));
|
let h=pos.map(|v|u32::from_ne_bytes(v.to_ne_bytes()));
|
||||||
(if let Some(&pos_id)=pos_id_from.get(&h){
|
let pos_id=if let Some(&pos_id)=pos_id_from.get(&h){
|
||||||
pos_id
|
pos_id
|
||||||
}else{
|
}else{
|
||||||
let pos_id=unique_pos.len();
|
let pos_id=unique_pos.len();
|
||||||
unique_pos.push(pos.clone());
|
unique_pos.push(pos.clone());
|
||||||
pos_id_from.insert(h,pos_id);
|
pos_id_from.insert(h,pos_id);
|
||||||
pos_id
|
pos_id
|
||||||
}) as u32
|
};
|
||||||
}).collect();
|
map_pos_id.insert(old_pos_id,pos_id);
|
||||||
let map_tex_id:Vec<u32>=model.unique_tex.iter().map(|tex|{
|
}
|
||||||
let h=tex.map(|v|bytemuck::cast::<f32,u32>(v));
|
for (old_tex_id,tex) in model.unique_tex.iter().enumerate(){
|
||||||
(if let Some(&tex_id)=tex_id_from.get(&h){
|
let h=tex.map(|v|u32::from_ne_bytes(v.to_ne_bytes()));
|
||||||
|
let tex_id=if let Some(&tex_id)=tex_id_from.get(&h){
|
||||||
tex_id
|
tex_id
|
||||||
}else{
|
}else{
|
||||||
let tex_id=unique_tex.len();
|
let tex_id=unique_tex.len();
|
||||||
unique_tex.push(tex.clone());
|
unique_tex.push(tex.clone());
|
||||||
tex_id_from.insert(h,tex_id);
|
tex_id_from.insert(h,tex_id);
|
||||||
tex_id
|
tex_id
|
||||||
}) as u32
|
};
|
||||||
}).collect();
|
map_tex_id.insert(old_tex_id,tex_id);
|
||||||
let map_normal_id:Vec<u32>=model.unique_normal.iter().map(|untransformed_normal|{
|
}
|
||||||
|
for (old_normal_id,untransformed_normal) in model.unique_normal.iter().enumerate(){
|
||||||
let normal=(instance.normal_transform*glam::Vec3::from_array(untransformed_normal.clone())).to_array();
|
let normal=(instance.normal_transform*glam::Vec3::from_array(untransformed_normal.clone())).to_array();
|
||||||
let h=normal.map(|v|bytemuck::cast::<f32,u32>(v));
|
let h=normal.map(|v|u32::from_ne_bytes(v.to_ne_bytes()));
|
||||||
(if let Some(&normal_id)=normal_id_from.get(&h){
|
let normal_id=if let Some(&normal_id)=normal_id_from.get(&h){
|
||||||
normal_id
|
normal_id
|
||||||
}else{
|
}else{
|
||||||
let normal_id=unique_normal.len();
|
let normal_id=unique_normal.len();
|
||||||
unique_normal.push(normal.clone());
|
unique_normal.push(normal.clone());
|
||||||
normal_id_from.insert(h,normal_id);
|
normal_id_from.insert(h,normal_id);
|
||||||
normal_id
|
normal_id
|
||||||
}) as u32
|
};
|
||||||
}).collect();
|
map_normal_id.insert(old_normal_id,normal_id);
|
||||||
let map_color_id:Vec<u32>=model.unique_color.iter().map(|color|{
|
}
|
||||||
let h=color.map(|v|bytemuck::cast::<f32,u32>(v));
|
for (old_color_id,color) in model.unique_color.iter().enumerate(){
|
||||||
(if let Some(&color_id)=color_id_from.get(&h){
|
let h=color.map(|v|u32::from_ne_bytes(v.to_ne_bytes()));
|
||||||
|
let color_id=if let Some(&color_id)=color_id_from.get(&h){
|
||||||
color_id
|
color_id
|
||||||
}else{
|
}else{
|
||||||
let color_id=unique_color.len();
|
let color_id=unique_color.len();
|
||||||
unique_color.push(color.clone());
|
unique_color.push(color.clone());
|
||||||
color_id_from.insert(h,color_id);
|
color_id_from.insert(h,color_id);
|
||||||
color_id
|
color_id
|
||||||
}) as u32
|
};
|
||||||
}).collect();
|
map_color_id.insert(old_color_id,color_id);
|
||||||
|
}
|
||||||
//map the indexed vertices onto new indices
|
//map the indexed vertices onto new indices
|
||||||
//creating the vertex map is slightly different because the vertices are directly hashable
|
//creating the vertex map is slightly different because the vertices are directly hashable
|
||||||
let map_vertex_id:Vec<u32>=model.unique_vertices.iter().map(|unmapped_vertex|{
|
for (old_vertex_id,unmapped_vertex) in model.unique_vertices.iter().enumerate(){
|
||||||
let vertex=model::IndexedVertex{
|
let vertex=model::IndexedVertex{
|
||||||
pos:map_pos_id[unmapped_vertex.pos as usize] as u32,
|
pos:map_pos_id[&(unmapped_vertex.pos as usize)] as u32,
|
||||||
tex:map_tex_id[unmapped_vertex.tex as usize] as u32,
|
tex:map_tex_id[&(unmapped_vertex.tex as usize)] as u32,
|
||||||
normal:map_normal_id[unmapped_vertex.normal as usize] as u32,
|
normal:map_normal_id[&(unmapped_vertex.normal as usize)] as u32,
|
||||||
color:map_color_id[unmapped_vertex.color as usize] as u32,
|
color:map_color_id[&(unmapped_vertex.color as usize)] as u32,
|
||||||
};
|
};
|
||||||
(if let Some(&vertex_id)=vertex_id_from.get(&vertex){
|
let vertex_id=if let Some(&vertex_id)=vertex_id_from.get(&vertex){
|
||||||
vertex_id
|
vertex_id
|
||||||
}else{
|
}else{
|
||||||
let vertex_id=unique_vertices.len();
|
let vertex_id=unique_vertices.len();
|
||||||
unique_vertices.push(vertex.clone());
|
unique_vertices.push(vertex.clone());
|
||||||
vertex_id_from.insert(vertex,vertex_id);
|
vertex_id_from.insert(vertex,vertex_id);
|
||||||
vertex_id
|
vertex_id
|
||||||
}) as u32
|
};
|
||||||
}).collect();
|
map_vertex_id.insert(old_vertex_id as u32,vertex_id as u32);
|
||||||
|
}
|
||||||
for group in &model.groups{
|
for group in &model.groups{
|
||||||
for poly in &group.polys{
|
for poly in &group.polys{
|
||||||
polys.push(model::IndexedPolygon{vertices:poly.vertices.iter().map(|&vertex_id|map_vertex_id[vertex_id as usize]).collect()});
|
polys.push(model::IndexedPolygon{vertices:poly.vertices.iter().map(|vertex_id|map_vertex_id[vertex_id]).collect()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,6 +427,7 @@ impl GlobalState{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//construct transposed models
|
||||||
//fill untouched models
|
//fill untouched models
|
||||||
for (model_id,model) in unique_texture_models.into_iter().enumerate(){
|
for (model_id,model) in unique_texture_models.into_iter().enumerate(){
|
||||||
if !selected_model_instances.contains(&model_id){
|
if !selected_model_instances.contains(&model_id){
|
||||||
@ -431,8 +436,8 @@ impl GlobalState{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//de-index models
|
//de-index models
|
||||||
let deduplicated_models_len=deduplicated_models.len();
|
let mut models=Vec::with_capacity(indexed_models_len);
|
||||||
let models:Vec<model_graphics::ModelGraphicsSingleTexture>=deduplicated_models.into_iter().map(|model|{
|
for model in deduplicated_models.into_iter(){
|
||||||
let mut vertices = Vec::new();
|
let mut vertices = Vec::new();
|
||||||
let mut index_from_vertex = std::collections::HashMap::new();//::<IndexedVertex,usize>
|
let mut index_from_vertex = std::collections::HashMap::new();//::<IndexedVertex,usize>
|
||||||
let mut entities = Vec::new();
|
let mut entities = Vec::new();
|
||||||
@ -462,13 +467,13 @@ impl GlobalState{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
entities.push(indices);
|
entities.push(indices);
|
||||||
model_graphics::ModelGraphicsSingleTexture{
|
models.push(model_graphics::ModelGraphicsSingleTexture{
|
||||||
instances:model.instances,
|
instances:model.instances,
|
||||||
vertices,
|
vertices,
|
||||||
entities,
|
entities,
|
||||||
texture:model.texture,
|
texture:model.texture,
|
||||||
}
|
});
|
||||||
}).collect();
|
}
|
||||||
//.into_iter() the modeldata vec so entities can be /moved/ to models.entities
|
//.into_iter() the modeldata vec so entities can be /moved/ to models.entities
|
||||||
let mut model_count=0;
|
let mut model_count=0;
|
||||||
let mut instance_count=0;
|
let mut instance_count=0;
|
||||||
@ -540,7 +545,6 @@ impl GlobalState{
|
|||||||
println!("Texture References={}",num_textures);
|
println!("Texture References={}",num_textures);
|
||||||
println!("Textures Loaded={}",texture_views.len());
|
println!("Textures Loaded={}",texture_views.len());
|
||||||
println!("Indexed Models={}",indexed_models_len);
|
println!("Indexed Models={}",indexed_models_len);
|
||||||
println!("Deduplicated Models={}",deduplicated_models_len);
|
|
||||||
println!("Graphics Objects: {}",self.graphics.models.len());
|
println!("Graphics Objects: {}",self.graphics.models.len());
|
||||||
println!("Graphics Instances: {}",instance_count);
|
println!("Graphics Instances: {}",instance_count);
|
||||||
}
|
}
|
||||||
@ -931,7 +935,7 @@ impl framework::Example for GlobalState {
|
|||||||
let screen_size=glam::uvec2(config.width,config.height);
|
let screen_size=glam::uvec2(config.width,config.height);
|
||||||
|
|
||||||
let camera=GraphicsCamera::new(screen_size,user_settings.calculate_fov(1.0,&screen_size).as_vec2());
|
let camera=GraphicsCamera::new(screen_size,user_settings.calculate_fov(1.0,&screen_size).as_vec2());
|
||||||
let camera_uniforms = camera.to_uniform_data(physics.output().adjust_mouse(&physics::MouseState::default()));
|
let camera_uniforms = camera.to_uniform_data(physics.output().adjust_mouse(&physics.next_mouse));
|
||||||
let camera_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let camera_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("Camera"),
|
label: Some("Camera"),
|
||||||
contents: bytemuck::cast_slice(&camera_uniforms),
|
contents: bytemuck::cast_slice(&camera_uniforms),
|
||||||
@ -1063,7 +1067,6 @@ impl framework::Example for GlobalState {
|
|||||||
self.graphics.clear();
|
self.graphics.clear();
|
||||||
|
|
||||||
let mut physics=physics::PhysicsState::default();
|
let mut physics=physics::PhysicsState::default();
|
||||||
//physics.spawn()
|
|
||||||
physics.game.stage_id=0;
|
physics.game.stage_id=0;
|
||||||
physics.spawn_point=spawn_point;
|
physics.spawn_point=spawn_point;
|
||||||
physics.process_instruction(instruction::TimedInstruction{
|
physics.process_instruction(instruction::TimedInstruction{
|
||||||
|
82
src/model.rs
82
src/model.rs
@ -1,4 +1,4 @@
|
|||||||
use crate::integer::{Time,Planar64,Planar64Vec3,Planar64Affine3};
|
use crate::integer::{Planar64,Planar64Vec3,Planar64Affine3};
|
||||||
pub type TextureCoordinate=glam::Vec2;
|
pub type TextureCoordinate=glam::Vec2;
|
||||||
pub type Color4=glam::Vec4;
|
pub type Color4=glam::Vec4;
|
||||||
#[derive(Clone,Hash,PartialEq,Eq)]
|
#[derive(Clone,Hash,PartialEq,Eq)]
|
||||||
@ -92,15 +92,11 @@ pub enum TempIndexedAttributes{
|
|||||||
|
|
||||||
//you have this effect while in contact
|
//you have this effect while in contact
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
pub struct ContactingSurf{}
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ContactingLadder{
|
pub struct ContactingLadder{
|
||||||
pub sticky:bool
|
pub sticky:bool
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum ContactingBehaviour{
|
|
||||||
Surf,
|
|
||||||
Ladder(ContactingLadder),
|
|
||||||
Elastic(u32),//[1/2^32,1] 0=None (elasticity+1)/2^32
|
|
||||||
}
|
|
||||||
//you have this effect while intersecting
|
//you have this effect while intersecting
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IntersectingWater{
|
pub struct IntersectingWater{
|
||||||
@ -108,37 +104,18 @@ pub struct IntersectingWater{
|
|||||||
pub density:Planar64,
|
pub density:Planar64,
|
||||||
pub current:Planar64Vec3,
|
pub current:Planar64Vec3,
|
||||||
}
|
}
|
||||||
//All models can be given these attributes
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GameMechanicAccelerator{
|
pub struct IntersectingAccelerator{
|
||||||
pub acceleration:Planar64Vec3
|
pub acceleration:Planar64Vec3
|
||||||
}
|
}
|
||||||
|
//All models can be given these attributes
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum GameMechanicBooster{
|
pub struct GameMechanicJumpLimit{
|
||||||
Affine(Planar64Affine3),//capable of SetVelocity,DotVelocity,normal booster,bouncy part,redirect velocity, and much more
|
pub count:u32,
|
||||||
Velocity(Planar64Vec3),//straight up boost velocity adds to your current velocity
|
|
||||||
Energy{direction:Planar64Vec3,energy:Planar64},//increase energy in direction
|
|
||||||
}
|
}
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone)]
|
||||||
pub enum TrajectoryChoice{
|
pub struct GameMechanicBooster{
|
||||||
HighArcLongDuration,//underhand lob at target: less horizontal speed and more air time
|
pub velocity:Planar64Vec3,
|
||||||
LowArcShortDuration,//overhand throw at target: more horizontal speed and less air time
|
|
||||||
}
|
|
||||||
#[derive(Clone,Debug)]
|
|
||||||
pub enum GameMechanicSetTrajectory{
|
|
||||||
AirTime(Time),//air time (relative to gravity direction) is invariant across mass and gravity changes
|
|
||||||
Height(Planar64),//boost height (relative to gravity direction) is invariant across mass and gravity changes
|
|
||||||
TargetPointTime{//launch on a trajectory that will land at a target point in a set amount of time
|
|
||||||
target_point:Planar64Vec3,
|
|
||||||
time:Time,//short time = fast and direct, long time = launch high in the air, negative time = wrong way
|
|
||||||
},
|
|
||||||
TrajectoryTargetPoint{//launch at a fixed speed and land at a target point
|
|
||||||
target_point:Planar64Vec3,
|
|
||||||
speed:Planar64,//if speed is too low this will fail to reach the target. The closest-passing trajectory will be chosen instead
|
|
||||||
trajectory_choice:TrajectoryChoice,
|
|
||||||
},
|
|
||||||
Velocity(Planar64Vec3),//SetVelocity
|
|
||||||
DotVelocity{direction:Planar64Vec3,dot:Planar64},//set your velocity in a specific direction without touching other directions
|
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ZoneBehaviour{
|
pub enum ZoneBehaviour{
|
||||||
@ -153,10 +130,10 @@ pub struct GameMechanicZone{
|
|||||||
pub behaviour:ZoneBehaviour,
|
pub behaviour:ZoneBehaviour,
|
||||||
}
|
}
|
||||||
// enum TrapCondition{
|
// enum TrapCondition{
|
||||||
// FasterThan(Planar64),
|
// FasterThan(i64),
|
||||||
// SlowerThan(Planar64),
|
// SlowerThan(i64),
|
||||||
// InRange(Planar64,Planar64),
|
// InRange(i64,i64),
|
||||||
// OutsideRange(Planar64,Planar64),
|
// OutsideRange(i64,i64),
|
||||||
// }
|
// }
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum StageElementBehaviour{
|
pub enum StageElementBehaviour{
|
||||||
@ -165,7 +142,6 @@ pub enum StageElementBehaviour{
|
|||||||
Trigger,
|
Trigger,
|
||||||
Teleport,
|
Teleport,
|
||||||
Platform,
|
Platform,
|
||||||
JumpLimit(u32),
|
|
||||||
//Speedtrap(TrapCondition),//Acts as a trigger with a speed condition
|
//Speedtrap(TrapCondition),//Acts as a trigger with a speed condition
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -188,42 +164,24 @@ pub enum TeleportBehaviour{
|
|||||||
StageElement(GameMechanicStageElement),
|
StageElement(GameMechanicStageElement),
|
||||||
Wormhole(GameMechanicWormhole),
|
Wormhole(GameMechanicWormhole),
|
||||||
}
|
}
|
||||||
//attributes listed in order of handling
|
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone)]
|
||||||
pub struct GameMechanicAttributes{
|
pub struct GameMechanicAttributes{
|
||||||
pub zone:Option<GameMechanicZone>,
|
pub jump_limit:Option<GameMechanicJumpLimit>,
|
||||||
pub booster:Option<GameMechanicBooster>,
|
pub booster:Option<GameMechanicBooster>,
|
||||||
pub trajectory:Option<GameMechanicSetTrajectory>,
|
pub zone:Option<GameMechanicZone>,
|
||||||
pub teleport_behaviour:Option<TeleportBehaviour>,
|
pub teleport_behaviour:Option<TeleportBehaviour>,
|
||||||
pub accelerator:Option<GameMechanicAccelerator>,
|
|
||||||
}
|
|
||||||
impl GameMechanicAttributes{
|
|
||||||
pub fn any(&self)->bool{
|
|
||||||
self.booster.is_some()
|
|
||||||
||self.trajectory.is_some()
|
|
||||||
||self.zone.is_some()
|
|
||||||
||self.teleport_behaviour.is_some()
|
|
||||||
||self.accelerator.is_some()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone)]
|
||||||
pub struct ContactingAttributes{
|
pub struct ContactingAttributes{
|
||||||
|
pub elasticity:Option<u32>,//[1/2^32,1] 0=None (elasticity+1)/2^32
|
||||||
//friction?
|
//friction?
|
||||||
pub contact_behaviour:Option<ContactingBehaviour>,
|
pub surf:Option<ContactingSurf>,
|
||||||
}
|
pub ladder:Option<ContactingLadder>,
|
||||||
impl ContactingAttributes{
|
|
||||||
pub fn any(&self)->bool{
|
|
||||||
self.contact_behaviour.is_some()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone)]
|
||||||
pub struct IntersectingAttributes{
|
pub struct IntersectingAttributes{
|
||||||
pub water:Option<IntersectingWater>,
|
pub water:Option<IntersectingWater>,
|
||||||
}
|
pub accelerator:Option<IntersectingAccelerator>,
|
||||||
impl IntersectingAttributes{
|
|
||||||
pub fn any(&self)->bool{
|
|
||||||
self.water.is_some()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//Spawn(u32) NO! spawns are indexed in the map header instead of marked with attibutes
|
//Spawn(u32) NO! spawns are indexed in the map header instead of marked with attibutes
|
||||||
pub enum CollisionAttributes{
|
pub enum CollisionAttributes{
|
||||||
|
@ -42,7 +42,7 @@ impl From<glam::Vec4> for ModelGraphicsColor4{
|
|||||||
impl std::hash::Hash for ModelGraphicsColor4{
|
impl std::hash::Hash for ModelGraphicsColor4{
|
||||||
fn hash<H: std::hash::Hasher>(&self,state:&mut H) {
|
fn hash<H: std::hash::Hasher>(&self,state:&mut H) {
|
||||||
for &f in self.0.as_ref(){
|
for &f in self.0.as_ref(){
|
||||||
bytemuck::cast::<f32,u32>(f).hash(state);
|
u32::from_ne_bytes(f.to_ne_bytes()).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
613
src/physics.rs
613
src/physics.rs
@ -115,62 +115,24 @@ impl MouseState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum WalkEnum{
|
pub enum WalkEnum{
|
||||||
Reached,
|
Reached,
|
||||||
Transient(WalkTarget),
|
Transient,
|
||||||
}
|
}
|
||||||
struct WalkTarget{
|
pub struct WalkState {
|
||||||
velocity:Planar64Vec3,
|
pub target_velocity: Planar64Vec3,
|
||||||
time:Time,
|
pub target_time: Time,
|
||||||
|
pub state: WalkEnum,
|
||||||
}
|
}
|
||||||
struct WalkState{
|
impl WalkState {
|
||||||
normal:Planar64Vec3,
|
pub fn new() -> Self {
|
||||||
state:WalkEnum,
|
Self{
|
||||||
}
|
target_velocity:Planar64Vec3::ZERO,
|
||||||
impl WalkEnum{
|
target_time:Time::ZERO,
|
||||||
//args going crazy
|
state:WalkEnum::Reached,
|
||||||
//(walk_enum,body.acceleration)=with_target_velocity();
|
|
||||||
fn with_target_velocity(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3,normal:&Planar64Vec3)->(WalkEnum,Planar64Vec3){
|
|
||||||
touching.constrain_velocity(models,&mut velocity);
|
|
||||||
let mut target_diff=velocity-body.velocity;
|
|
||||||
//remove normal component
|
|
||||||
target_diff-=normal.clone()*(normal.dot(target_diff)/normal.dot(normal.clone()));
|
|
||||||
if target_diff==Planar64Vec3::ZERO{
|
|
||||||
let mut a=Planar64Vec3::ZERO;
|
|
||||||
touching.constrain_acceleration(models,&mut a);
|
|
||||||
(WalkEnum::Reached,a)
|
|
||||||
}else{
|
|
||||||
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
|
||||||
let diff_len=target_diff.length();
|
|
||||||
let friction=if diff_len<style.walk_speed{
|
|
||||||
style.static_friction
|
|
||||||
}else{
|
|
||||||
style.kinetic_friction
|
|
||||||
};
|
|
||||||
let accel=style.walk_accel.min(style.gravity.dot(Planar64Vec3::NEG_Y)*friction);
|
|
||||||
let time_delta=diff_len/accel;
|
|
||||||
let mut a=target_diff.with_length(accel);
|
|
||||||
touching.constrain_acceleration(models,&mut a);
|
|
||||||
(WalkEnum::Transient(WalkTarget{velocity,time:body.time+Time::from(time_delta)}),a)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl WalkState{
|
|
||||||
fn ground(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3)->(Self,Planar64Vec3){
|
|
||||||
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,&Planar64Vec3::Y);
|
|
||||||
(Self{
|
|
||||||
state:walk_enum,
|
|
||||||
normal:Planar64Vec3::Y,
|
|
||||||
},a)
|
|
||||||
}
|
|
||||||
fn ladder(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&Vec<ModelPhysics>,mut velocity:Planar64Vec3,normal:&Planar64Vec3)->(Self,Planar64Vec3){
|
|
||||||
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,normal);
|
|
||||||
(Self{
|
|
||||||
state:walk_enum,
|
|
||||||
normal:normal.clone(),
|
|
||||||
},a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -220,14 +182,6 @@ impl PhysicsCamera {
|
|||||||
.clamp(self.angle_pitch_lower_limit,self.angle_pitch_upper_limit);
|
.clamp(self.angle_pitch_lower_limit,self.angle_pitch_upper_limit);
|
||||||
return glam::vec2(ax.into(),ay.into());
|
return glam::vec2(ax.into(),ay.into());
|
||||||
}
|
}
|
||||||
fn simulate_move_rotation(&self,mouse_pos:glam::IVec2)->Planar64Mat3{
|
|
||||||
let a=-self.sensitivity.mul_int((mouse_pos-self.mouse.pos+self.clamped_mouse_pos).as_i64vec2());
|
|
||||||
let ax=Angle32::wrap_from_i64(a.x);
|
|
||||||
let ay=Angle32::clamp_from_i64(a.y)
|
|
||||||
//clamp to actual vertical cam limit
|
|
||||||
.clamp(self.angle_pitch_lower_limit,self.angle_pitch_upper_limit);
|
|
||||||
Planar64Mat3::from_rotation_yx(ax,ay)
|
|
||||||
}
|
|
||||||
fn simulate_move_rotation_y(&self,mouse_pos_x:i32)->Planar64Mat3{
|
fn simulate_move_rotation_y(&self,mouse_pos_x:i32)->Planar64Mat3{
|
||||||
let ax=-self.sensitivity.x.mul_int((mouse_pos_x-self.mouse.pos.x+self.clamped_mouse_pos.x) as i64);
|
let ax=-self.sensitivity.x.mul_int((mouse_pos_x-self.mouse.pos.x+self.clamped_mouse_pos.x) as i64);
|
||||||
Planar64Mat3::from_rotation_y(Angle32::wrap_from_i64(ax))
|
Planar64Mat3::from_rotation_y(Angle32::wrap_from_i64(ax))
|
||||||
@ -246,48 +200,34 @@ impl std::default::Default for GameMechanicsState{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WorldState{}
|
pub struct WorldState{}
|
||||||
|
|
||||||
enum JumpCalculation{
|
pub struct StyleModifiers{
|
||||||
Capped,//roblox
|
pub controls_mask:u32,//controls which are unable to be activated
|
||||||
Energy,//new
|
pub controls_held:u32,//controls which must be active to be able to strafe
|
||||||
Linear,//source
|
pub strafe_tick_rate:Ratio64,
|
||||||
}
|
pub jump_time:Time,
|
||||||
|
pub mv:Planar64,
|
||||||
enum JumpImpulse{
|
pub walkspeed:Planar64,
|
||||||
FromTime(Time),//jump time is invariant across mass and gravity changes
|
pub friction:Planar64,
|
||||||
FromHeight(Planar64),//jump height is invariant across mass and gravity changes
|
pub walk_accel:Planar64,
|
||||||
FromDeltaV(Planar64),//jump velocity is invariant across mass and gravity changes
|
pub gravity:Planar64Vec3,
|
||||||
FromEnergy(Planar64),// :)
|
pub hitbox_halfsize:Planar64Vec3,
|
||||||
}
|
|
||||||
//Jumping acts on dot(walks_state.normal,body.velocity)
|
|
||||||
//Capped means it increases the dot to the cap
|
|
||||||
//Energy means it adds energy
|
|
||||||
//Linear means it linearly adds on
|
|
||||||
|
|
||||||
struct StyleModifiers{
|
|
||||||
controls_mask:u32,//controls which are unable to be activated
|
|
||||||
controls_held:u32,//controls which must be active to be able to strafe
|
|
||||||
strafe_tick_rate:Ratio64,
|
|
||||||
jump_impulse:JumpImpulse,
|
|
||||||
jump_calculation:JumpCalculation,
|
|
||||||
static_friction:Planar64,
|
|
||||||
kinetic_friction:Planar64,
|
|
||||||
walk_speed:Planar64,
|
|
||||||
walk_accel:Planar64,
|
|
||||||
ladder_speed:Planar64,
|
|
||||||
ladder_accel:Planar64,
|
|
||||||
ladder_dot:Planar64,
|
|
||||||
swim_speed:Planar64,
|
|
||||||
mass:Planar64,
|
|
||||||
mv:Planar64,
|
|
||||||
air_accel_limit:Option<Planar64>,
|
|
||||||
gravity:Planar64Vec3,
|
|
||||||
hitbox_halfsize:Planar64Vec3,
|
|
||||||
}
|
}
|
||||||
impl std::default::Default for StyleModifiers{
|
impl std::default::Default for StyleModifiers{
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::roblox_bhop()
|
Self{
|
||||||
|
controls_mask: !0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
||||||
|
controls_held: 0,
|
||||||
|
strafe_tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
|
jump_time: Time::from_nanos(715_588_000/2*100),//0.715588/2.0*100.0
|
||||||
|
gravity: Planar64Vec3::int(0,-100,0),
|
||||||
|
friction: Planar64::int(12)/10,
|
||||||
|
walk_accel: Planar64::int(90),
|
||||||
|
mv: Planar64::int(27)/10,
|
||||||
|
walkspeed: Planar64::int(18),
|
||||||
|
hitbox_halfsize: Planar64Vec3::int(2,5,2)/2,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl StyleModifiers{
|
impl StyleModifiers{
|
||||||
@ -304,121 +244,6 @@ impl StyleModifiers{
|
|||||||
const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
||||||
const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
||||||
|
|
||||||
fn new()->Self{
|
|
||||||
Self{
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
controls_held:0,
|
|
||||||
strafe_tick_rate:Ratio64::new(128,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
jump_impulse:JumpImpulse::FromEnergy(Planar64::int(512)),
|
|
||||||
jump_calculation:JumpCalculation::Energy,
|
|
||||||
gravity:Planar64Vec3::int(0,-80,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(2),
|
|
||||||
air_accel_limit:None,
|
|
||||||
walk_speed:Planar64::int(16),
|
|
||||||
walk_accel:Planar64::int(80),
|
|
||||||
ladder_speed:Planar64::int(16),
|
|
||||||
ladder_accel:Planar64::int(160),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roblox_bhop()->Self{
|
|
||||||
Self{
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
controls_held:0,
|
|
||||||
strafe_tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
jump_impulse:JumpImpulse::FromTime(Time::from_micros(715_588)),
|
|
||||||
jump_calculation:JumpCalculation::Capped,
|
|
||||||
gravity:Planar64Vec3::int(0,-100,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(27)/10,
|
|
||||||
air_accel_limit:None,
|
|
||||||
walk_speed:Planar64::int(18),
|
|
||||||
walk_accel:Planar64::int(90),
|
|
||||||
ladder_speed:Planar64::int(18),
|
|
||||||
ladder_accel:Planar64::int(180),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn roblox_surf()->Self{
|
|
||||||
Self{
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
controls_held:0,
|
|
||||||
strafe_tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
jump_impulse:JumpImpulse::FromTime(Time::from_micros(715_588)),
|
|
||||||
jump_calculation:JumpCalculation::Capped,
|
|
||||||
gravity:Planar64Vec3::int(0,-50,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(27)/10,
|
|
||||||
air_accel_limit:None,
|
|
||||||
walk_speed:Planar64::int(18),
|
|
||||||
walk_accel:Planar64::int(90),
|
|
||||||
ladder_speed:Planar64::int(18),
|
|
||||||
ladder_accel:Planar64::int(180),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn source_bhop()->Self{
|
|
||||||
//camera_offset=vec3(0,64/16-73/16/2,0),
|
|
||||||
Self{
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
controls_held:0,
|
|
||||||
strafe_tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
jump_impulse:JumpImpulse::FromHeight(Planar64::raw(52<<28)),
|
|
||||||
jump_calculation:JumpCalculation::Linear,
|
|
||||||
gravity:Planar64Vec3::raw(0,-800<<28,0),
|
|
||||||
static_friction:Planar64::int(2),//?
|
|
||||||
kinetic_friction:Planar64::int(3),//?
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::raw(30<<28),
|
|
||||||
air_accel_limit:Some(Planar64::raw(150<<28)*66),
|
|
||||||
walk_speed:Planar64::int(18),//?
|
|
||||||
walk_accel:Planar64::int(90),//?
|
|
||||||
ladder_speed:Planar64::int(18),//?
|
|
||||||
ladder_accel:Planar64::int(180),//?
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
|
||||||
swim_speed:Planar64::int(12),//?
|
|
||||||
hitbox_halfsize:Planar64Vec3::raw(33<<28,73<<28,33<<28)/2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn source_surf()->Self{
|
|
||||||
//camera_offset=vec3(0,64/16-73/16/2,0),
|
|
||||||
Self{
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
controls_held:0,
|
|
||||||
strafe_tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
jump_impulse:JumpImpulse::FromHeight(Planar64::raw(52<<28)),
|
|
||||||
jump_calculation:JumpCalculation::Linear,
|
|
||||||
gravity:Planar64Vec3::raw(0,-800<<28,0),
|
|
||||||
static_friction:Planar64::int(2),//?
|
|
||||||
kinetic_friction:Planar64::int(3),//?
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::raw(30<<28),
|
|
||||||
air_accel_limit:Some(Planar64::raw(150<<28)*66),
|
|
||||||
walk_speed:Planar64::int(18),//?
|
|
||||||
walk_accel:Planar64::int(90),//?
|
|
||||||
ladder_speed:Planar64::int(18),//?
|
|
||||||
ladder_accel:Planar64::int(180),//?
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
|
||||||
swim_speed:Planar64::int(12),//?
|
|
||||||
hitbox_halfsize:Planar64Vec3::raw(33<<28,73<<28,33<<28)/2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_control(&self,control:u32,controls:u32)->bool{
|
fn get_control(&self,control:u32,controls:u32)->bool{
|
||||||
controls&self.controls_mask&control==control
|
controls&self.controls_mask&control==control
|
||||||
}
|
}
|
||||||
@ -453,70 +278,32 @@ impl StyleModifiers{
|
|||||||
return control_dir
|
return control_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn get_jump_time(&self)->Planar64
|
fn get_jump_power(&self)->Planar64Vec3{
|
||||||
//fn get_jump_height(&self)->Planar64
|
Planar64Vec3::int(0,715588,0)/(2*1000000/100)
|
||||||
//fn get_jump_energy(&self)->Planar64
|
|
||||||
fn get_jump_deltav(&self)->Planar64{
|
|
||||||
match &self.jump_impulse{
|
|
||||||
&JumpImpulse::FromTime(time)=>self.gravity.length()*(time/2),
|
|
||||||
&JumpImpulse::FromHeight(height)=>(self.gravity.length()*height*2).sqrt(),
|
|
||||||
&JumpImpulse::FromDeltaV(deltav)=>deltav,
|
|
||||||
&JumpImpulse::FromEnergy(energy)=>(energy*2/self.mass).sqrt(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_walk_target_velocity(&self,camera:&PhysicsCamera,controls:u32,next_mouse:&MouseState,time:Time)->Planar64Vec3{
|
|
||||||
let camera_mat=camera.simulate_move_rotation_y(camera.mouse.lerp(&next_mouse,time).x);
|
|
||||||
let control_dir=camera_mat*self.get_control_dir(controls);
|
|
||||||
control_dir*self.walk_speed
|
|
||||||
}
|
|
||||||
fn get_ladder_target_velocity(&self,camera:&PhysicsCamera,controls:u32,next_mouse:&MouseState,time:Time)->Planar64Vec3{
|
|
||||||
let camera_mat=camera.simulate_move_rotation(camera.mouse.lerp(&next_mouse,time));
|
|
||||||
let control_dir=camera_mat*self.get_control_dir(controls);
|
|
||||||
// local m=sqrt(ControlDir.length_squared())
|
|
||||||
// local d=dot(Normal,ControlDir)/m
|
|
||||||
// if d<-LadderDot then
|
|
||||||
// ControlDir=Up*m
|
|
||||||
// d=dot(Normal,Up)
|
|
||||||
// elseif LadderDot<d then
|
|
||||||
// ControlDir=Up*-m
|
|
||||||
// d=-dot(Normal,Up)
|
|
||||||
// end
|
|
||||||
// return cross(cross(Normal,ControlDir),Normal)/sqrt(1-d*d)
|
|
||||||
control_dir*self.walk_speed
|
|
||||||
}
|
|
||||||
fn get_propulsion_target_velocity(&self,camera:&PhysicsCamera,controls:u32,next_mouse:&MouseState,time:Time)->Planar64Vec3{
|
|
||||||
let camera_mat=camera.simulate_move_rotation(camera.mouse.lerp(&next_mouse,time));
|
|
||||||
let control_dir=camera_mat*self.get_control_dir(controls);
|
|
||||||
control_dir*self.walk_speed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MoveState{
|
|
||||||
Air,
|
|
||||||
Walk(WalkState),
|
|
||||||
Water,
|
|
||||||
Ladder(WalkState),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PhysicsState{
|
pub struct PhysicsState{
|
||||||
pub time:Time,
|
pub time:Time,
|
||||||
body:Body,
|
pub body:Body,
|
||||||
world:WorldState,//currently there is only one state the world can be in
|
pub world:WorldState,//currently there is only one state the world can be in
|
||||||
pub game:GameMechanicsState,
|
pub game:GameMechanicsState,
|
||||||
style:StyleModifiers,
|
pub style:StyleModifiers,
|
||||||
touching:TouchingState,
|
pub contacts:std::collections::HashMap::<u32,RelativeCollision>,
|
||||||
|
pub intersects:std::collections::HashMap::<u32,RelativeCollision>,
|
||||||
|
//pub intersections: Vec<ModelId>,
|
||||||
//camera must exist in state because wormholes modify the camera, also camera punch
|
//camera must exist in state because wormholes modify the camera, also camera punch
|
||||||
camera:PhysicsCamera,
|
pub camera:PhysicsCamera,
|
||||||
next_mouse:MouseState,//Where is the mouse headed next
|
pub next_mouse:MouseState,//Where is the mouse headed next
|
||||||
controls:u32,
|
pub controls:u32,
|
||||||
move_state:MoveState,
|
pub walk:WalkState,
|
||||||
|
pub grounded:bool,
|
||||||
//all models
|
//all models
|
||||||
models:Vec<ModelPhysics>,
|
pub models:Vec<ModelPhysics>,
|
||||||
bvh:crate::bvh::BvhNode,
|
pub bvh:crate::bvh::BvhNode,
|
||||||
|
|
||||||
modes:Vec<crate::model::ModeDescription>,
|
pub modes:Vec<crate::model::ModeDescription>,
|
||||||
mode_from_mode_id:std::collections::HashMap::<u32,usize>,
|
pub mode_from_mode_id:std::collections::HashMap::<u32,usize>,
|
||||||
//the spawn point is where you spawn when you load into the map.
|
//the spawn point is where you spawn when you load into the map.
|
||||||
//This is not the same as Reset which teleports you to Spawn0
|
//This is not the same as Reset which teleports you to Spawn0
|
||||||
pub spawn_point:Planar64Vec3,
|
pub spawn_point:Planar64Vec3,
|
||||||
@ -608,55 +395,6 @@ impl RelativeCollision {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TouchingState{
|
|
||||||
contacts:std::collections::HashMap::<u32,RelativeCollision>,
|
|
||||||
intersects:std::collections::HashMap::<u32,RelativeCollision>,
|
|
||||||
}
|
|
||||||
impl TouchingState{
|
|
||||||
fn clear(&mut self){
|
|
||||||
self.contacts.clear();
|
|
||||||
self.intersects.clear();
|
|
||||||
}
|
|
||||||
fn insert_contact(&mut self,model_id:u32,collision:RelativeCollision)->Option<RelativeCollision>{
|
|
||||||
self.contacts.insert(model_id,collision)
|
|
||||||
}
|
|
||||||
fn remove_contact(&mut self,model_id:u32)->Option<RelativeCollision>{
|
|
||||||
self.contacts.remove(&model_id)
|
|
||||||
}
|
|
||||||
fn insert_intersect(&mut self,model_id:u32,collision:RelativeCollision)->Option<RelativeCollision>{
|
|
||||||
self.intersects.insert(model_id,collision)
|
|
||||||
}
|
|
||||||
fn remove_intersect(&mut self,model_id:u32)->Option<RelativeCollision>{
|
|
||||||
self.intersects.remove(&model_id)
|
|
||||||
}
|
|
||||||
fn constrain_velocity(&self,models:&Vec<ModelPhysics>,velocity:&mut Planar64Vec3){
|
|
||||||
for (_,contact) in &self.contacts {
|
|
||||||
let n=contact.normal(models);
|
|
||||||
let d=velocity.dot(n);
|
|
||||||
if d<Planar64::ZERO{
|
|
||||||
(*velocity)-=n*(d/n.dot(n));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn constrain_acceleration(&self,models:&Vec<ModelPhysics>,acceleration:&mut Planar64Vec3){
|
|
||||||
for (_,contact) in &self.contacts {
|
|
||||||
let n=contact.normal(models);
|
|
||||||
let d=acceleration.dot(n);
|
|
||||||
if d<Planar64::ZERO{
|
|
||||||
(*acceleration)-=n*(d/n.dot(n));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Default for TouchingState{
|
|
||||||
fn default() -> Self {
|
|
||||||
Self{
|
|
||||||
contacts: std::collections::HashMap::new(),
|
|
||||||
intersects: std::collections::HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Body {
|
impl Body {
|
||||||
pub fn with_pva(position:Planar64Vec3,velocity:Planar64Vec3,acceleration:Planar64Vec3) -> Self {
|
pub fn with_pva(position:Planar64Vec3,velocity:Planar64Vec3,acceleration:Planar64Vec3) -> Self {
|
||||||
Self{
|
Self{
|
||||||
@ -693,10 +431,12 @@ impl Default for PhysicsState{
|
|||||||
body: Body::with_pva(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0)),
|
body: Body::with_pva(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0)),
|
||||||
time: Time::ZERO,
|
time: Time::ZERO,
|
||||||
style:StyleModifiers::default(),
|
style:StyleModifiers::default(),
|
||||||
touching:TouchingState::default(),
|
grounded: false,
|
||||||
|
contacts: std::collections::HashMap::new(),
|
||||||
|
intersects: std::collections::HashMap::new(),
|
||||||
models: Vec::new(),
|
models: Vec::new(),
|
||||||
bvh:crate::bvh::BvhNode::default(),
|
bvh:crate::bvh::BvhNode::default(),
|
||||||
move_state: MoveState::Air,
|
walk: WalkState::new(),
|
||||||
camera: PhysicsCamera::from_offset(Planar64Vec3::int(0,2,0)),//4.5-2.5=2
|
camera: PhysicsCamera::from_offset(Planar64Vec3::int(0,2,0)),//4.5-2.5=2
|
||||||
next_mouse: MouseState::default(),
|
next_mouse: MouseState::default(),
|
||||||
controls: 0,
|
controls: 0,
|
||||||
@ -712,7 +452,8 @@ impl PhysicsState {
|
|||||||
pub fn clear(&mut self){
|
pub fn clear(&mut self){
|
||||||
self.models.clear();
|
self.models.clear();
|
||||||
self.modes.clear();
|
self.modes.clear();
|
||||||
self.touching.clear();
|
self.contacts.clear();
|
||||||
|
self.intersects.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_worker(mut self)->crate::worker::CompatWorker<TimedInstruction<InputInstruction>,PhysicsOutputState,Box<dyn FnMut(TimedInstruction<InputInstruction>)->PhysicsOutputState>>{
|
pub fn into_worker(mut self)->crate::worker::CompatWorker<TimedInstruction<InputInstruction>,PhysicsOutputState,Box<dyn FnMut(TimedInstruction<InputInstruction>)->PhysicsOutputState>>{
|
||||||
@ -912,19 +653,33 @@ impl PhysicsState {
|
|||||||
self.controls=if state{self.controls|control}else{self.controls&!control};
|
self.controls=if state{self.controls|control}else{self.controls&!control};
|
||||||
}
|
}
|
||||||
fn jump(&mut self){
|
fn jump(&mut self){
|
||||||
match &self.move_state{
|
self.grounded=false;//do I need this?
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
|
let mut v=self.body.velocity+self.style.get_jump_power();
|
||||||
let mut v=self.body.velocity+walk_state.normal*self.style.get_jump_deltav();
|
self.contact_constrain_velocity(&mut v);
|
||||||
self.touching.constrain_velocity(&self.models,&mut v);
|
self.body.velocity=v;
|
||||||
self.body.velocity=v;
|
|
||||||
},
|
|
||||||
MoveState::Air|MoveState::Water=>(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn contact_constrain_velocity(&self,velocity:&mut Planar64Vec3){
|
||||||
|
for (_,contact) in &self.contacts {
|
||||||
|
let n=contact.normal(&self.models);
|
||||||
|
let d=velocity.dot(n);
|
||||||
|
if d<Planar64::ZERO{
|
||||||
|
(*velocity)-=n*(d/n.dot(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn contact_constrain_acceleration(&self,acceleration:&mut Planar64Vec3){
|
||||||
|
for (_,contact) in &self.contacts {
|
||||||
|
let n=contact.normal(&self.models);
|
||||||
|
let d=acceleration.dot(n);
|
||||||
|
if d<Planar64::ZERO{
|
||||||
|
(*acceleration)-=n*(d/n.dot(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fn next_strafe_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
fn next_strafe_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
return Some(TimedInstruction{
|
return Some(TimedInstruction{
|
||||||
time:Time::from_nanos(self.style.strafe_tick_rate.rhs_div_int(self.style.strafe_tick_rate.mul_int(self.time.nanos()+1)+1)),
|
time:Time::from_nanos(self.style.strafe_tick_rate.rhs_div_int(self.style.strafe_tick_rate.mul_int(self.time.nanos())+1)),
|
||||||
//only poll the physics if there is a before and after mouse event
|
//only poll the physics if there is a before and after mouse event
|
||||||
instruction:PhysicsInstruction::StrafeTick
|
instruction:PhysicsInstruction::StrafeTick
|
||||||
});
|
});
|
||||||
@ -962,30 +717,44 @@ impl PhysicsState {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
fn refresh_walk_target(&mut self){
|
fn refresh_walk_target(&mut self){
|
||||||
match &mut self.move_state{
|
//calculate acceleration yada yada
|
||||||
MoveState::Air|MoveState::Water=>(),
|
if self.grounded{
|
||||||
MoveState::Walk(WalkState{normal,state})=>{
|
let mut v=self.walk.target_velocity;
|
||||||
let n=normal;
|
self.contact_constrain_velocity(&mut v);
|
||||||
(*state,self.body.acceleration)=WalkEnum::with_target_velocity(&self.touching,&self.body,&self.style,&self.models,self.style.get_walk_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&n);
|
let mut target_diff=v-self.body.velocity;
|
||||||
},
|
//remove normal component
|
||||||
MoveState::Ladder(WalkState{normal,state})=>{
|
target_diff-=Planar64Vec3::Y*target_diff.y();
|
||||||
let n=normal;
|
if target_diff==Planar64Vec3::ZERO{
|
||||||
(*state,self.body.acceleration)=WalkEnum::with_target_velocity(&self.touching,&self.body,&self.style,&self.models,self.style.get_ladder_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&n);
|
let mut a=Planar64Vec3::ZERO;
|
||||||
},
|
self.contact_constrain_acceleration(&mut a);
|
||||||
|
self.body.acceleration=a;
|
||||||
|
self.walk.state=WalkEnum::Reached;
|
||||||
|
}else{
|
||||||
|
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
||||||
|
let accel=self.style.walk_accel.min(self.style.gravity.dot(Planar64Vec3::NEG_Y)*self.style.friction);
|
||||||
|
let time_delta=target_diff.length()/accel;
|
||||||
|
let mut a=target_diff.with_length(accel);
|
||||||
|
self.contact_constrain_acceleration(&mut a);
|
||||||
|
self.body.acceleration=a;
|
||||||
|
self.walk.target_time=self.body.time+Time::from(time_delta);
|
||||||
|
self.walk.state=WalkEnum::Transient;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
self.walk.state=WalkEnum::Reached;//there is no walk target while not grounded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn next_move_instruction(&self)->Option<TimedInstruction<PhysicsInstruction>>{
|
fn next_walk_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
//check if you have a valid walk state and create an instruction
|
//check if you have a valid walk state and create an instruction
|
||||||
match &self.move_state{
|
if self.grounded{
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>match &walk_state.state{
|
match self.walk.state{
|
||||||
WalkEnum::Transient(walk_target)=>Some(TimedInstruction{
|
WalkEnum::Transient=>Some(TimedInstruction{
|
||||||
time:walk_target.time,
|
time:self.walk.target_time,
|
||||||
instruction:PhysicsInstruction::ReachWalkTargetVelocity
|
instruction:PhysicsInstruction::ReachWalkTargetVelocity
|
||||||
}),
|
}),
|
||||||
WalkEnum::Reached=>None,
|
WalkEnum::Reached=>None,
|
||||||
}
|
}
|
||||||
MoveState::Air=>self.next_strafe_instruction(),
|
}else{
|
||||||
MoveState::Water=>None,//TODO
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mesh(&self) -> TreyMesh {
|
fn mesh(&self) -> TreyMesh {
|
||||||
@ -1275,7 +1044,7 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
|
|||||||
//JUST POLLING!!! NO MUTATION
|
//JUST POLLING!!! NO MUTATION
|
||||||
let mut collector = crate::instruction::InstructionCollector::new(time_limit);
|
let mut collector = crate::instruction::InstructionCollector::new(time_limit);
|
||||||
//check for collision stop instructions with curent contacts
|
//check for collision stop instructions with curent contacts
|
||||||
for (_,collision_data) in &self.touching.contacts {
|
for (_,collision_data) in &self.contacts {
|
||||||
collector.collect(self.predict_collision_end(self.time,time_limit,collision_data));
|
collector.collect(self.predict_collision_end(self.time,time_limit,collision_data));
|
||||||
}
|
}
|
||||||
// for collision_data in &self.intersects{
|
// for collision_data in &self.intersects{
|
||||||
@ -1287,11 +1056,17 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
|
|||||||
aabb.grow(self.body.extrapolated_position(time_limit));
|
aabb.grow(self.body.extrapolated_position(time_limit));
|
||||||
aabb.inflate(self.style.hitbox_halfsize);
|
aabb.inflate(self.style.hitbox_halfsize);
|
||||||
self.bvh.the_tester(&aabb,&mut |id|{
|
self.bvh.the_tester(&aabb,&mut |id|{
|
||||||
if !(self.touching.contacts.contains_key(&id)||self.touching.intersects.contains_key(&id)){
|
if !(self.contacts.contains_key(&id)||self.intersects.contains_key(&id)){
|
||||||
collector.collect(self.predict_collision_start(self.time,time_limit,id));
|
collector.collect(self.predict_collision_start(self.time,time_limit,id));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
collector.collect(self.next_move_instruction());
|
if self.grounded {
|
||||||
|
//walk maintenance
|
||||||
|
collector.collect(self.next_walk_instruction());
|
||||||
|
}else{
|
||||||
|
//check to see when the next strafe tick is
|
||||||
|
collector.collect(self.next_strafe_instruction());
|
||||||
|
}
|
||||||
collector.instruction()
|
collector.instruction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1319,42 +1094,24 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
let model=c.model(&self.models).unwrap();
|
let model=c.model(&self.models).unwrap();
|
||||||
match &model.attributes{
|
match &model.attributes{
|
||||||
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
||||||
let mut v=self.body.velocity;
|
match &contacting.surf{
|
||||||
match &contacting.contact_behaviour{
|
Some(surf)=>println!("I'm surfing!"),
|
||||||
Some(crate::model::ContactingBehaviour::Surf)=>println!("I'm surfing!"),
|
|
||||||
&Some(crate::model::ContactingBehaviour::Elastic(elasticity))=>{
|
|
||||||
let n=c.normal(&self.models);
|
|
||||||
let d=n.dot(v)*Planar64::raw(-1-elasticity as i64);
|
|
||||||
v-=n*(d/n.dot(n));
|
|
||||||
},
|
|
||||||
Some(crate::model::ContactingBehaviour::Ladder(contacting_ladder))=>{
|
|
||||||
if contacting_ladder.sticky{
|
|
||||||
//kill v
|
|
||||||
v=Planar64Vec3::ZERO;//model.velocity
|
|
||||||
}
|
|
||||||
//ladder walkstate
|
|
||||||
let (walk_state,a)=WalkState::ladder(&self.touching,&self.body,&self.style,&self.models,self.style.get_ladder_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&c.normal(&self.models));
|
|
||||||
self.move_state=MoveState::Ladder(walk_state);
|
|
||||||
self.body.acceleration=a;
|
|
||||||
}
|
|
||||||
None=>match &c.face {
|
None=>match &c.face {
|
||||||
TreyMeshFace::Top => {
|
TreyMeshFace::Top => {
|
||||||
//ground
|
//ground
|
||||||
let (walk_state,a)=WalkState::ground(&self.touching,&self.body,&self.style,&self.models,self.style.get_walk_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time));
|
self.grounded=true;
|
||||||
self.move_state=MoveState::Walk(walk_state);
|
|
||||||
self.body.acceleration=a;
|
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
//check ground
|
//check ground
|
||||||
self.touching.insert_contact(c.model,c);
|
self.contacts.insert(c.model,c);
|
||||||
match &general.teleport_behaviour{
|
match &general.teleport_behaviour{
|
||||||
Some(crate::model::TeleportBehaviour::StageElement(stage_element))=>{
|
Some(crate::model::TeleportBehaviour::StageElement(stage_element))=>{
|
||||||
if stage_element.force||self.game.stage_id<stage_element.stage_id{
|
if stage_element.force||self.game.stage_id<stage_element.stage_id{
|
||||||
self.game.stage_id=stage_element.stage_id;
|
self.game.stage_id=stage_element.stage_id;
|
||||||
}
|
}
|
||||||
match &stage_element.behaviour{
|
match stage_element.behaviour{
|
||||||
crate::model::StageElementBehaviour::SpawnAt=>(),
|
crate::model::StageElementBehaviour::SpawnAt=>(),
|
||||||
crate::model::StageElementBehaviour::Trigger
|
crate::model::StageElementBehaviour::Trigger
|
||||||
|crate::model::StageElementBehaviour::Teleport=>{
|
|crate::model::StageElementBehaviour::Teleport=>{
|
||||||
@ -1364,15 +1121,16 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
if let Some(model)=self.models.get(spawn as usize){
|
if let Some(model)=self.models.get(spawn as usize){
|
||||||
self.body.position=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(self.style.hitbox_halfsize.y()+Planar64::ONE/16);
|
self.body.position=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(self.style.hitbox_halfsize.y()+Planar64::ONE/16);
|
||||||
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
|
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
|
||||||
self.touching.clear();
|
self.contacts.clear();
|
||||||
|
self.intersects.clear();
|
||||||
self.body.acceleration=self.style.gravity;
|
self.body.acceleration=self.style.gravity;
|
||||||
self.move_state=MoveState::Air;//TODO: calculate contacts and determine the actual state
|
self.walk.state=WalkEnum::Reached;
|
||||||
|
self.grounded=false;
|
||||||
}else{println!("bad1");}
|
}else{println!("bad1");}
|
||||||
}else{println!("bad2");}
|
}else{println!("bad2");}
|
||||||
}else{println!("bad3");}
|
}else{println!("bad3");}
|
||||||
},
|
},
|
||||||
crate::model::StageElementBehaviour::Platform=>(),
|
crate::model::StageElementBehaviour::Platform=>(),
|
||||||
crate::model::StageElementBehaviour::JumpLimit(_)=>(),//TODO
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(crate::model::TeleportBehaviour::Wormhole(wormhole))=>{
|
Some(crate::model::TeleportBehaviour::Wormhole(wormhole))=>{
|
||||||
@ -1381,59 +1139,30 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
None=>(),
|
None=>(),
|
||||||
}
|
}
|
||||||
//flatten v
|
//flatten v
|
||||||
self.touching.constrain_velocity(&self.models,&mut v);
|
let mut v=self.body.velocity;
|
||||||
|
self.contact_constrain_velocity(&mut v);
|
||||||
match &general.booster{
|
match &general.booster{
|
||||||
Some(booster)=>{
|
Some(booster)=>{
|
||||||
match booster{
|
v+=booster.velocity;
|
||||||
&crate::model::GameMechanicBooster::Affine(transform)=>v=transform.transform_point3(v),
|
self.contact_constrain_velocity(&mut v);
|
||||||
&crate::model::GameMechanicBooster::Velocity(velocity)=>v+=velocity,
|
|
||||||
&crate::model::GameMechanicBooster::Energy{direction,energy}=>todo!(),
|
|
||||||
}
|
|
||||||
self.touching.constrain_velocity(&self.models,&mut v);
|
|
||||||
},
|
|
||||||
None=>(),
|
|
||||||
}
|
|
||||||
match &general.trajectory{
|
|
||||||
Some(trajectory)=>{
|
|
||||||
println!("??? {:?}",trajectory);
|
|
||||||
match trajectory{
|
|
||||||
&crate::model::GameMechanicSetTrajectory::Height(height)=>{
|
|
||||||
//vg=sqrt(-2*gg*height)
|
|
||||||
println!("height booster h={}",height);
|
|
||||||
let vg=v.dot(self.style.gravity);
|
|
||||||
let gg=self.style.gravity.dot(self.style.gravity);
|
|
||||||
let hb=(gg.sqrt()*height*2).sqrt()*gg.sqrt();
|
|
||||||
println!("hb={} vg={}",hb,vg);
|
|
||||||
let b=self.style.gravity*((-hb-vg)/gg);
|
|
||||||
println!("bopo {}",b);
|
|
||||||
v+=b;
|
|
||||||
},
|
|
||||||
&crate::model::GameMechanicSetTrajectory::Velocity(velocity)=>v=velocity,
|
|
||||||
crate::model::GameMechanicSetTrajectory::AirTime(_)
|
|
||||||
|crate::model::GameMechanicSetTrajectory::TargetPointTime{target_point:_,time:_}
|
|
||||||
|crate::model::GameMechanicSetTrajectory::TrajectoryTargetPoint{target_point:_,speed:_,trajectory_choice:_}
|
|
||||||
|crate::model::GameMechanicSetTrajectory::DotVelocity{direction:_,dot:_}
|
|
||||||
=>(),
|
|
||||||
}
|
|
||||||
self.touching.constrain_velocity(&self.models,&mut v);
|
|
||||||
},
|
},
|
||||||
None=>(),
|
None=>(),
|
||||||
}
|
}
|
||||||
self.body.velocity=v;
|
self.body.velocity=v;
|
||||||
if self.style.get_control(StyleModifiers::CONTROL_JUMP,self.controls){
|
if self.grounded&&self.style.get_control(StyleModifiers::CONTROL_JUMP,self.controls){
|
||||||
self.jump();
|
self.jump();
|
||||||
}
|
}
|
||||||
self.refresh_walk_target();
|
self.refresh_walk_target();
|
||||||
},
|
},
|
||||||
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
|
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
|
||||||
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
|
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
|
||||||
self.touching.insert_intersect(c.model,c);
|
self.intersects.insert(c.model,c);
|
||||||
match &general.teleport_behaviour{
|
match &general.teleport_behaviour{
|
||||||
Some(crate::model::TeleportBehaviour::StageElement(stage_element))=>{
|
Some(crate::model::TeleportBehaviour::StageElement(stage_element))=>{
|
||||||
if stage_element.force||self.game.stage_id<stage_element.stage_id{
|
if stage_element.force||self.game.stage_id<stage_element.stage_id{
|
||||||
self.game.stage_id=stage_element.stage_id;
|
self.game.stage_id=stage_element.stage_id;
|
||||||
}
|
}
|
||||||
match &stage_element.behaviour{
|
match stage_element.behaviour{
|
||||||
crate::model::StageElementBehaviour::SpawnAt=>(),
|
crate::model::StageElementBehaviour::SpawnAt=>(),
|
||||||
crate::model::StageElementBehaviour::Trigger
|
crate::model::StageElementBehaviour::Trigger
|
||||||
|crate::model::StageElementBehaviour::Teleport=>{
|
|crate::model::StageElementBehaviour::Teleport=>{
|
||||||
@ -1443,15 +1172,16 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
if let Some(model)=self.models.get(spawn as usize){
|
if let Some(model)=self.models.get(spawn as usize){
|
||||||
self.body.position=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(self.style.hitbox_halfsize.y()+Planar64::ONE/16);
|
self.body.position=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(self.style.hitbox_halfsize.y()+Planar64::ONE/16);
|
||||||
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
|
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
|
||||||
self.touching.clear();
|
self.contacts.clear();
|
||||||
|
self.intersects.clear();
|
||||||
self.body.acceleration=self.style.gravity;
|
self.body.acceleration=self.style.gravity;
|
||||||
self.move_state=MoveState::Air;//TODO: calculate contacts and determine the actual state
|
self.walk.state=WalkEnum::Reached;
|
||||||
|
self.grounded=false;
|
||||||
}else{println!("bad1");}
|
}else{println!("bad1");}
|
||||||
}else{println!("bad2");}
|
}else{println!("bad2");}
|
||||||
}else{println!("bad3");}
|
}else{println!("bad3");}
|
||||||
},
|
},
|
||||||
crate::model::StageElementBehaviour::Platform=>(),
|
crate::model::StageElementBehaviour::Platform=>(),
|
||||||
crate::model::StageElementBehaviour::JumpLimit(_)=>(),//TODO
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(crate::model::TeleportBehaviour::Wormhole(wormhole))=>{
|
Some(crate::model::TeleportBehaviour::Wormhole(wormhole))=>{
|
||||||
@ -1466,22 +1196,21 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
let model=c.model(&self.models).unwrap();
|
let model=c.model(&self.models).unwrap();
|
||||||
match &model.attributes{
|
match &model.attributes{
|
||||||
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
||||||
self.touching.remove_contact(c.model);//remove contact before calling contact_constrain_acceleration
|
self.contacts.remove(&c.model);//remove contact before calling contact_constrain_acceleration
|
||||||
let mut a=self.style.gravity;
|
let mut a=self.style.gravity;
|
||||||
self.touching.constrain_acceleration(&self.models,&mut a);
|
self.contact_constrain_acceleration(&mut a);
|
||||||
self.body.acceleration=a;
|
self.body.acceleration=a;
|
||||||
//check ground
|
//check ground
|
||||||
//self.touching.get_move_state();
|
|
||||||
match &c.face {
|
match &c.face {
|
||||||
TreyMeshFace::Top => {
|
TreyMeshFace::Top => {
|
||||||
//TODO: make this more advanced checking contacts
|
self.grounded=false;
|
||||||
self.move_state=MoveState::Air;
|
|
||||||
},
|
},
|
||||||
_=>self.refresh_walk_target(),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
self.refresh_walk_target();
|
||||||
},
|
},
|
||||||
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
|
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
|
||||||
self.touching.remove_intersect(c.model);
|
self.intersects.remove(&c.model);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1491,32 +1220,23 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
let d=self.body.velocity.dot(control_dir);
|
let d=self.body.velocity.dot(control_dir);
|
||||||
if d<self.style.mv {
|
if d<self.style.mv {
|
||||||
let mut v=self.body.velocity+control_dir*(self.style.mv-d);
|
let mut v=self.body.velocity+control_dir*(self.style.mv-d);
|
||||||
self.touching.constrain_velocity(&self.models,&mut v);
|
self.contact_constrain_velocity(&mut v);
|
||||||
self.body.velocity=v;
|
self.body.velocity=v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PhysicsInstruction::ReachWalkTargetVelocity => {
|
PhysicsInstruction::ReachWalkTargetVelocity => {
|
||||||
match &mut self.move_state{
|
//precisely set velocity
|
||||||
MoveState::Air|MoveState::Water=>(),
|
let mut a=Planar64Vec3::ZERO;
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
|
self.contact_constrain_acceleration(&mut a);
|
||||||
match &mut walk_state.state{
|
self.body.acceleration=a;
|
||||||
WalkEnum::Reached=>(),
|
let mut v=self.walk.target_velocity;
|
||||||
WalkEnum::Transient(walk_target)=>{
|
self.contact_constrain_velocity(&mut v);
|
||||||
//precisely set velocity
|
self.body.velocity=v;
|
||||||
let mut a=self.style.gravity;
|
self.walk.state=WalkEnum::Reached;
|
||||||
self.touching.constrain_acceleration(&self.models,&mut a);
|
|
||||||
self.body.acceleration=a;
|
|
||||||
let mut v=walk_target.velocity;
|
|
||||||
self.touching.constrain_velocity(&self.models,&mut v);
|
|
||||||
self.body.velocity=v;
|
|
||||||
walk_state.state=WalkEnum::Reached;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
PhysicsInstruction::Input(input_instruction) => {
|
PhysicsInstruction::Input(input_instruction) => {
|
||||||
let mut refresh_walk_target=true;
|
let mut refresh_walk_target=true;
|
||||||
|
let mut refresh_walk_target_velocity=true;
|
||||||
match input_instruction{
|
match input_instruction{
|
||||||
PhysicsInputInstruction::SetNextMouse(m) => {
|
PhysicsInputInstruction::SetNextMouse(m) => {
|
||||||
self.camera.move_mouse(self.next_mouse.pos);
|
self.camera.move_mouse(self.next_mouse.pos);
|
||||||
@ -1534,8 +1254,10 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
PhysicsInputInstruction::SetMoveDown(s) => self.set_control(StyleModifiers::CONTROL_MOVEDOWN,s),
|
PhysicsInputInstruction::SetMoveDown(s) => self.set_control(StyleModifiers::CONTROL_MOVEDOWN,s),
|
||||||
PhysicsInputInstruction::SetJump(s) => {
|
PhysicsInputInstruction::SetJump(s) => {
|
||||||
self.set_control(StyleModifiers::CONTROL_JUMP,s);
|
self.set_control(StyleModifiers::CONTROL_JUMP,s);
|
||||||
self.jump();
|
if self.grounded{
|
||||||
refresh_walk_target=false;
|
self.jump();
|
||||||
|
}
|
||||||
|
refresh_walk_target_velocity=false;
|
||||||
},
|
},
|
||||||
PhysicsInputInstruction::SetZoom(s) => {
|
PhysicsInputInstruction::SetZoom(s) => {
|
||||||
self.set_control(StyleModifiers::CONTROL_ZOOM,s);
|
self.set_control(StyleModifiers::CONTROL_ZOOM,s);
|
||||||
@ -1546,14 +1268,21 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
self.body.position=self.spawn_point;
|
self.body.position=self.spawn_point;
|
||||||
self.body.velocity=Planar64Vec3::ZERO;
|
self.body.velocity=Planar64Vec3::ZERO;
|
||||||
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
|
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
|
||||||
self.touching.clear();
|
self.contacts.clear();
|
||||||
self.body.acceleration=self.style.gravity;
|
self.body.acceleration=self.style.gravity;
|
||||||
self.move_state=MoveState::Air;
|
self.walk.state=WalkEnum::Reached;
|
||||||
|
self.grounded=false;
|
||||||
refresh_walk_target=false;
|
refresh_walk_target=false;
|
||||||
},
|
},
|
||||||
PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle!
|
PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle!
|
||||||
}
|
}
|
||||||
if refresh_walk_target{
|
if refresh_walk_target{
|
||||||
|
//calculate walk target velocity
|
||||||
|
if refresh_walk_target_velocity{
|
||||||
|
let camera_mat=self.camera.simulate_move_rotation_y(self.camera.mouse.lerp(&self.next_mouse,self.time).x);
|
||||||
|
let control_dir=camera_mat*self.style.get_control_dir(self.controls);
|
||||||
|
self.walk.target_velocity=control_dir*self.style.walkspeed;
|
||||||
|
}
|
||||||
self.refresh_walk_target();
|
self.refresh_walk_target();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -174,7 +174,7 @@ pub fn unit_cornerwedge()->crate::model::IndexedModel{
|
|||||||
generate_partial_unit_cornerwedge(t)
|
generate_partial_unit_cornerwedge(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Copy,Clone)]
|
||||||
pub struct FaceDescription{
|
pub struct FaceDescription{
|
||||||
pub texture:Option<u32>,
|
pub texture:Option<u32>,
|
||||||
pub transform:glam::Affine2,
|
pub transform:glam::Affine2,
|
||||||
|
Reference in New Issue
Block a user