From e18d9347683d64e6548d0b5917abba551a344686 Mon Sep 17 00:00:00 2001 From: caelunshun Date: Fri, 13 Sep 2019 23:49:29 -0600 Subject: [PATCH] Support bounding boxes for non-cubic blocks --- server/src/physics/block_bboxes.rs | 51 ++++++++++++++++++++++++++++++ server/src/physics/math.rs | 31 ++++++++++-------- server/src/physics/mod.rs | 1 + 3 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 server/src/physics/block_bboxes.rs diff --git a/server/src/physics/block_bboxes.rs b/server/src/physics/block_bboxes.rs new file mode 100644 index 000000000..12cee06ee --- /dev/null +++ b/server/src/physics/block_bboxes.rs @@ -0,0 +1,51 @@ +//! Bounding boxes for every non-cubic block. + +use crate::physics::component::bbox; +use feather_blocks::Block; +use ncollide3d::bounding_volume::AABB; + +/// Returns the bounding box for the given block. +/// +/// Non-solid blocks have no bounding box, +/// and the bounding box for a non-solid block +/// is undefined. +pub fn bbox_for_block(block: &Block) -> AABB { + match block { + Block::WhiteBed(_) + | Block::OrangeBed(_) + | Block::MagentaBed(_) + | Block::LightBlueBed(_) + | Block::YellowBed(_) + | Block::LimeBed(_) + | Block::PinkBed(_) + | Block::GrayBed(_) + | Block::LightGrayBed(_) + | Block::CyanBed(_) + | Block::PurpleBed(_) + | Block::BlueBed(_) + | Block::BrownBed(_) + | Block::GreenBed(_) + | Block::RedBed(_) + | Block::BlackBed(_) + | Block::PrismarineSlab(_) + | Block::PrismarineBrickSlab(_) + | Block::DarkPrismarineSlab(_) + | Block::OakSlab(_) + | Block::SpruceSlab(_) + | Block::BirchSlab(_) + | Block::JungleSlab(_) + | Block::AcaciaSlab(_) + | Block::DarkOakSlab(_) + | Block::StoneSlab(_) + | Block::SandstoneSlab(_) + | Block::PetrifiedOakSlab(_) + | Block::CobblestoneSlab(_) + | Block::BrickSlab(_) + | Block::StoneBrickSlab(_) + | Block::NetherBrickSlab(_) + | Block::QuartzSlab(_) + | Block::RedSandstoneSlab(_) + | Block::PurpurSlab(_) => bbox(1.0, 0.5), + _ => bbox(1.0, 1.0), + } +} diff --git a/server/src/physics/math.rs b/server/src/physics/math.rs index 8751d061d..9b53b7077 100644 --- a/server/src/physics/math.rs +++ b/server/src/physics/math.rs @@ -2,7 +2,9 @@ //! the physics system. use crate::entity::{ChunkEntities, PositionComponent}; +use crate::physics::block_bboxes::bbox_for_block; use crate::physics::BoundingBoxComponent; +use feather_blocks::Block; use feather_core::world::{BlockPosition, ChunkMap, Position}; use feather_core::{BlockExt, ChunkPosition}; use glm::{vec3, DVec3, Vec3}; @@ -157,12 +159,14 @@ pub fn block_impacted_by_ray( // Calculate world-space position of // impact using `ncollide`. let ray = Ray::new(Point3::from(origin), direction); - let shape = block_shape(); + let shape = block_shape(&block); let isometry = block_isometry(current_pos); - let impact = shape - .toi_and_normal_with_ray(&isometry, &ray, true) - .unwrap(); // Unwrap is safe because we know the ray intersects the block + let impact = match shape.toi_and_normal_with_ray(&isometry, &ray, true) { + Some(toi) => toi, + None => continue, + }; + let pos = Position::from(origin + impact.toi * direction); return Some(RayImpact { @@ -418,7 +422,7 @@ pub fn adjacent_to_bbox( let sign = f64::from(sign); let size = bbox.size() / 2.0; - let mut blocks: SmallVec<[BlockPosition; 4]> = smallvec![]; + let mut blocks: SmallVec<[(BlockPosition, Block); 4]> = smallvec![]; let other_axis1 = match axis { 0 => 1, @@ -473,7 +477,7 @@ pub fn adjacent_to_bbox( Some(block) => { if block.is_solid() { checked.insert(block_pos).unwrap(); - blocks.push(block_pos); + blocks.push((block_pos, block)); } } None => continue, @@ -481,19 +485,20 @@ pub fn adjacent_to_bbox( } let mut shapes = Vec::with_capacity(4); - let block_shape = block_shape(); - for block in &blocks { - let isometry = block_isometry(*block); - shapes.push((isometry, ShapeHandle::new(block_shape.clone()))); + for (block_pos, block) in &blocks { + let isometry = block_isometry(*block_pos); + let shape = block_shape(&block); + shapes.push((isometry, ShapeHandle::new(shape))); } Compound::new(shapes) } -/// Returns an `ncollide` `Cuboid` corresponding to a block. -pub fn block_shape() -> Cuboid { - Cuboid::new(vec3(0.5, 0.5, 0.5)) +/// Returns an `ncollide` `Cuboid` corresponding to the given block. +pub fn block_shape(block: &Block) -> Cuboid { + let bbox = bbox_for_block(block); + Cuboid::new(bbox.half_extents()) } /// Returns an `Isometry` representing a block's translation. diff --git a/server/src/physics/mod.rs b/server/src/physics/mod.rs index 077f183fe..cd02ace5c 100644 --- a/server/src/physics/mod.rs +++ b/server/src/physics/mod.rs @@ -1,5 +1,6 @@ //! Module for calculating physics interactions. +mod block_bboxes; mod component; mod entity; mod math;