forked from StrafesNET/strafe-client
point hitbox work
This commit is contained in:
parent
769f88eb9f
commit
d71f143d68
@ -1,5 +1,5 @@
|
|||||||
//integer units
|
//integer units
|
||||||
#[derive(Clone,Copy,Hash,PartialEq,PartialOrd,Debug)]
|
#[derive(Clone,Copy,Hash,Eq,PartialEq,PartialOrd,Debug)]
|
||||||
pub struct Time(i64);
|
pub struct Time(i64);
|
||||||
impl Time{
|
impl Time{
|
||||||
pub const ZERO:Self=Self(0);
|
pub const ZERO:Self=Self(0);
|
||||||
@ -800,7 +800,7 @@ impl std::ops::Div<i64> for Planar64Vec3{
|
|||||||
}
|
}
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
pub struct Planar64Mat3{
|
pub struct Planar64Mat3{
|
||||||
x_axis:Planar64Vec3,
|
x_axis:Planar64Vec3,
|
||||||
y_axis:Planar64Vec3,
|
y_axis:Planar64Vec3,
|
||||||
@ -916,7 +916,7 @@ impl std::ops::Div<i64> for Planar64Mat3{
|
|||||||
}
|
}
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy,Default)]
|
#[derive(Clone,Copy,Default,Hash,Eq,PartialEq)]
|
||||||
pub struct Planar64Affine3{
|
pub struct Planar64Affine3{
|
||||||
pub matrix3:Planar64Mat3,//includes scale above 1
|
pub matrix3:Planar64Mat3,//includes scale above 1
|
||||||
pub translation:Planar64Vec3,
|
pub translation:Planar64Vec3,
|
||||||
|
34
src/model.rs
34
src/model.rs
@ -83,11 +83,11 @@ pub enum TempIndexedAttributes{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//you have this effect while in contact
|
//you have this effect while in contact
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct ContactingLadder{
|
pub struct ContactingLadder{
|
||||||
pub sticky:bool
|
pub sticky:bool
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum ContactingBehaviour{
|
pub enum ContactingBehaviour{
|
||||||
Surf,
|
Surf,
|
||||||
Cling,//usable as a zipline, or other weird and wonderful things
|
Cling,//usable as a zipline, or other weird and wonderful things
|
||||||
@ -95,24 +95,24 @@ pub enum ContactingBehaviour{
|
|||||||
Elastic(u32),//[1/2^32,1] 0=None (elasticity+1)/2^32
|
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,Hash,Eq,PartialEq)]
|
||||||
pub struct IntersectingWater{
|
pub struct IntersectingWater{
|
||||||
pub viscosity:Planar64,
|
pub viscosity:Planar64,
|
||||||
pub density:Planar64,
|
pub density:Planar64,
|
||||||
pub current:Planar64Vec3,
|
pub current:Planar64Vec3,
|
||||||
}
|
}
|
||||||
//All models can be given these attributes
|
//All models can be given these attributes
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct GameMechanicAccelerator{
|
pub struct GameMechanicAccelerator{
|
||||||
pub acceleration:Planar64Vec3
|
pub acceleration:Planar64Vec3
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum GameMechanicBooster{
|
pub enum GameMechanicBooster{
|
||||||
Affine(Planar64Affine3),//capable of SetVelocity,DotVelocity,normal booster,bouncy part,redirect velocity, and much more
|
Affine(Planar64Affine3),//capable of SetVelocity,DotVelocity,normal booster,bouncy part,redirect velocity, and much more
|
||||||
Velocity(Planar64Vec3),//straight up boost velocity adds to your current velocity
|
Velocity(Planar64Vec3),//straight up boost velocity adds to your current velocity
|
||||||
Energy{direction:Planar64Vec3,energy:Planar64},//increase energy in direction
|
Energy{direction:Planar64Vec3,energy:Planar64},//increase energy in direction
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum GameMechanicCheckpoint{
|
pub enum GameMechanicCheckpoint{
|
||||||
Ordered{
|
Ordered{
|
||||||
mode_id:u32,
|
mode_id:u32,
|
||||||
@ -122,12 +122,12 @@ pub enum GameMechanicCheckpoint{
|
|||||||
mode_id:u32,
|
mode_id:u32,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum TrajectoryChoice{
|
pub enum TrajectoryChoice{
|
||||||
HighArcLongDuration,//underhand lob at target: less horizontal speed and more air time
|
HighArcLongDuration,//underhand lob at target: less horizontal speed and more air time
|
||||||
LowArcShortDuration,//overhand throw at target: more horizontal speed and less air time
|
LowArcShortDuration,//overhand throw at target: more horizontal speed and less air time
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum GameMechanicSetTrajectory{
|
pub enum GameMechanicSetTrajectory{
|
||||||
AirTime(Time),//air time (relative to gravity direction) is invariant across mass and gravity changes
|
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
|
Height(Planar64),//boost height (relative to gravity direction) is invariant across mass and gravity changes
|
||||||
@ -143,14 +143,14 @@ pub enum GameMechanicSetTrajectory{
|
|||||||
Velocity(Planar64Vec3),//SetVelocity
|
Velocity(Planar64Vec3),//SetVelocity
|
||||||
DotVelocity{direction:Planar64Vec3,dot:Planar64},//set your velocity in a specific direction without touching other directions
|
DotVelocity{direction:Planar64Vec3,dot:Planar64},//set your velocity in a specific direction without touching other directions
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum ZoneBehaviour{
|
pub enum ZoneBehaviour{
|
||||||
//Start is indexed
|
//Start is indexed
|
||||||
//Checkpoints are indexed
|
//Checkpoints are indexed
|
||||||
Finish,
|
Finish,
|
||||||
Anitcheat,
|
Anitcheat,
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct GameMechanicZone{
|
pub struct GameMechanicZone{
|
||||||
pub mode_id:u32,
|
pub mode_id:u32,
|
||||||
pub behaviour:ZoneBehaviour,
|
pub behaviour:ZoneBehaviour,
|
||||||
@ -161,7 +161,7 @@ pub struct GameMechanicZone{
|
|||||||
// InRange(Planar64,Planar64),
|
// InRange(Planar64,Planar64),
|
||||||
// OutsideRange(Planar64,Planar64),
|
// OutsideRange(Planar64,Planar64),
|
||||||
// }
|
// }
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum StageElementBehaviour{
|
pub enum StageElementBehaviour{
|
||||||
//Spawn,//The behaviour of stepping on a spawn setting the spawnid
|
//Spawn,//The behaviour of stepping on a spawn setting the spawnid
|
||||||
SpawnAt,
|
SpawnAt,
|
||||||
@ -178,14 +178,14 @@ pub enum StageElementBehaviour{
|
|||||||
JumpLimit(u32),
|
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,Hash,Eq,PartialEq)]
|
||||||
pub struct GameMechanicStageElement{
|
pub struct GameMechanicStageElement{
|
||||||
pub mode_id:u32,
|
pub mode_id:u32,
|
||||||
pub stage_id:u32,//which spawn to send to
|
pub stage_id:u32,//which spawn to send to
|
||||||
pub force:bool,//allow setting to lower spawn id i.e. 7->3
|
pub force:bool,//allow setting to lower spawn id i.e. 7->3
|
||||||
pub behaviour:StageElementBehaviour
|
pub behaviour:StageElementBehaviour
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct GameMechanicWormhole{
|
pub struct GameMechanicWormhole{
|
||||||
//destination does not need to be another wormhole
|
//destination does not need to be another wormhole
|
||||||
//this defines a one way portal to a destination model transform
|
//this defines a one way portal to a destination model transform
|
||||||
@ -193,13 +193,13 @@ pub struct GameMechanicWormhole{
|
|||||||
pub destination_model_id:u32,
|
pub destination_model_id:u32,
|
||||||
//(position,angles)*=origin.transform.inverse()*destination.transform
|
//(position,angles)*=origin.transform.inverse()*destination.transform
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum TeleportBehaviour{
|
pub enum TeleportBehaviour{
|
||||||
StageElement(GameMechanicStageElement),
|
StageElement(GameMechanicStageElement),
|
||||||
Wormhole(GameMechanicWormhole),
|
Wormhole(GameMechanicWormhole),
|
||||||
}
|
}
|
||||||
//attributes listed in order of handling
|
//attributes listed in order of handling
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct GameMechanicAttributes{
|
pub struct GameMechanicAttributes{
|
||||||
pub zone:Option<GameMechanicZone>,
|
pub zone:Option<GameMechanicZone>,
|
||||||
pub booster:Option<GameMechanicBooster>,
|
pub booster:Option<GameMechanicBooster>,
|
||||||
@ -218,7 +218,7 @@ impl GameMechanicAttributes{
|
|||||||
||self.accelerator.is_some()
|
||self.accelerator.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct ContactingAttributes{
|
pub struct ContactingAttributes{
|
||||||
//friction?
|
//friction?
|
||||||
pub contact_behaviour:Option<ContactingBehaviour>,
|
pub contact_behaviour:Option<ContactingBehaviour>,
|
||||||
@ -228,7 +228,7 @@ impl ContactingAttributes{
|
|||||||
self.contact_behaviour.is_some()
|
self.contact_behaviour.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone,Hash,Eq,PartialEq)]
|
||||||
pub struct IntersectingAttributes{
|
pub struct IntersectingAttributes{
|
||||||
pub water:Option<IntersectingWater>,
|
pub water:Option<IntersectingWater>,
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,11 @@ struct Face{
|
|||||||
normal:Planar64Vec3,
|
normal:Planar64Vec3,
|
||||||
dot:Planar64,
|
dot:Planar64,
|
||||||
}
|
}
|
||||||
|
impl Face{
|
||||||
|
fn nd(&self)->(Planar64Vec3,Planar64){
|
||||||
|
(self.normal,self.dot)
|
||||||
|
}
|
||||||
|
}
|
||||||
struct Vert(Planar64Vec3);
|
struct Vert(Planar64Vec3);
|
||||||
struct FaceRefs{
|
struct FaceRefs{
|
||||||
edges:Vec<(EdgeId,FaceId)>,
|
edges:Vec<(EdgeId,FaceId)>,
|
||||||
@ -171,22 +176,23 @@ impl PhysicsMesh{
|
|||||||
pub fn verts<'a>(&'a self)->impl Iterator<Item=Planar64Vec3>+'a{
|
pub fn verts<'a>(&'a self)->impl Iterator<Item=Planar64Vec3>+'a{
|
||||||
self.verts.iter().map(|Vert(pos)|*pos)
|
self.verts.iter().map(|Vert(pos)|*pos)
|
||||||
}
|
}
|
||||||
pub fn brute_t(&self,body:&crate::physics::Body,time_limit:crate::integer::Time)->Option<(FaceId,crate::integer::Time)>{
|
pub fn brute(&self,body:&crate::physics::Body,time_limit:crate::integer::Time)->Option<(FaceId,crate::integer::Time)>{
|
||||||
//check each face
|
//check each face
|
||||||
let mut best_time=time_limit;
|
let mut best_time=time_limit;
|
||||||
let mut best_face=None;
|
let mut best_face=None;
|
||||||
for (i,f) in self.face_topology.iter().enumerate(){
|
for (i,face) in self.faces.iter().enumerate(){
|
||||||
let (n,d)=self.face_nd(FaceId(i));
|
let face_id=FaceId(i);
|
||||||
|
let (n,d)=face.nd();
|
||||||
for t in crate::zeroes::zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
for t in crate::zeroes::zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
let t=body.time+crate::integer::Time::from(t);
|
let t=body.time+crate::integer::Time::from(t);
|
||||||
if body.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
if body.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
let p=body.extrapolated_position(t);
|
let p=body.extrapolated_position(t);
|
||||||
if f.edges.iter().all(|&(_,face_id)|{
|
if self.face_edges(face_id).iter().all(|&(_,face_id)|{
|
||||||
let (n,d)=self.face_nd(face_id);
|
let (n,d)=self.face_nd(face_id);
|
||||||
n.dot(p)<=d
|
n.dot(p)<=d
|
||||||
}){
|
}){
|
||||||
best_time=t;
|
best_time=t;
|
||||||
best_face=Some(FaceId(i));
|
best_face=Some(face_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,6 +270,70 @@ pub struct TransformedMesh<'a>{
|
|||||||
normal_transform:&'a crate::integer::Planar64Mat3,
|
normal_transform:&'a crate::integer::Planar64Mat3,
|
||||||
normal_determinant:Planar64,
|
normal_determinant:Planar64,
|
||||||
}
|
}
|
||||||
|
impl TransformedMesh<'_>{
|
||||||
|
pub fn brute_in(&self,body:&crate::physics::Body,time_limit:crate::integer::Time)->Option<(FaceId,crate::integer::Time)>{
|
||||||
|
//check each face
|
||||||
|
let mut best_time=time_limit;
|
||||||
|
let mut best_face=None;
|
||||||
|
for i in 0..self.mesh.faces.len(){
|
||||||
|
let face_id=FaceId(i);
|
||||||
|
let (n,d)=self.face_nd(face_id);
|
||||||
|
for t in crate::zeroes::zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
|
let t=body.time+crate::integer::Time::from(t);
|
||||||
|
if body.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
|
let p=body.extrapolated_position(t);
|
||||||
|
if self.face_edges(face_id).iter().all(|&(_,face_id)|{
|
||||||
|
let (n,d)=self.face_nd(face_id);
|
||||||
|
n.dot(p)<=d
|
||||||
|
}){
|
||||||
|
best_time=t;
|
||||||
|
best_face=Some(face_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best_face.map(|f|(f,best_time))
|
||||||
|
}
|
||||||
|
pub fn brute_out(&self,body:&crate::physics::Body,time_limit:crate::integer::Time)->Option<(FaceId,crate::integer::Time)>{
|
||||||
|
//check each face
|
||||||
|
let mut best_time=time_limit;
|
||||||
|
let mut best_face=None;
|
||||||
|
for i in 0..self.mesh.faces.len(){
|
||||||
|
let face_id=FaceId(i);
|
||||||
|
let (n,d)=self.face_nd(face_id);
|
||||||
|
for t in crate::zeroes::zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
|
let t=body.time+crate::integer::Time::from(t);
|
||||||
|
if body.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))>Planar64::ZERO{
|
||||||
|
let p=body.extrapolated_position(t);
|
||||||
|
if self.face_edges(face_id).iter().all(|&(_,face_id)|{
|
||||||
|
let (n,d)=self.face_nd(face_id);
|
||||||
|
n.dot(p)<=d
|
||||||
|
}){
|
||||||
|
best_time=t;
|
||||||
|
best_face=Some(face_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best_face.map(|f|(f,best_time))
|
||||||
|
}
|
||||||
|
pub fn brute_out_face(&self,body:&crate::physics::Body,time_limit:crate::integer::Time,face_id:FaceId)->Option<(FaceId,crate::integer::Time)>{
|
||||||
|
//check each face
|
||||||
|
let mut best_time=time_limit;
|
||||||
|
let mut best_face=None;
|
||||||
|
for &(edge_id,face_id) in self.mesh.face_edges(face_id).iter(){
|
||||||
|
let (n,d)=self.face_nd(face_id);
|
||||||
|
for t in crate::zeroes::zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||||
|
let t=body.time+crate::integer::Time::from(t);
|
||||||
|
if body.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))>Planar64::ZERO{
|
||||||
|
best_time=t;
|
||||||
|
best_face=Some(face_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best_face.map(|f|(f,best_time))
|
||||||
|
}
|
||||||
|
}
|
||||||
impl MeshQuery<FaceId,EdgeId,VertId> for TransformedMesh<'_>{
|
impl MeshQuery<FaceId,EdgeId,VertId> for TransformedMesh<'_>{
|
||||||
fn closest_fev(&self,point:Planar64Vec3)->FEV<FaceId,EdgeId,VertId>{
|
fn closest_fev(&self,point:Planar64Vec3)->FEV<FaceId,EdgeId,VertId>{
|
||||||
//TODO: put some genius code right here
|
//TODO: put some genius code right here
|
||||||
@ -405,6 +475,7 @@ impl MeshQuery<MinkowskiFace,MinkowskiEdge,MinkowskiVert> for MinkowskiMesh<'_>{
|
|||||||
}).collect())
|
}).collect())
|
||||||
},
|
},
|
||||||
MinkowskiFace::EdgeEdge(e0,e1)=>{
|
MinkowskiFace::EdgeEdge(e0,e1)=>{
|
||||||
|
/*
|
||||||
let e0v=self.mesh0.edge_verts(e0);
|
let e0v=self.mesh0.edge_verts(e0);
|
||||||
let e1v=self.mesh1.edge_verts(e1);
|
let e1v=self.mesh1.edge_verts(e1);
|
||||||
let [r0,r1]=e0v.map(|vert_id0|{
|
let [r0,r1]=e0v.map(|vert_id0|{
|
||||||
@ -427,6 +498,8 @@ impl MeshQuery<MinkowskiFace,MinkowskiEdge,MinkowskiVert> for MinkowskiMesh<'_>{
|
|||||||
(MinkowskiEdge::EdgeVert(e0,vert_id1),MinkowskiFace::VertFace(v0,face_id1))
|
(MinkowskiEdge::EdgeVert(e0,vert_id1),MinkowskiFace::VertFace(v0,face_id1))
|
||||||
});
|
});
|
||||||
Cow::Owned(vec![r0,r1,r2,r3])
|
Cow::Owned(vec![r0,r1,r2,r3])
|
||||||
|
*/
|
||||||
|
todo!()
|
||||||
},
|
},
|
||||||
MinkowskiFace::VertFace(v0,f1)=>{
|
MinkowskiFace::VertFace(v0,f1)=>{
|
||||||
Cow::Owned(self.mesh1.face_edges(f1).iter().map(|&(edge_id1,face_id1)|{
|
Cow::Owned(self.mesh1.face_edges(f1).iter().map(|&(edge_id1,face_id1)|{
|
||||||
|
202
src/physics.rs
202
src/physics.rs
@ -85,15 +85,12 @@ struct WalkState{
|
|||||||
impl WalkEnum{
|
impl WalkEnum{
|
||||||
//args going crazy
|
//args going crazy
|
||||||
//(walk_enum,body.acceleration)=with_target_velocity();
|
//(walk_enum,body.acceleration)=with_target_velocity();
|
||||||
fn with_target_velocity(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&PhysicsModels,mut velocity:Planar64Vec3,normal:&Planar64Vec3)->(WalkEnum,Planar64Vec3){
|
fn with_target_velocity(body:&Body,style:&StyleModifiers,models:&PhysicsModels,velocity:Planar64Vec3,normal:&Planar64Vec3)->(WalkEnum,Planar64Vec3){
|
||||||
touching.constrain_velocity(models,&mut velocity);
|
|
||||||
let mut target_diff=velocity-body.velocity;
|
let mut target_diff=velocity-body.velocity;
|
||||||
//remove normal component
|
//remove normal component
|
||||||
target_diff-=normal.clone()*(normal.dot(target_diff)/normal.dot(normal.clone()));
|
target_diff-=normal.clone()*(normal.dot(target_diff)/normal.dot(normal.clone()));
|
||||||
if target_diff==Planar64Vec3::ZERO{
|
if target_diff==Planar64Vec3::ZERO{
|
||||||
let mut a=Planar64Vec3::ZERO;
|
(WalkEnum::Reached,Planar64Vec3::ZERO)
|
||||||
touching.constrain_acceleration(models,&mut a);
|
|
||||||
(WalkEnum::Reached,a)
|
|
||||||
}else{
|
}else{
|
||||||
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
//normal friction acceleration is clippedAcceleration.dot(normal)*friction
|
||||||
let diff_len=target_diff.length();
|
let diff_len=target_diff.length();
|
||||||
@ -105,21 +102,20 @@ impl WalkEnum{
|
|||||||
let accel=style.walk_accel.min(style.gravity.dot(Planar64Vec3::NEG_Y)*friction);
|
let accel=style.walk_accel.min(style.gravity.dot(Planar64Vec3::NEG_Y)*friction);
|
||||||
let time_delta=diff_len/accel;
|
let time_delta=diff_len/accel;
|
||||||
let mut a=target_diff.with_length(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)
|
(WalkEnum::Transient(WalkTarget{velocity,time:body.time+Time::from(time_delta)}),a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl WalkState{
|
impl WalkState{
|
||||||
fn ground(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&PhysicsModels,velocity:Planar64Vec3)->(Self,Planar64Vec3){
|
fn ground(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&PhysicsModels,velocity:Planar64Vec3)->(Self,Planar64Vec3){
|
||||||
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,&Planar64Vec3::Y);
|
let (walk_enum,a)=WalkEnum::with_target_velocity(body,style,models,velocity,&Planar64Vec3::Y);
|
||||||
(Self{
|
(Self{
|
||||||
state:walk_enum,
|
state:walk_enum,
|
||||||
normal:Planar64Vec3::Y,
|
normal:Planar64Vec3::Y,
|
||||||
},a)
|
},a)
|
||||||
}
|
}
|
||||||
fn ladder(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&PhysicsModels,velocity:Planar64Vec3,normal:&Planar64Vec3)->(Self,Planar64Vec3){
|
fn ladder(touching:&TouchingState,body:&Body,style:&StyleModifiers,models:&PhysicsModels,velocity:Planar64Vec3,normal:&Planar64Vec3)->(Self,Planar64Vec3){
|
||||||
let (walk_enum,a)=WalkEnum::with_target_velocity(touching,body,style,models,velocity,normal);
|
let (walk_enum,a)=WalkEnum::with_target_velocity(body,style,models,velocity,normal);
|
||||||
(Self{
|
(Self{
|
||||||
state:walk_enum,
|
state:walk_enum,
|
||||||
normal:normal.clone(),
|
normal:normal.clone(),
|
||||||
@ -208,8 +204,10 @@ impl PhysicsModels{
|
|||||||
self.models.push(model);
|
self.models.push(model);
|
||||||
model_id
|
model_id
|
||||||
}
|
}
|
||||||
fn push_attr(&mut self,attr:PhysicsCollisionAttributes){
|
fn push_attr(&mut self,attr:PhysicsCollisionAttributes)->usize{
|
||||||
|
let attr_id=self.attributes.len();
|
||||||
self.attributes.push(attr);
|
self.attributes.push(attr);
|
||||||
|
attr_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,6 +337,7 @@ struct StyleModifiers{
|
|||||||
swim_speed:Planar64,
|
swim_speed:Planar64,
|
||||||
mass:Planar64,
|
mass:Planar64,
|
||||||
mv:Planar64,
|
mv:Planar64,
|
||||||
|
surf_slope:Option<Planar64>,
|
||||||
rocket_force:Option<Planar64>,
|
rocket_force:Option<Planar64>,
|
||||||
gravity:Planar64Vec3,
|
gravity:Planar64Vec3,
|
||||||
hitbox_halfsize:Planar64Vec3,
|
hitbox_halfsize:Planar64Vec3,
|
||||||
@ -386,6 +385,7 @@ impl StyleModifiers{
|
|||||||
ladder_accel:Planar64::int(160),
|
ladder_accel:Planar64::int(160),
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
||||||
swim_speed:Planar64::int(12),
|
swim_speed:Planar64::int(12),
|
||||||
|
surf_slope:Some(Planar64::raw(7)/8),
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
||||||
}
|
}
|
||||||
@ -414,6 +414,7 @@ impl StyleModifiers{
|
|||||||
ladder_accel:Planar64::int(180),
|
ladder_accel:Planar64::int(180),
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
||||||
swim_speed:Planar64::int(12),
|
swim_speed:Planar64::int(12),
|
||||||
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
||||||
}
|
}
|
||||||
@ -441,6 +442,7 @@ impl StyleModifiers{
|
|||||||
ladder_accel:Planar64::int(180),
|
ladder_accel:Planar64::int(180),
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
||||||
swim_speed:Planar64::int(12),
|
swim_speed:Planar64::int(12),
|
||||||
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
||||||
}
|
}
|
||||||
@ -469,6 +471,7 @@ impl StyleModifiers{
|
|||||||
ladder_accel:Planar64::int(180),//?
|
ladder_accel:Planar64::int(180),//?
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
||||||
swim_speed:Planar64::int(12),//?
|
swim_speed:Planar64::int(12),//?
|
||||||
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox_halfsize:Planar64Vec3::raw(33<<28,73<<28,33<<28)/2,
|
hitbox_halfsize:Planar64Vec3::raw(33<<28,73<<28,33<<28)/2,
|
||||||
camera_offset:Planar64Vec3::raw(0,(64<<28)-(73<<27),0),
|
camera_offset:Planar64Vec3::raw(0,(64<<28)-(73<<27),0),
|
||||||
}
|
}
|
||||||
@ -496,6 +499,7 @@ impl StyleModifiers{
|
|||||||
ladder_accel:Planar64::int(180),//?
|
ladder_accel:Planar64::int(180),//?
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
||||||
swim_speed:Planar64::int(12),//?
|
swim_speed:Planar64::int(12),//?
|
||||||
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox_halfsize:Planar64Vec3::raw(33<<28,73<<28,33<<28)/2,
|
hitbox_halfsize:Planar64Vec3::raw(33<<28,73<<28,33<<28)/2,
|
||||||
camera_offset:Planar64Vec3::raw(0,(64<<28)-(73<<27),0),
|
camera_offset:Planar64Vec3::raw(0,(64<<28)-(73<<27),0),
|
||||||
}
|
}
|
||||||
@ -519,6 +523,7 @@ impl StyleModifiers{
|
|||||||
ladder_accel:Planar64::int(180),
|
ladder_accel:Planar64::int(180),
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
||||||
swim_speed:Planar64::int(12),
|
swim_speed:Planar64::int(12),
|
||||||
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
hitbox_halfsize:Planar64Vec3::int(2,5,2)/2,
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
||||||
}
|
}
|
||||||
@ -642,6 +647,7 @@ impl PhysicsOutputState{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
enum PhysicsCollisionAttributes{
|
enum PhysicsCollisionAttributes{
|
||||||
Contact{//track whether you are contacting the object
|
Contact{//track whether you are contacting the object
|
||||||
contacting:crate::model::ContactingAttributes,
|
contacting:crate::model::ContactingAttributes,
|
||||||
@ -652,6 +658,17 @@ enum PhysicsCollisionAttributes{
|
|||||||
general:crate::model::GameMechanicAttributes,
|
general:crate::model::GameMechanicAttributes,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
struct NonPhysicsError;
|
||||||
|
impl TryFrom<&crate::model::CollisionAttributes> for PhysicsCollisionAttributes{
|
||||||
|
type Error=NonPhysicsError;
|
||||||
|
fn try_from(value:&crate::model::CollisionAttributes)->Result<Self,Self::Error>{
|
||||||
|
match value{
|
||||||
|
crate::model::CollisionAttributes::Decoration=>Err(NonPhysicsError),
|
||||||
|
crate::model::CollisionAttributes::Contact{contacting,general}=>Ok(Self::Contact{contacting:contacting.clone(),general:general.clone()}),
|
||||||
|
crate::model::CollisionAttributes::Intersect{intersecting,general}=>Ok(Self::Intersect{intersecting:intersecting.clone(),general:general.clone()}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PhysicsModel{
|
pub struct PhysicsModel{
|
||||||
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es
|
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es
|
||||||
@ -664,7 +681,7 @@ pub struct PhysicsModel{
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PhysicsModel{
|
impl PhysicsModel{
|
||||||
fn new(mesh_id:usize,attr_id:usize,transform:crate::integer::Planar64Affine3)->Self{
|
pub fn new(mesh_id:usize,attr_id:usize,transform:crate::integer::Planar64Affine3)->Self{
|
||||||
let normal_transform=transform.matrix3.inverse().transpose();
|
let normal_transform=transform.matrix3.inverse().transpose();
|
||||||
Self{
|
Self{
|
||||||
mesh_id,
|
mesh_id,
|
||||||
@ -674,18 +691,12 @@ impl PhysicsModel{
|
|||||||
normal_determinant:normal_transform.determinant(),
|
normal_determinant:normal_transform.determinant(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn from_model(mesh_id:usize,instance:&crate::model::ModelInstance)->Option<Self>{
|
|
||||||
match &instance.attributes{
|
|
||||||
crate::model::CollisionAttributes::Contact{contacting,general}=>Some(PhysicsModel::new(mesh_id,instance.transform.clone(),PhysicsCollisionAttributes::Contact{contacting:contacting.clone(),general:general.clone()})),
|
|
||||||
crate::model::CollisionAttributes::Intersect{intersecting,general}=>Some(PhysicsModel::new(mesh_id,instance.transform.clone(),PhysicsCollisionAttributes::Intersect{intersecting:intersecting.clone(),general:general.clone()})),
|
|
||||||
crate::model::CollisionAttributes::Decoration=>None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
||||||
struct ContactCollision{
|
struct ContactCollision{
|
||||||
face_id:crate::model_physics::MinkowskiFace,
|
//face_id:crate::model_physics::MinkowskiFace,
|
||||||
|
face_id:crate::model_physics::FaceId,
|
||||||
model_id:usize,//using id to avoid lifetimes
|
model_id:usize,//using id to avoid lifetimes
|
||||||
}
|
}
|
||||||
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
||||||
@ -697,6 +708,14 @@ enum Collision{
|
|||||||
Contact(ContactCollision),
|
Contact(ContactCollision),
|
||||||
Intersect(IntersectCollision),
|
Intersect(IntersectCollision),
|
||||||
}
|
}
|
||||||
|
impl Collision{
|
||||||
|
fn model_id(&self)->usize{
|
||||||
|
match self{
|
||||||
|
&Collision::Contact(ContactCollision{model_id,face_id:_})
|
||||||
|
|&Collision::Intersect(IntersectCollision{model_id})=>model_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct TouchingState{
|
struct TouchingState{
|
||||||
contacts:std::collections::HashSet::<ContactCollision>,
|
contacts:std::collections::HashSet::<ContactCollision>,
|
||||||
@ -719,23 +738,56 @@ impl TouchingState{
|
|||||||
Collision::Intersect(collision)=>self.intersects.remove(collision),
|
Collision::Intersect(collision)=>self.intersects.remove(collision),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get_acceleration(&self,gravity:Planar64Vec3)->Planar64Vec3{
|
|
||||||
//accelerators
|
|
||||||
//water
|
|
||||||
//contact constrain?
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn constrain_velocity(&self,models:&PhysicsModels,velocity:&mut Planar64Vec3){
|
fn constrain_velocity(&self,models:&PhysicsModels,velocity:&mut Planar64Vec3){
|
||||||
|
//TODO: trey push solve
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
//trey push solve
|
let n=contact.normal(models);
|
||||||
|
velocity-=n.dot(velocity)/n.length();
|
||||||
}
|
}
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
fn constrain_acceleration(&self,models:&PhysicsModels,acceleration:&mut Planar64Vec3){
|
fn constrain_acceleration(&self,models:&PhysicsModels,acceleration:&mut Planar64Vec3){
|
||||||
|
//TODO: trey push solve
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
//trey push solve
|
let n=contact.normal(models);
|
||||||
|
acceleration-=n.dot(acceleration)/n.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_move_state(&self,mut a:Planar64Vec3)->(MoveState,Planar64Vec3){
|
||||||
|
//check current move conditions and use heuristics to determine
|
||||||
|
//which ladder to climb on, which ground to walk on, etc
|
||||||
|
//collect move state affecting objects from contacts (accelerator,water,ladder,ground)
|
||||||
|
for contact in &self.contacts{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
for intersect in &self.intersects{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
(move_state,a)
|
||||||
|
}
|
||||||
|
fn predict_collision_end(&self,collector:&mut crate::instruction::InstructionCollector<PhysicsInstruction>,models:&PhysicsModels,body:&Body,time:Time){
|
||||||
|
for contact in &self.contacts{
|
||||||
|
//detect face slide off
|
||||||
|
collector.collect(models.mesh(contact.model_id).brute_out_face(body,collector.time(),contact.face_id).map(|(face,time)|{
|
||||||
|
TimedInstruction{
|
||||||
|
time,
|
||||||
|
instruction:PhysicsInstruction::CollisionStart(
|
||||||
|
Collision::Contact(ContactCollision{model_id:contact.model_id,face_id:face})
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
let relative_body=VirtualBody::relative(&Body::default(),body).body(time);
|
||||||
|
for intersect in &self.intersects{
|
||||||
|
//detect model collision in reverse
|
||||||
|
collector.collect(models.mesh(intersect.model_id).brute_out(&relative_body,collector.time()).map(|(face,time)|{
|
||||||
|
TimedInstruction{
|
||||||
|
time,
|
||||||
|
instruction:PhysicsInstruction::CollisionStart(
|
||||||
|
Collision::Intersect(IntersectCollision{model_id:intersect.model_id})
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,13 +897,21 @@ impl PhysicsState {
|
|||||||
pub fn generate_models(&mut self,indexed_models:&crate::model::IndexedModelInstances){
|
pub fn generate_models(&mut self,indexed_models:&crate::model::IndexedModelInstances){
|
||||||
let mut starts=Vec::new();
|
let mut starts=Vec::new();
|
||||||
let mut spawns=Vec::new();
|
let mut spawns=Vec::new();
|
||||||
|
let mut attr_hash=std::collections::HashMap::new();
|
||||||
for model in &indexed_models.models{
|
for model in &indexed_models.models{
|
||||||
let mesh_id=self.meshes.len();
|
let mesh_id=self.meshes.len();
|
||||||
let mut make_mesh=false;
|
let mut make_mesh=false;
|
||||||
for model_instance in &model.instances{
|
for model_instance in &model.instances{
|
||||||
if let Some(model_physics)=PhysicsModel::from_model(mesh_id,model_instance){
|
if let Ok(physics_attributes)=PhysicsCollisionAttributes::try_from(&model_instance.attributes){
|
||||||
|
let attr_id=if let Some(&attr_id)=attr_hash.get(&physics_attributes){
|
||||||
|
attr_id
|
||||||
|
}else{
|
||||||
|
let attr_id=self.models.push_attr(physics_attributes.clone());
|
||||||
|
attr_hash.insert(physics_attributes,attr_id);
|
||||||
|
attr_id
|
||||||
|
};
|
||||||
|
let model_physics=PhysicsModel::new(mesh_id,attr_id,model_instance.transform);
|
||||||
make_mesh=true;
|
make_mesh=true;
|
||||||
//TODO: index attributes
|
|
||||||
let model_id=self.models.push_model(model_physics);
|
let model_id=self.models.push_model(model_physics);
|
||||||
for attr in &model_instance.temp_indexing{
|
for attr in &model_instance.temp_indexing{
|
||||||
match attr{
|
match attr{
|
||||||
@ -918,6 +978,13 @@ impl PhysicsState {
|
|||||||
fn set_control(&mut self,control:u32,state:bool){
|
fn set_control(&mut self,control:u32,state:bool){
|
||||||
self.controls=if state{self.controls|control}else{self.controls&!control};
|
self.controls=if state{self.controls|control}else{self.controls&!control};
|
||||||
}
|
}
|
||||||
|
fn gravity(&self)->Planar64Vec3{
|
||||||
|
let mut a=self.style.gravity;
|
||||||
|
if let Some(rocket_force)=self.style.rocket_force{
|
||||||
|
a+=self.style.get_propulsion_control_dir(&self.camera,self.controls,&self.next_mouse,self.time)*rocket_force;
|
||||||
|
}
|
||||||
|
a
|
||||||
|
}
|
||||||
fn jump(&mut self){
|
fn jump(&mut self){
|
||||||
match &self.move_state{
|
match &self.move_state{
|
||||||
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
|
MoveState::Walk(walk_state)|MoveState::Ladder(walk_state)=>{
|
||||||
@ -976,13 +1043,13 @@ impl PhysicsState {
|
|||||||
MoveState::Walk(WalkState{normal,state})=>{
|
MoveState::Walk(WalkState{normal,state})=>{
|
||||||
let n=normal;
|
let n=normal;
|
||||||
let a;
|
let a;
|
||||||
(*state,a)=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);
|
(*state,a)=WalkEnum::with_target_velocity(&self.body,&self.style,&self.models,self.style.get_walk_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&n);
|
||||||
Some(a)
|
Some(a)
|
||||||
},
|
},
|
||||||
MoveState::Ladder(WalkState{normal,state})=>{
|
MoveState::Ladder(WalkState{normal,state})=>{
|
||||||
let n=normal;
|
let n=normal;
|
||||||
let a;
|
let a;
|
||||||
(*state,a)=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);
|
(*state,a)=WalkEnum::with_target_velocity(&self.body,&self.style,&self.models,self.style.get_ladder_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time),&n);
|
||||||
Some(a)
|
Some(a)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1003,28 +1070,32 @@ impl PhysicsState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState {
|
impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState{
|
||||||
//this little next instruction function can cache its return value and invalidate the cached value by watching the State.
|
//this little next instruction function can cache its return value and invalidate the cached value by watching the State.
|
||||||
fn next_instruction(&self,time_limit:Time) -> Option<TimedInstruction<PhysicsInstruction>> {
|
fn next_instruction(&self,time_limit:Time)->Option<TimedInstruction<PhysicsInstruction>>{
|
||||||
//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);
|
||||||
|
|
||||||
collector.collect(self.next_move_instruction());
|
collector.collect(self.next_move_instruction());
|
||||||
|
|
||||||
//check for collision ends
|
//check for collision ends
|
||||||
self.touching.next_instruction(&mut collector,self.style.mesh,self.body,self.time,collector.time());
|
self.touching.predict_collision_end(&mut collector,&self.models,&self.body,self.time);
|
||||||
//check for collision starts
|
//check for collision starts
|
||||||
let mut aabb=crate::aabb::Aabb::default();
|
let mut aabb=crate::aabb::Aabb::default();
|
||||||
aabb.grow(self.body.extrapolated_position(self.time));
|
aabb.grow(self.body.extrapolated_position(self.time));
|
||||||
aabb.grow(self.body.extrapolated_position(collector.time()));
|
aabb.grow(self.body.extrapolated_position(collector.time()));
|
||||||
aabb.inflate(self.style.hitbox_halfsize);
|
aabb.inflate(self.style.hitbox_halfsize);
|
||||||
|
//common body
|
||||||
|
let relative_body=VirtualBody::relative(&Body::default(),&self.body).body(self.time);
|
||||||
self.bvh.the_tester(&aabb,&mut |id|{
|
self.bvh.the_tester(&aabb,&mut |id|{
|
||||||
//no checks are needed because of the time limits.
|
//no checks are needed because of the time limits.
|
||||||
let minkowski=crate::model_physics::MinkowskiMesh::minkowski_sum(self.style.mesh,&self.models.mesh(id));
|
//let minkowski=crate::model_physics::MinkowskiMesh::minkowski_sum(self.style.mesh,&self.models.mesh(id));
|
||||||
let relative_body=VirtualBody::relative(&self.body,&Body::default()).body(self.time);
|
//collector.collect(crate::face_crawler::predict_collision(&minkowski,&relative_body,collector.time()).map(|(face,time)|{
|
||||||
collector.collect(crate::face_crawler::predict_collision(&minkowski,&relative_body,collector.time()).map(|(face,time)|{
|
collector.collect(self.models.mesh(id).brute_in(&relative_body,collector.time()).map(|(face,time)|{
|
||||||
//TODO: match model attribute and generate Collision::{Contact,Intersect}
|
TimedInstruction{time,instruction:PhysicsInstruction::CollisionStart(match self.models.attr(id){
|
||||||
TimedInstruction{time,instruction:PhysicsInstruction::CollisionStart(Collision::Contact(ContactCollision{model_id:id,face_id:face}))}
|
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>Collision::Contact(ContactCollision{model_id:id,face_id:face}),
|
||||||
|
PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>Collision::Intersect(IntersectCollision{model_id:id}),
|
||||||
|
})}
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
collector.instruction()
|
collector.instruction()
|
||||||
@ -1066,7 +1137,7 @@ fn run_teleport_behaviour(teleport_behaviour:&Option<crate::model::TeleportBehav
|
|||||||
None
|
None
|
||||||
},
|
},
|
||||||
&crate::model::StageElementBehaviour::Checkpoint{ordered_checkpoint_id,unordered_checkpoint_count}=>{
|
&crate::model::StageElementBehaviour::Checkpoint{ordered_checkpoint_id,unordered_checkpoint_count}=>{
|
||||||
if (ordered_checkpoint_id.is_none()||ordered_checkpoint_id.is_some_and(|id|id<game.next_ordered_checkpoint_id))
|
if ordered_checkpoint_id.map_or(true,|id|id<game.next_ordered_checkpoint_id)
|
||||||
&&unordered_checkpoint_count<=game.unordered_checkpoints.len() as u32{
|
&&unordered_checkpoint_count<=game.unordered_checkpoints.len() as u32{
|
||||||
//pass
|
//pass
|
||||||
None
|
None
|
||||||
@ -1107,16 +1178,18 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
}
|
}
|
||||||
match ins.instruction{
|
match ins.instruction{
|
||||||
PhysicsInstruction::CollisionStart(c)=>{
|
PhysicsInstruction::CollisionStart(c)=>{
|
||||||
match self.models.attr(c.model_id()){
|
let model_id=c.model_id();
|
||||||
|
match self.models.attr(model_id){
|
||||||
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
||||||
let mut v=self.body.velocity;
|
let mut v=self.body.velocity;
|
||||||
match &contacting.contact_behaviour{
|
match &contacting.contact_behaviour{
|
||||||
Some(crate::model::ContactingBehaviour::Surf)=>println!("I'm surfing!"),
|
Some(crate::model::ContactingBehaviour::Surf)=>println!("I'm surfing!"),
|
||||||
Some(crate::model::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
|
Some(crate::model::ContactingBehaviour::Cling)=>println!("Unimplemented!"),
|
||||||
&Some(crate::model::ContactingBehaviour::Elastic(elasticity))=>{
|
&Some(crate::model::ContactingBehaviour::Elastic(elasticity))=>{
|
||||||
let n=c.normal(&self.models);
|
// let n=c.normal(&self.models);
|
||||||
let d=n.dot(v)*Planar64::raw(-1-elasticity as i64);
|
// let d=n.dot(v)*Planar64::raw(-1-elasticity as i64);
|
||||||
v-=n*(d/n.dot(n));
|
// v-=n*(d/n.dot(n));
|
||||||
|
todo!()
|
||||||
},
|
},
|
||||||
Some(crate::model::ContactingBehaviour::Ladder(contacting_ladder))=>{
|
Some(crate::model::ContactingBehaviour::Ladder(contacting_ladder))=>{
|
||||||
if contacting_ladder.sticky{
|
if contacting_ladder.sticky{
|
||||||
@ -1124,18 +1197,21 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
v=Planar64Vec3::ZERO;//model.velocity
|
v=Planar64Vec3::ZERO;//model.velocity
|
||||||
}
|
}
|
||||||
//ladder walkstate
|
//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));
|
let mut target_velocity=self.style.get_ladder_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time);
|
||||||
|
self.touching.constrain_velocity(&self.models,&mut target_velocity);
|
||||||
|
let (walk_state,mut a)=WalkState::ladder(&self.touching,&self.body,&self.style,&self.models,target_velocity,&c.normal(&self.models));
|
||||||
self.move_state=MoveState::Ladder(walk_state);
|
self.move_state=MoveState::Ladder(walk_state);
|
||||||
|
self.touching.constrain_acceleration(&self.models,&mut a);
|
||||||
self.body.acceleration=a;
|
self.body.acceleration=a;
|
||||||
}
|
}
|
||||||
None=>match &c.face {
|
None=>if self.style.surf_slope.map_or(true,|s|s<c.normal(&self.models).slope(up)){
|
||||||
TreyMeshFace::Top => {
|
//ground
|
||||||
//ground
|
let mut target_velocity=self.style.get_walk_target_velocity(&self.camera,self.controls,&self.next_mouse,self.time);
|
||||||
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.touching.constrain_velocity(&self.models,&mut target_velocity);
|
||||||
self.move_state=MoveState::Walk(walk_state);
|
let (walk_state,mut a)=WalkState::ground(&self.touching,&self.body,&self.style,&self.models,target_velocity);
|
||||||
self.body.acceleration=a;
|
self.move_state=MoveState::Walk(walk_state);
|
||||||
},
|
self.touching.constrain_acceleration(&self.models,&mut a);
|
||||||
_ => (),
|
self.body.acceleration=a;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
//check ground
|
//check ground
|
||||||
@ -1173,7 +1249,8 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
if self.style.get_control(StyleModifiers::CONTROL_JUMP,self.controls){
|
if self.style.get_control(StyleModifiers::CONTROL_JUMP,self.controls){
|
||||||
self.jump();
|
self.jump();
|
||||||
}
|
}
|
||||||
if let Some(a)=self.refresh_walk_target(){
|
if let Some(mut a)=self.refresh_walk_target(){
|
||||||
|
self.touching.constrain_acceleration(&self.models,&mut a);
|
||||||
self.body.acceleration=a;
|
self.body.acceleration=a;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1186,18 +1263,12 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
},
|
},
|
||||||
PhysicsInstruction::CollisionEnd(c) => {
|
PhysicsInstruction::CollisionEnd(c) => {
|
||||||
match self.models.attr(c.model_id()){
|
match self.models.attr(c.model_id()){
|
||||||
PhysicsCollisionAttributes::Contact{contacting: _,general: _}=>{
|
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>{
|
||||||
self.touching.remove(&c);//remove contact before calling contact_constrain_acceleration
|
self.touching.remove(&c);//remove contact before calling contact_constrain_acceleration
|
||||||
let mut a=self.style.gravity;
|
|
||||||
if let Some(rocket_force)=self.style.rocket_force{
|
|
||||||
a+=self.style.get_propulsion_control_dir(&self.camera,self.controls,&self.next_mouse,self.time)*rocket_force;
|
|
||||||
}
|
|
||||||
self.touching.constrain_acceleration(&self.models,&mut a);
|
|
||||||
self.body.acceleration=a;
|
|
||||||
//check ground
|
//check ground
|
||||||
self.move_state=self.touching.get_move_state();
|
(self.move_state,self.body.acceleration)=self.touching.get_move_state(self.gravity());
|
||||||
},
|
},
|
||||||
PhysicsCollisionAttributes::Intersect{intersecting: _,general: _}=>{
|
PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>{
|
||||||
self.touching.remove(&c);
|
self.touching.remove(&c);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1271,7 +1342,8 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
|
|||||||
PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle!
|
PhysicsInputInstruction::Idle => {refresh_walk_target=false;},//literally idle!
|
||||||
}
|
}
|
||||||
if refresh_walk_target{
|
if refresh_walk_target{
|
||||||
if let Some(a)=self.refresh_walk_target(){
|
if let Some(mut a)=self.refresh_walk_target(){
|
||||||
|
self.touching.constrain_acceleration(&self.models,&mut a);
|
||||||
self.body.acceleration=a;
|
self.body.acceleration=a;
|
||||||
}else if let Some(rocket_force)=self.style.rocket_force{
|
}else if let Some(rocket_force)=self.style.rocket_force{
|
||||||
let mut a=self.style.gravity;
|
let mut a=self.style.gravity;
|
||||||
|
Loading…
Reference in New Issue
Block a user