alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates common src physics.rs
//! Ports of `AxisAlignedBB`, the intercept helpers of `Vec3D` and `MovingObjectPosition`.
use glam::DVec3;
#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub struct Aabb {
pub min: DVec3,
pub max: DVec3,
}
impl Aabb {
pub const fn new(min: DVec3, max: DVec3) -> Self {
Self { min, max }
}
pub fn from_coords(x1: f64, y1: f64, z1: f64, x2: f64, y2: f64, z2: f64) -> Self {
Self::new(DVec3::new(x1, y1, z1), DVec3::new(x2, y2, z2))
}
/// `addCoord`: grown in the direction of a movement.
pub fn expand_towards(&self, d: DVec3) -> Self {
let mut b = *self;
for axis in 0..3 {
if d[axis] < 0.0 {
b.min[axis] += d[axis];
}
if d[axis] > 0.0 {
b.max[axis] += d[axis];
}
}
b
}
/// `expand`: grown by `d` on every side.
pub fn inflate(&self, d: DVec3) -> Self {
Self::new(self.min - d, self.max + d)
}
/// `contract`.
pub fn deflate(&self, d: DVec3) -> Self {
Self::new(self.min + d, self.max - d)
}
/// `getOffsetBoundingBox`.
pub fn offset(&self, d: DVec3) -> Self {
Self::new(self.min + d, self.max + d)
}
fn clip(&self, other: &Self, axis: usize, mut delta: f64) -> f64 {
let (a, b) = ((axis + 1) % 3, (axis + 2) % 3);
let overlaps = |i: usize| other.max[i] > self.min[i] && other.min[i] < self.max[i];
if !overlaps(a) || !overlaps(b) {
return delta;
}
if delta > 0.0 && other.max[axis] <= self.min[axis] {
delta = delta.min(self.min[axis] - other.max[axis]);
}
if delta < 0.0 && other.min[axis] >= self.max[axis] {
delta = delta.max(self.max[axis] - other.min[axis]);
}
delta
}
/// `calculateXOffset`: how far `other` may move along x before hitting this box.
pub fn clip_x(&self, other: &Self, dx: f64) -> f64 {
self.clip(other, 0, dx)
}
pub fn clip_y(&self, other: &Self, dy: f64) -> f64 {
self.clip(other, 1, dy)
}
pub fn clip_z(&self, other: &Self, dz: f64) -> f64 {
self.clip(other, 2, dz)
}
/// `intersectsWith`: open intervals on every axis.
pub fn intersects(&self, other: &Self) -> bool {
(0..3).all(|i| other.max[i] > self.min[i] && other.min[i] < self.max[i])
}
/// `isVecInside`.
pub fn contains(&self, p: DVec3) -> bool {
(0..3).all(|i| p[i] > self.min[i] && p[i] < self.max[i])
}
pub fn average_edge(&self) -> f64 {
let d = self.max - self.min;
(d.x + d.y + d.z) / 3.0
}
/// `calculateIntercept`: the nearest face hit by the segment and its side.
pub fn intercept(&self, start: DVec3, end: DVec3) -> Option<(DVec3, u8)> {
nearest_face(start, end, self.min, self.max)
}
}
/// `Vec3D.getIntermediateWithXValue` and friends: the point of the segment where an axis has
/// a value, if within the segment.
pub fn intermediate(start: DVec3, end: DVec3, axis: usize, value: f64) -> Option<DVec3> {
let d = end - start;
if d[axis] * d[axis] < f64::from(1.0e-7_f32) {
return None;
}
let t = (value - start[axis]) / d[axis];
(0.0..=1.0).contains(&t).then(|| start + d * t)
}
/// The face intercepts of `collisionRayTrace`/`calculateIntercept` for a box, nearest first by
/// distance from `start`, with the side numbers 4, 5, 0, 1, 2, 3 for -x, +x, -y, +y, -z, +z.
pub fn nearest_face(start: DVec3, end: DVec3, min: DVec3, max: DVec3) -> Option<(DVec3, u8)> {
let candidates = [
(0, min.x, 4),
(0, max.x, 5),
(1, min.y, 0),
(1, max.y, 1),
(2, min.z, 2),
(2, max.z, 3),
];
let mut best: Option<(DVec3, u8)> = None;
for (axis, value, side) in candidates {
let Some(p) = intermediate(start, end, axis, value) else {
continue;
};
let (a, b) = ((axis + 1) % 3, (axis + 2) % 3);
let inside = |i: usize| p[i] >= min[i] && p[i] <= max[i];
if !inside(a) || !inside(b) {
continue;
}
if best.is_none_or(|(q, _)| start.distance_squared(p) < start.distance_squared(q)) {
best = Some((p, side));
}
}
best
}
/// `MovingObjectPosition` for a block.
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct BlockHit {
pub x: i32,
pub y: i32,
pub z: i32,
pub side: u8,
pub point: DVec3,
}