mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
add more collision stuff
This commit is contained in:
parent
3364b82a1e
commit
dd0589b512
6 changed files with 226 additions and 4 deletions
|
@ -64,3 +64,39 @@ pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) ->
|
|||
|
||||
min
|
||||
}
|
||||
|
||||
pub fn lcm(a: u32, b: u32) -> u64 {
|
||||
let gcd = gcd(a, b);
|
||||
(a as u64) * (b / gcd) as u64
|
||||
}
|
||||
pub fn gcd(mut a: u32, mut b: u32) -> u32 {
|
||||
while b != 0 {
|
||||
let t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
a
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_gcd() {
|
||||
assert_eq!(gcd(0, 0), 0);
|
||||
assert_eq!(gcd(1, 1), 1);
|
||||
|
||||
assert_eq!(gcd(0, 1), 1);
|
||||
assert_eq!(gcd(1, 0), 1);
|
||||
|
||||
assert_eq!(gcd(12, 8), 4);
|
||||
assert_eq!(gcd(8, 12), 4);
|
||||
|
||||
assert_eq!(gcd(12, 9), 3);
|
||||
assert_eq!(gcd(9, 12), 3);
|
||||
|
||||
assert_eq!(gcd(12, 7), 1);
|
||||
assert_eq!(gcd(7, 12), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,7 +303,6 @@ const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
|
|||
impl McBufReadable for BlockPos {
|
||||
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
|
||||
let val = i64::read_from(buf)?;
|
||||
println!("reading blockpos from {}", val);
|
||||
let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
|
||||
let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
|
||||
let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
|
||||
|
|
|
@ -44,7 +44,7 @@ pub trait DiscreteVoxelShape: Send + Sync {
|
|||
fn clone(&self) -> Box<dyn DiscreteVoxelShape>;
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Clone, Eq, PartialEq)]
|
||||
pub struct BitSetDiscreteVoxelShape {
|
||||
x_size: u32,
|
||||
y_size: u32,
|
||||
|
|
37
azalea-physics/src/collision/mergers.rs
Normal file
37
azalea-physics/src/collision/mergers.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
pub trait IndexMerger {
|
||||
// DoubleList getList();
|
||||
|
||||
// boolean forMergedIndexes(IndexMerger.IndexConsumer var1);
|
||||
|
||||
// int size();
|
||||
|
||||
// public interface IndexConsumer {
|
||||
// boolean merge(int var1, int var2, int var3);
|
||||
// }
|
||||
fn get_list(&self) -> Vec<f64>;
|
||||
fn for_merged_indexes(&self, consumer: &IndexConsumer) -> bool;
|
||||
fn size(&self) -> usize;
|
||||
}
|
||||
|
||||
type IndexConsumer = dyn FnOnce(i32, i32, i32) -> bool;
|
||||
|
||||
pub struct IdenticalMerger {
|
||||
pub coords: Vec<f64>,
|
||||
}
|
||||
impl IndexMerger for IdenticalMerger {
|
||||
fn get_list(&self) -> Vec<f64> {
|
||||
self.coords.clone()
|
||||
}
|
||||
fn for_merged_indexes(&self, consumer: &IndexConsumer) -> bool {
|
||||
let mut var2 = self.coords.len() - 1;
|
||||
for var3 in 0..var2 {
|
||||
if !consumer(var3 as i32, var3 as i32, var3 as i32) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
fn size(&self) -> usize {
|
||||
self.coords.len()
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
mod blocks;
|
||||
mod dimension_collisions;
|
||||
mod discrete_voxel_shape;
|
||||
mod mergers;
|
||||
mod shape;
|
||||
|
||||
use azalea_core::{Axis, PositionXYZ, Vec3, AABB, EPSILON};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::collision::{BitSetDiscreteVoxelShape, DiscreteVoxelShape, AABB};
|
||||
use azalea_core::{binary_search, Axis, AxisCycle, EPSILON};
|
||||
use std::cmp;
|
||||
use azalea_core::{binary_search, lcm, Axis, AxisCycle, EPSILON};
|
||||
use std::{any::Any, cmp, num::NonZeroU32};
|
||||
|
||||
use super::mergers::IndexMerger;
|
||||
|
||||
pub struct Shapes {}
|
||||
|
||||
|
@ -9,6 +11,11 @@ pub fn block_shape() -> Box<dyn VoxelShape> {
|
|||
shape.fill(0, 0, 0);
|
||||
Box::new(CubeVoxelShape::new(Box::new(shape)))
|
||||
}
|
||||
pub fn block_box_shape() -> Box<dyn VoxelShape> {
|
||||
let mut shape = BitSetDiscreteVoxelShape::new(1, 1, 1);
|
||||
shape.fill(0, 0, 0);
|
||||
Box::new(CubeVoxelShape::new(Box::new(shape)))
|
||||
}
|
||||
pub fn empty_shape() -> Box<dyn VoxelShape> {
|
||||
Box::new(ArrayVoxelShape::new(
|
||||
Box::new(BitSetDiscreteVoxelShape::new(0, 0, 0)),
|
||||
|
@ -33,6 +40,110 @@ impl Shapes {
|
|||
}
|
||||
movement
|
||||
}
|
||||
|
||||
pub fn join_unoptimized(
|
||||
a: Box<dyn VoxelShape>,
|
||||
b: Box<dyn VoxelShape>,
|
||||
op: impl FnOnce(bool, bool) -> bool,
|
||||
) -> Box<dyn VoxelShape> {
|
||||
if op(false, false) {
|
||||
panic!("Illegal operation");
|
||||
};
|
||||
// if (a == b) {
|
||||
// return if op(true, true) { a } else { empty_shape() };
|
||||
// }
|
||||
let op_true_false = op(true, false);
|
||||
let op_false_true = op(false, true);
|
||||
if a.is_empty() {
|
||||
return if op_false_true { b } else { empty_shape() };
|
||||
}
|
||||
if b.is_empty() {
|
||||
return if op_true_false { a } else { empty_shape() };
|
||||
}
|
||||
// IndexMerger var5 = createIndexMerger(1, a.getCoords(Direction.Axis.X), b.getCoords(Direction.Axis.X), var3, var4);
|
||||
// IndexMerger var6 = createIndexMerger(var5.size() - 1, a.getCoords(Direction.Axis.Y), b.getCoords(Direction.Axis.Y), var3, var4);
|
||||
// IndexMerger var7 = createIndexMerger((var5.size() - 1) * (var6.size() - 1), a.getCoords(Direction.Axis.Z), b.getCoords(Direction.Axis.Z), var3, var4);
|
||||
// BitSetDiscreteVoxelShape var8 = BitSetDiscreteVoxelShape.join(a.shape, b.shape, var5, var6, var7, op);
|
||||
// return (VoxelShape)(var5 instanceof DiscreteCubeMerger && var6 instanceof DiscreteCubeMerger && var7 instanceof DiscreteCubeMerger ? new CubeVoxelShape(var8) : new ArrayVoxelShape(var8, var5.getList(), var6.getList(), var7.getList()));
|
||||
let var5 = Self::create_index_merger(
|
||||
1,
|
||||
a.get_coords(Axis::X),
|
||||
b.get_coords(Axis::X),
|
||||
op_true_false,
|
||||
op_false_true,
|
||||
);
|
||||
let var6 = Self::create_index_merger(
|
||||
(var5.size() - 1).try_into().unwrap(),
|
||||
a.get_coords(Axis::Y),
|
||||
b.get_coords(Axis::Y),
|
||||
op_true_false,
|
||||
op_false_true,
|
||||
);
|
||||
let var7 = Self::create_index_merger(
|
||||
((var5.size() - 1) * (var6.size() - 1)).try_into().unwrap(),
|
||||
a.get_coords(Axis::Z),
|
||||
b.get_coords(Axis::Z),
|
||||
op_true_false,
|
||||
op_false_true,
|
||||
);
|
||||
let var8 = BitSetDiscreteVoxelShape::join(a.shape(), b.shape(), &var5, &var6, &var7, &op);
|
||||
if var5.is_discrete_cube_merger()
|
||||
&& var6.is_discrete_cube_merger()
|
||||
&& var7.is_discrete_cube_merger()
|
||||
{
|
||||
Box::new(CubeVoxelShape::new(Box::new(var8)))
|
||||
} else {
|
||||
Box::new(ArrayVoxelShape::new(
|
||||
Box::new(var8),
|
||||
var5.get_list(),
|
||||
var6.get_list(),
|
||||
var7.get_list(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_index_merger(
|
||||
var0: i32,
|
||||
var1: Vec<f64>,
|
||||
var2: Vec<f64>,
|
||||
var3: bool,
|
||||
var4: bool,
|
||||
) -> impl IndexMerger {
|
||||
// int var5 = var1.size() - 1;
|
||||
let var5 = var1.len() - 1;
|
||||
// int var6 = var2.size() - 1
|
||||
let var6 = var2.len() - 1;
|
||||
// if (var1 instanceof CubePointRange && var2 instanceof CubePointRange) {
|
||||
// downcast
|
||||
if (&var1 as &dyn Any).is::<CubePointRange>() && (&var2 as &dyn Any).is::<CubePointRange>()
|
||||
{
|
||||
// return new DiscreteCubeMerger(var0, var5, var6, var3, var4);
|
||||
let var7: i64 = lcm(var5 as u32, var6 as u32).try_into().unwrap();
|
||||
// if ((long)var0 * var7 <= 256L) {
|
||||
if (var0 as i64 * var7 <= 256) {
|
||||
return DiscreteCubeMerger::new(var5, var6);
|
||||
}
|
||||
}
|
||||
|
||||
// if (var1.getDouble(var5) < var2.getDouble(0) - 1.0E-7D) {
|
||||
// return new NonOverlappingMerger(var1, var2, false);
|
||||
// } else if (var2.getDouble(var6) < var1.getDouble(0) - 1.0E-7D) {
|
||||
// return new NonOverlappingMerger(var2, var1, true);
|
||||
// } else {
|
||||
// return (IndexMerger)(var5 == var6 && Objects.equals(var1, var2) ? new IdenticalMerger(var1) : new IndirectMerger(var1, var2, var3, var4));
|
||||
// }
|
||||
if var1.get_double(var5) < var2.get_double(0) - 1.0E-7 {
|
||||
return NonOverlappingMerger::new(var1, var2, false);
|
||||
} else if var2.get_double(var6) < var1.get_double(0) - 1.0E-7 {
|
||||
return NonOverlappingMerger::new(var2, var1, true);
|
||||
} else {
|
||||
if var5 == var6 && var1 == var2 {
|
||||
return IdenticalMerger::new(var1);
|
||||
} else {
|
||||
return IndirectMerger::new(var1, var2, var3, var4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VoxelShape: Send + Sync {
|
||||
|
@ -40,6 +151,10 @@ pub trait VoxelShape: Send + Sync {
|
|||
|
||||
fn get_coords(&self, axis: Axis) -> Vec<f64>;
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.shape().is_empty()
|
||||
}
|
||||
|
||||
// TODO: optimization: should this be changed to return ArrayVoxelShape?
|
||||
// i might change the implementation of empty_shape in the future so not 100% sure
|
||||
fn move_relative(&self, x: f64, y: f64, z: f64) -> Box<dyn VoxelShape> {
|
||||
|
@ -236,6 +351,40 @@ impl VoxelShape for CubeVoxelShape {
|
|||
}
|
||||
}
|
||||
|
||||
// public class CubePointRange extends AbstractDoubleList {
|
||||
// private final int parts;
|
||||
|
||||
// CubePointRange(int var1) {
|
||||
// super();
|
||||
// if (var1 <= 0) {
|
||||
// throw new IllegalArgumentException("Need at least 1 part");
|
||||
// } else {
|
||||
// this.parts = var1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// public double getDouble(int var1) {
|
||||
// return (double)var1 / (double)this.parts;
|
||||
// }
|
||||
|
||||
// public int size() {
|
||||
// return this.parts + 1;
|
||||
// }
|
||||
// }
|
||||
pub struct CubePointRange {
|
||||
/// Needs at least 1 part
|
||||
pub parts: NonZeroU32,
|
||||
}
|
||||
impl CubePointRange {
|
||||
pub fn get_double(&self, index: u32) -> f64 {
|
||||
index as f64 / self.parts.get() as f64
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u32 {
|
||||
self.parts.get() + 1
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Add table
Reference in a new issue