From 93e34b2c88fd3dbc7f6d8509d7a04d33c48ce512 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Wed, 14 Feb 2024 21:56:59 +0100 Subject: [PATCH] refactor stuff --- kubi/src/client_physics.rs | 86 ++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/kubi/src/client_physics.rs b/kubi/src/client_physics.rs index 17bcb7b..7bb2aad 100644 --- a/kubi/src/client_physics.rs +++ b/kubi/src/client_physics.rs @@ -8,8 +8,21 @@ use crate::{delta_time::DeltaTime, world::ChunkStorage}; #[derive(Unique)] pub struct GlobalClPhysicsConfig { pub gravity: Vec3, + ///XXX: currenly unused: + pub iterations: usize, } +impl Default for GlobalClPhysicsConfig { + fn default() -> Self { + Self { + gravity: Vec3::new(0., -9.8, 0.), + iterations: 10, + } + } +} + +//TODO: actors should be represented by a vertical line, not a point. +//XXX: maybe a capsule? (or configurable hull?) #[derive(Component)] pub struct ClPhysicsActor { pub offset: Vec3, @@ -18,7 +31,8 @@ pub struct ClPhysicsActor { pub terminal_velocity: f32, //TODO: this should be configurable per block pub friction_agains_ground: f32, - on_ground_flag: bool, + flag_ground: bool, + flag_collision: bool, } impl ClPhysicsActor { @@ -27,7 +41,7 @@ impl ClPhysicsActor { } pub fn on_ground(&self) -> bool { - self.on_ground_flag + self.flag_ground } } @@ -40,73 +54,91 @@ impl Default for ClPhysicsActor { velocity: Vec3::ZERO, terminal_velocity: 40., friction_agains_ground: 0.5, - on_ground_flag: false, + flag_ground: false, + flag_collision: false, } } } +trait BlockCollisionExt { + fn collision_type(&self) -> CollisionType; + fn is_solid(&self) -> bool { + self.collision_type() == CollisionType::Solid + } +} + +impl BlockCollisionExt for Option { + fn collision_type(&self) -> CollisionType { + self.unwrap_or(Block::Air).descriptor().collision + } +} + +impl BlockCollisionExt for Block { + fn collision_type(&self) -> CollisionType { + self.descriptor().collision + } +} + pub fn init_client_physics( storages: AllStoragesView, ) { - storages.add_unique(GlobalClPhysicsConfig { - gravity: Vec3::new(0., -1.0, 0.), - }); + storages.add_unique(GlobalClPhysicsConfig::default()); } pub fn update_client_physics_late( mut actors: ViewMut, mut transforms: ViewMut, - phy_conf: UniqueView, + conf: UniqueView, world: UniqueView, dt: UniqueView, ) { for (mut actor, mut transform) in (&mut actors, &mut transforms).iter() { //apply forces let actor_forces = actor.forces; - actor.velocity += actor_forces + phy_conf.gravity; + actor.velocity += (actor_forces + conf.gravity) * dt.0.as_secs_f32(); actor.forces = Vec3::ZERO; + //get position let (scale, rotation, mut actor_position) = transform.0.to_scale_rotation_translation(); actor_position -= actor.offset; + + //get grid-aligned pos and blocks let actor_block_pos = actor_position.floor().as_ivec3(); let actor_block = world.get_block(actor_block_pos); let actor_block_below = world.get_block(actor_block_pos + IVec3::NEG_Y); - actor.on_ground_flag = - actor_block_below.map_or_else(|| false, |x| x.descriptor().collision == CollisionType::Solid) || - actor_block.map_or_else(|| false, |x| x.descriptor().collision == CollisionType::Solid); + + //update flags + actor.flag_collision = actor_block.is_solid(); + actor.flag_ground = actor.flag_collision || actor_block_below.is_solid(); + //push actor back out of the block - if actor_block.is_some() { - //first, compute the normal (assuming actor is a point) - //must be accurate! - let mut normal = Vec3::ZERO; - for i in 0..3 { - let mut offset = Vec3::ZERO; - offset[i] = 0.5; - let block_pos = actor_block_pos + offset.as_ivec3(); - let block = world.get_block(block_pos).unwrap_or(Block::Air); - if block.descriptor().collision == CollisionType::Solid { - normal[i] = 1.; - } - } + if actor.flag_collision { + //first, compute restitution, based on position inside the block + // let block_center = actor_block_pos.as_f32() + Vec3::ONE * 0.5; + // let to_block_center = actor_position - block_center; + //then, based on normal: //push the actor back - actor_position += normal * 0.5; + //actor_position += normal * 0.5; //cancel out velocity in the direction of the normal // let dot = actor.velocity.dot(normal); // if dot > 0. { // //actor.velocity -= normal * dot; // actor.velocity = Vec3::ZERO; // } - if actor.on_ground_flag { + + //HACK: for now, just stop the vertical velocity if on ground altogether, + //as we don't have proper collision velocity resolution yet (we need to compute dot product or sth) + if actor.flag_ground { actor.velocity.y = 0.; } } + //Apply velocity actor_position += actor.velocity * dt.0.as_secs_f32(); actor_position += actor.offset; transform.0 = Mat4::from_scale_rotation_translation(scale, rotation, actor_position); } - // for (_, mut transform) in (&controllers, &mut transforms).iter() { // let (scale, rotation, mut translation) = transform.0.to_scale_rotation_translation(); // translation.y -= dt.0.as_secs_f32() * 100.;