Skip to content

Commit

Permalink
first_collision rewrite. somewhat fixed arrow through floor
Browse files Browse the repository at this point in the history
  • Loading branch information
Tebarem authored and andrewgazelka committed Dec 20, 2024
1 parent 60a7470 commit 7142da6
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 56 deletions.
2 changes: 2 additions & 0 deletions crates/hyperion/src/egress/sync_entity_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,8 @@ impl Module for EntityStateSyncModule {
// getting max distance
let distance = velocity.0.length();

debug!("distance = {distance}");

let ray = geometry::ray::Ray::new(center, velocity.0) * distance;

let Some(collision) = get_first_collision(ray, &world) else {
Expand Down
87 changes: 33 additions & 54 deletions crates/hyperion/src/simulation/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,66 +120,45 @@ impl Blocks {

#[must_use]
pub fn first_collision(&self, ray: Ray) -> Option<RayCollision> {
// Calculate exact start position (the block we're in)
let start_pos = ray.origin();

// Calculate end position with a small offset to handle edge cases
let end_pos = ray.origin() + ray.direction();

// Convert to block coordinates, expanding bounds to ensure we catch all blocks
let min_block = start_pos.min(end_pos).floor().as_ivec3();
let max_block = start_pos.max(end_pos).ceil().as_ivec3();

// Set up voxel traversal through the blocks
let traversal = ray.voxel_traversal(min_block, max_block);

let mut min: Option<RayCollision> = None;

for cell in traversal {
// if there is no block at this cell, return None
let block = self.get_block(cell)?;

let origin = Vec3::new(cell.x as f32, cell.y as f32, cell.z as f32);

let min_dist = block
.collision_shapes()
.map(|shape| {
geometry::aabb::Aabb::new(shape.min().as_vec3(), shape.max().as_vec3())
})
.map(|shape| shape + origin)
.filter_map(|shape| shape.intersect_ray(&ray))
.min();

let Some(min_dist) = min_dist else {
continue;
};

let collision_normal = ray.origin() + ray.direction() * min_dist.into_inner();
//let collision_normal = (collision_point - origin).normalize();

match &min {
Some(current_min) => {
if min_dist.into_inner() < current_min.distance {
min = Some(RayCollision {
distance: min_dist.into_inner(),
location: cell,
normal: collision_normal,
block,
});
}
}
None => {
min = Some(RayCollision {
distance: min_dist.into_inner(),
location: cell,
normal: collision_normal,
// Get ray properties
let direction = ray.direction().normalize();
let max_distance = ray.direction().length();
let step_size = 0.1; // Small increment to check along ray

// Walk along ray
let mut current_distance = 0.0;
while current_distance <= max_distance {
let current_pos = ray.origin() + direction * current_distance;
let block_pos = current_pos.floor().as_ivec3();

if let Some(block) = self.get_block(block_pos) {
let origin = Vec3::new(block_pos.x as f32, block_pos.y as f32, block_pos.z as f32);

let collision = block
.collision_shapes()
.map(|shape| {
geometry::aabb::Aabb::new(shape.min().as_vec3(), shape.max().as_vec3())
})
.map(|shape| shape + origin)
.filter_map(|shape| shape.intersect_ray(&ray))
.min();

if let Some(dist) = collision {
let hit_point = ray.origin() + direction * dist.into_inner();

return Some(RayCollision {
distance: dist.into_inner(),
location: block_pos,
normal: hit_point,
block,
});
}
}

current_distance += step_size;
}

min
None
}

#[must_use]
Expand Down
4 changes: 2 additions & 2 deletions events/tag/src/module/bow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ impl Module for BowModule {
world,
&mut EventQueue<event::ProjectileBlockEvent>,
)
.singleton()
.kind::<flecs::pipeline::PostUpdate>()
.multi_threaded()
.kind::<flecs::pipeline::PreStore>()
.each_iter(move |it, _, event_queue| {
let _system = it.system();
let world = it.world();
Expand Down

0 comments on commit 7142da6

Please sign in to comment.