runtime attributes + implement model intersection (but not collision end)

This commit is contained in:
Quaternions 2023-10-04 14:15:04 -07:00
parent fb2e2afeb9
commit b8f13539db
2 changed files with 102 additions and 36 deletions

View File

@ -221,13 +221,13 @@ impl Camera {
}
pub struct GameMechanicsState{
pub spawn_id:u32,
pub stage_id:u32,
//jump_counts:HashMap<u32,u32>,
}
impl std::default::Default for GameMechanicsState{
fn default() -> Self {
Self{
spawn_id:0,
stage_id:0,
}
}
}
@ -317,7 +317,8 @@ pub struct PhysicsState{
pub world:WorldState,//currently there is only one state the world can be in
pub game:GameMechanicsState,
pub style:StyleModifiers,
pub contacts:std::collections::HashSet::<RelativeCollision>,
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
pub camera:Camera,
@ -459,6 +460,7 @@ pub struct ModelPhysics {
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es
//in this iteration, all it needs is extents.
mesh: TreyMesh,
transform:glam::Affine3A,
attributes:PhysicsCollisionAttributes,
}
@ -471,6 +473,7 @@ impl ModelPhysics {
Self{
mesh:aabb,
attributes,
transform:transform.clone(),
}
}
pub fn from_model(model:&crate::model::IndexedModel,instance:&crate::model::ModelInstance) -> Option<Self> {
@ -557,6 +560,8 @@ impl PhysicsState {
pub fn clear(&mut self){
self.models.clear();
self.modes.clear();
self.contacts.clear();
self.intersects.clear();
}
pub fn get_mode(&self,mode_id:u32)->Option<&crate::model::ModeDescription>{
if let Some(&mode)=self.mode_from_mode_id.get(&mode_id){
@ -591,7 +596,7 @@ impl PhysicsState {
}
fn contact_constrain_velocity(&self,velocity:&mut glam::Vec3){
for contact in self.contacts.iter() {
for (_,contact) in &self.contacts {
let n=contact.normal(&self.models);
let d=velocity.dot(n);
if d<0f32{
@ -600,7 +605,7 @@ impl PhysicsState {
}
}
fn contact_constrain_acceleration(&self,acceleration:&mut glam::Vec3){
for contact in self.contacts.iter() {
for (_,contact) in &self.contacts {
let n=contact.normal(&self.models);
let d=acceleration.dot(n);
if d<0f32{
@ -973,12 +978,19 @@ impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState
//JUST POLLING!!! NO MUTATION
let mut collector = crate::instruction::InstructionCollector::new(time_limit);
//check for collision stop instructions with curent contacts
for collision_data in self.contacts.iter() {
for (_,collision_data) in &self.contacts {
collector.collect(self.predict_collision_end(self.time,time_limit,collision_data));
}
// for collision_data in &self.intersects{
// collector.collect(self.predict_collision_end2(self.time,time_limit,collision_data));
// }
//check for collision start instructions (against every part in the game with no optimization!!)
for i in 0..self.models.len() {
collector.collect(self.predict_collision_start(self.time,time_limit,i as u32));
let i=i as u32;
if self.contacts.contains_key(&i)||self.intersects.contains_key(&i){
continue;
}
collector.collect(self.predict_collision_start(self.time,time_limit,i));
}
if self.grounded {
//walk maintenance
@ -1013,15 +1025,54 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
self.spawn_point=position;
}
PhysicsInstruction::CollisionStart(c) => {
//check ground
match &c.face {
let model=c.model(&self.models).unwrap();
match &model.attributes{
PhysicsCollisionAttributes::Contact{contacting,general}=>{
match &contacting.surf{
Some(surf)=>println!("I'm surfing!"),
None=>match &c.face {
AabbFace::Top => {
//ground
self.grounded=true;
},
_ => (),
},
}
self.contacts.insert(c);
match &general.booster{
Some(booster)=>self.body.velocity+=booster.velocity,
None=>(),
}
match &general.stage_element{
Some(stage_element)=>{
if stage_element.force||self.game.stage_id<stage_element.stage_id{
self.game.stage_id=stage_element.stage_id;
}
match stage_element.behaviour{
crate::model::StageElementBehaviour::SpawnAt=>(),
crate::model::StageElementBehaviour::Trigger
|crate::model::StageElementBehaviour::Teleport=>{
//TODO make good
if let Some(mode)=self.get_mode(stage_element.mode_id){
if let Some(&spawn)=mode.get_spawn_model_id(self.game.stage_id){
if let Some(model)=self.models.get(spawn as usize){
self.body.position=model.transform.transform_point3(glam::Vec3::Y)+glam::Vec3::Y*(self.style.hitbox_halfsize.y+0.1);
//manual clear //for c in self.contacts{process_instruction(CollisionEnd(c))}
self.contacts.clear();
self.intersects.clear();
self.body.acceleration=self.style.gravity;
self.walk.state=WalkEnum::Reached;
self.grounded=false;
}else{println!("bad1");}
}else{println!("bad2");}
}else{println!("bad3");}
},
crate::model::StageElementBehaviour::Platform=>(),
}
},
None=>(),
}
//check ground
self.contacts.insert(c.model,c);
//flatten v
let mut v=self.body.velocity;
self.contact_constrain_velocity(&mut v);
@ -1031,8 +1082,17 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
}
self.refresh_walk_target();
},
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
self.intersects.insert(c.model,c);
},
}
},
PhysicsInstruction::CollisionEnd(c) => {
self.contacts.remove(&c);//remove contact before calling contact_constrain_acceleration
let model=c.model(&self.models).unwrap();
match &model.attributes{
PhysicsCollisionAttributes::Contact{contacting,general}=>{
self.contacts.remove(&c.model);//remove contact before calling contact_constrain_acceleration
let mut a=self.style.gravity;
self.contact_constrain_acceleration(&mut a);
self.body.acceleration=a;
@ -1045,6 +1105,11 @@ impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsStat
}
self.refresh_walk_target();
},
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
self.intersects.remove(&c.model);
},
}
},
PhysicsInstruction::StrafeTick => {
let camera_mat=self.camera.simulate_move_rotation_y(self.mouse_interpolation.interpolated_position(self.time).x-self.mouse_interpolation.mouse0.x);
let control_dir=camera_mat*self.style.get_control_dir(self.controls);

View File

@ -589,7 +589,8 @@ impl framework::Example for GlobalState {
time: 0,
style:body::StyleModifiers::default(),
grounded: false,
contacts: std::collections::HashSet::new(),
contacts: std::collections::HashMap::new(),
intersects: std::collections::HashMap::new(),
models: Vec::new(),
walk: body::WalkState::new(),
camera: body::Camera::from_offset(glam::vec3(0.0,4.5-2.5,0.0),(config.width as f32)/(config.height as f32)),