diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2025-01-10 16:45:27 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-10 16:45:27 -0600 |
| commit | 0d16f01571ec8315f3979eae46981e559ade1cf9 (patch) | |
| tree | ea43c32a57b0e6a67579d75a134dfbc009d09781 /azalea-physics/src/clip.rs | |
| parent | 615d8f9d2ac56b3244d328587243301da253eafd (diff) | |
| download | azalea-drasl-0d16f01571ec8315f3979eae46981e559ade1cf9.tar.xz | |
Fluid physics (#199)
* start implementing fluid physics
* Initial implementation of fluid pushing
* different travel function in water
* bubble columns
* jumping in water
* cleanup
* change ultrawarm to be required
* fix for clippy
Diffstat (limited to 'azalea-physics/src/clip.rs')
| -rw-r--r-- | azalea-physics/src/clip.rs | 154 |
1 files changed, 135 insertions, 19 deletions
diff --git a/azalea-physics/src/clip.rs b/azalea-physics/src/clip.rs index 4a374f58..b6e6a9f9 100644 --- a/azalea-physics/src/clip.rs +++ b/azalea-physics/src/clip.rs @@ -1,7 +1,13 @@ -use azalea_block::{BlockState, FluidState}; +use std::collections::HashSet; + +use azalea_block::{ + fluid_state::{FluidKind, FluidState}, + BlockState, +}; use azalea_core::{ + aabb::AABB, block_hit_result::BlockHitResult, - direction::Direction, + direction::{Axis, Direction}, math::{self, lerp, EPSILON}, position::{BlockPos, Vec3}, }; @@ -80,8 +86,8 @@ impl FluidPickType { match self { Self::None => false, Self::SourceOnly => fluid_state.amount == 8, - Self::Any => fluid_state.fluid != azalea_registry::Fluid::Empty, - Self::Water => fluid_state.fluid == azalea_registry::Fluid::Water, + Self::Any => fluid_state.kind != FluidKind::Empty, + Self::Water => fluid_state.kind == FluidKind::Water, } } } @@ -198,22 +204,10 @@ pub fn traverse_blocks<C, T>( let vec = right_after_end - right_before_start; - /// Returns either -1, 0, or 1, depending on whether the number is negative, - /// zero, or positive. - /// - /// This function exists because f64::signum doesn't check for 0. - fn get_number_sign(num: f64) -> f64 { - if num == 0. { - 0. - } else { - num.signum() - } - } - let vec_sign = Vec3 { - x: get_number_sign(vec.x), - y: get_number_sign(vec.y), - z: get_number_sign(vec.z), + x: math::sign(vec.x), + y: math::sign(vec.y), + z: math::sign(vec.z), }; #[rustfmt::skip] @@ -270,3 +264,125 @@ pub fn traverse_blocks<C, T>( } } } + +pub fn box_traverse_blocks(from: &Vec3, to: &Vec3, aabb: &AABB) -> HashSet<BlockPos> { + let delta = to - from; + let traversed_blocks = BlockPos::between_closed_aabb(aabb); + if delta.length_squared() < (0.99999_f32 * 0.99999) as f64 { + return traversed_blocks.into_iter().collect(); + } + + let mut traversed_and_collided_blocks = HashSet::new(); + let target_min_pos = aabb.min; + let from_min_pos = target_min_pos - delta; + add_collisions_along_travel( + &mut traversed_and_collided_blocks, + from_min_pos, + target_min_pos, + *aabb, + ); + traversed_and_collided_blocks.extend(traversed_blocks); + traversed_and_collided_blocks +} + +pub fn add_collisions_along_travel( + collisions: &mut HashSet<BlockPos>, + from: Vec3, + to: Vec3, + aabb: AABB, +) { + let delta = to - from; + let mut min_x = from.x.floor() as i32; + let mut min_y = from.y.floor() as i32; + let mut min_z = from.z.floor() as i32; + let direction_x = math::sign_as_int(delta.x); + let direction_y = math::sign_as_int(delta.y); + let direction_z = math::sign_as_int(delta.z); + let step_x = if direction_x == 0 { + f64::MAX + } else { + direction_x as f64 / delta.x + }; + let step_y = if direction_y == 0 { + f64::MAX + } else { + direction_y as f64 / delta.y + }; + let step_z = if direction_z == 0 { + f64::MAX + } else { + direction_z as f64 / delta.z + }; + let mut cur_x = step_x + * if direction_x > 0 { + 1. - math::fract(from.x) + } else { + math::fract(from.x) + }; + let mut cur_y = step_y + * if direction_y > 0 { + 1. - math::fract(from.y) + } else { + math::fract(from.y) + }; + let mut cur_z = step_z + * if direction_z > 0 { + 1. - math::fract(from.z) + } else { + math::fract(from.z) + }; + let mut step_count = 0; + + while cur_x <= 1. || cur_y <= 1. || cur_z <= 1. { + if cur_x < cur_y { + if cur_x < cur_z { + min_x += direction_x; + cur_x += step_x; + } else { + min_z += direction_z; + cur_z += step_z; + } + } else if cur_y < cur_z { + min_y += direction_y; + cur_y += step_y; + } else { + min_z += direction_z; + cur_z += step_z; + } + + if step_count > 16 { + break; + } + step_count += 1; + + let Some(clip_location) = AABB::clip_with_from_and_to( + &Vec3::new(min_x as f64, min_y as f64, min_z as f64), + &Vec3::new((min_x + 1) as f64, (min_y + 1) as f64, (min_z + 1) as f64), + &from, + &to, + ) else { + continue; + }; + + let initial_max_x = clip_location + .x + .clamp(min_x as f64 + 1.0E-5, min_x as f64 + 1.0 - 1.0E-5); + let initial_max_y = clip_location + .y + .clamp(min_y as f64 + 1.0E-5, min_y as f64 + 1.0 - 1.0E-5); + let initial_max_z = clip_location + .z + .clamp(min_z as f64 + 1.0E-5, min_z as f64 + 1.0 - 1.0E-5); + let max_x = (initial_max_x + aabb.get_size(Axis::X)).floor() as i32; + let max_y = (initial_max_y + aabb.get_size(Axis::Y)).floor() as i32; + let max_z = (initial_max_z + aabb.get_size(Axis::Z)).floor() as i32; + + for x in min_x..=max_x { + for y in min_y..=max_y { + for z in min_z..=max_z { + collisions.insert(BlockPos::new(x, y, z)); + } + } + } + } +} |
