diff options
| author | Mel <einebeere@gmail.com> | 2024-02-02 03:03:36 +0100 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2024-02-02 03:03:36 +0100 |
| commit | 250e37c742f3ad46f093f4534098cdf8f68a29a9 (patch) | |
| tree | 29bb86a24e5a987959a455cae13818cf0def8646 /src/World | |
| parent | 7b061aee2b4c15d242bb9f18101d6b9ea776c5cd (diff) | |
| download | meowcraft-250e37c742f3ad46f093f4534098cdf8f68a29a9.tar.zst meowcraft-250e37c742f3ad46f093f4534098cdf8f68a29a9.zip | |
Breaking blocks
Diffstat (limited to 'src/World')
| -rw-r--r-- | src/World/ChunkRegistry.hpp | 4 | ||||
| -rw-r--r-- | src/World/VoxelTraversal.hpp | 60 | ||||
| -rw-r--r-- | src/World/World.cpp | 11 | ||||
| -rw-r--r-- | src/World/World.hpp | 12 |
4 files changed, 86 insertions, 1 deletions
diff --git a/src/World/ChunkRegistry.hpp b/src/World/ChunkRegistry.hpp index ea887e4..2b87a3a 100644 --- a/src/World/ChunkRegistry.hpp +++ b/src/World/ChunkRegistry.hpp @@ -34,7 +34,9 @@ public: } void damage() { - if (status == Status::Done) chunk.value().damage(); + // if (status == Status::Done) chunk.value().damage(); + // TODO: Properly damage the chunk, notifying the nearby chunks, too. + status = Status::NeedsReification; } }; diff --git a/src/World/VoxelTraversal.hpp b/src/World/VoxelTraversal.hpp new file mode 100644 index 0000000..1638901 --- /dev/null +++ b/src/World/VoxelTraversal.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "../Common/Casts.hpp" +#include "../Math/Ray.hpp" +#include "Position.hpp" + +namespace MC::World::VoxelTraversal { + +// Amanatides, John, and Andrew Woo. 1987. +// "A Fast Voxel Traversal Algorithm for Ray Tracing." +// https://doi.org/10.2312/EGTP.19871000. +template <typename P> +Position::BlockWorld traverse(Ray ray, Real max_distance, P&& predicate) { + // Find the voxel grid cell containing the origin of the ray. + Position::BlockWorld block_pos = Position::World(ray.origin).round_to_block(); + Position::BlockWorldOffset const step = { + Math::sign(ray.direction.x()), + Math::sign(ray.direction.y()), + Math::sign(ray.direction.z()), + }; + + Position::WorldOffset t_max = { + (TO(Real, block_pos.x()) + TO(Real, step.x() > 0) - ray.origin.x()) / ray.direction.x(), + (TO(Real, block_pos.y()) + TO(Real, step.y() > 0) - ray.origin.y()) / ray.direction.y(), + (TO(Real, block_pos.z()) + TO(Real, step.z() > 0) - ray.origin.z()) / ray.direction.z() + }; + + Position::WorldOffset const t_delta = { + TO(Real, step.x()) / ray.direction.x(), + TO(Real, step.y()) / ray.direction.y(), + TO(Real, step.z()) / ray.direction.z() + }; + + while (!predicate(block_pos)) { + // TODO: Calculate distance exactly. + if (ray.origin.distance(Vec3(block_pos)) > max_distance) return {}; + + if (t_max.x() < t_max.y()) { + if (t_max.x() < t_max.z()) { + block_pos.x() += step.x(); + t_max.x() += t_delta.x(); + } else { + block_pos.z() += step.z(); + t_max.z() += t_delta.z(); + } + } else { + if (t_max.y() < t_max.z()) { + block_pos.y() += step.y(); + t_max.y() += t_delta.y(); + } else { + block_pos.z() += step.z(); + t_max.z() += t_delta.z(); + } + } + } + + return block_pos; +} + +} diff --git a/src/World/World.cpp b/src/World/World.cpp index ce15ae8..cc5d91f 100644 --- a/src/World/World.cpp +++ b/src/World/World.cpp @@ -47,6 +47,17 @@ Chunk::BlockData World::block_at(Position::BlockWorld pos) { return {}; } +void World::break_block(Position::BlockWorld pos) { + auto& chunk_data = m_registry.find(pos); + if (!chunk_data.chunk.has_value()) return; + + auto& block_data = chunk_data.chunk->at(pos.to_local()); + if (!block_data.type.is_solid()) return; + + block_data.type = {}; + chunk_data.damage(); +} + std::vector<ChunkIndex> World::get_visible_chunk_indices(const Position::World position) const { ChunkIndex center = ChunkIndex::from_position(position.round_to_block()); diff --git a/src/World/World.hpp b/src/World/World.hpp index 3dbd720..af49378 100644 --- a/src/World/World.hpp +++ b/src/World/World.hpp @@ -4,8 +4,10 @@ #include "ChunkIndex.hpp" #include "ChunkRegistry.hpp" #include "../Compute/Queue.hpp" +#include "../Math/Ray.hpp" #include "Generation/ChunkMeshing.hpp" #include "Generation/Lighting.hpp" +#include "VoxelTraversal.hpp" namespace MC::World { @@ -14,6 +16,16 @@ public: std::vector<ChunkRegistry::Data*> get_visible_chunks(Position::World position); Chunk::BlockData block_at(Position::BlockWorld pos); + void break_block(Position::BlockWorld pos); + + template <typename F> + Position::BlockWorld traverse(Ray ray, Real max_distance, F&& predicate) { + return VoxelTraversal::traverse( + ray, + max_distance, + [this, &predicate](Position::BlockWorld pos) { return predicate(block_at(pos)); } + ); + } Real get_average_chunk_time() const; |
