summaryrefslogtreecommitdiff
path: root/src/World
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-08-06 01:54:27 +0200
committerMel <einebeere@gmail.com>2023-08-06 01:54:27 +0200
commite6f5f9e03f673db796f1babb308609ca2576db2f (patch)
treefbc7d9451ec943a107f0ab54b3de7a7bd25e656d /src/World
parenta627fb7038c94de9be9709ea88dcd1dddc95c5a3 (diff)
downloadmeowcraft-e6f5f9e03f673db796f1babb308609ca2576db2f.tar.zst
meowcraft-e6f5f9e03f673db796f1babb308609ca2576db2f.zip
Improve MC::Position and remove some redundant code
Diffstat (limited to 'src/World')
-rw-r--r--src/World/ChunkIndex.hpp8
-rw-r--r--src/World/ChunkRegistry.cpp9
-rw-r--r--src/World/ChunkRegistry.hpp2
-rw-r--r--src/World/Generation/ChunkMeshing.cpp12
-rw-r--r--src/World/Generation/ChunkMeshing.hpp8
-rw-r--r--src/World/Position.hpp66
-rw-r--r--src/World/World.cpp7
7 files changed, 73 insertions, 39 deletions
diff --git a/src/World/ChunkIndex.hpp b/src/World/ChunkIndex.hpp
index ed3347b..70de99f 100644
--- a/src/World/ChunkIndex.hpp
+++ b/src/World/ChunkIndex.hpp
@@ -16,11 +16,17 @@ struct ChunkIndex {
return {(x + 0.5f) * Width, Height / 2.0f, (y + 0.5f) * Width};
}
- Position::BlockWorld world(Position::BlockLocal local) const {
+ Position::BlockWorld local_to_world_position(Position::BlockLocal local) const {
using namespace ChunkDimensions;
return {x * Width + local.x(), local.y(), y * Width + local.z()};
}
+ static ChunkIndex from_position(Position::BlockWorld pos) {
+ I32 chunk_x = std::round(pos.x() / ChunkDimensions::Width);
+ I32 chunk_y = std::round(pos.z() / ChunkDimensions::Width);
+ return {chunk_x, chunk_y};
+ }
+
I32 x, y;
};
diff --git a/src/World/ChunkRegistry.cpp b/src/World/ChunkRegistry.cpp
index 41fd1b0..97896fe 100644
--- a/src/World/ChunkRegistry.cpp
+++ b/src/World/ChunkRegistry.cpp
@@ -15,14 +15,11 @@ ChunkRegistry::Data& ChunkRegistry::get(ChunkIndex index) {
}
ChunkRegistry::Data& ChunkRegistry::find(Position::BlockWorld pos) {
- return get({
- static_cast<I32>(pos.x() / Chunk::Width),
- static_cast<I32>(pos.z() / Chunk::Width)
- });
+ return get(ChunkIndex::from_position(pos));
}
-ChunkRegistry::Data& ChunkRegistry::find(ChunkIndex chunk, Position::BlockLocal pos) {
- return find(chunk.world(pos));
+ChunkRegistry::Data& ChunkRegistry::find(Position::World pos) {
+ return find(pos.round_to_block());
}
} \ No newline at end of file
diff --git a/src/World/ChunkRegistry.hpp b/src/World/ChunkRegistry.hpp
index 2c515c5..ea887e4 100644
--- a/src/World/ChunkRegistry.hpp
+++ b/src/World/ChunkRegistry.hpp
@@ -41,7 +41,7 @@ public:
Data& get(ChunkIndex index);
Data& find(Position::BlockWorld pos);
- Data& find(ChunkIndex chunk, Position::BlockLocal pos);
+ Data& find(Position::World pos);
private:
std::unordered_map<ChunkIndex, Data> m_chunks;
};
diff --git a/src/World/Generation/ChunkMeshing.cpp b/src/World/Generation/ChunkMeshing.cpp
index 3855de4..feecc64 100644
--- a/src/World/Generation/ChunkMeshing.cpp
+++ b/src/World/Generation/ChunkMeshing.cpp
@@ -11,15 +11,15 @@ ChunkMesh mesh_chunk(Chunk& chunk, const SurroundingContext& context) {
};
}
-SurroundingContext::Block& SurroundingContext::at(Position::BlockOffset p) {
+SurroundingContext::Block& SurroundingContext::at(Position::BlockLocalOffset p) {
return m_blocks[pos(p)];
}
-const SurroundingContext::Block& SurroundingContext::at(Position::BlockOffset p) const {
+const SurroundingContext::Block& SurroundingContext::at(Position::BlockLocalOffset p) const {
return m_blocks[pos(p)];
}
-USize SurroundingContext::pos(Position::BlockOffset p) {
+USize SurroundingContext::pos(Position::BlockLocalOffset p) {
// First we calculate the index as if there were no gaps.
USize pos = 0;
pos += p.x() + 1;
@@ -39,7 +39,7 @@ SurroundingContext create_meshing_context(const Chunk& chunk, ChunkNeighbors& ne
for (I16 x = -1; x <= (I16)Chunk::Width; x++) {
for (I16 z = -1; z <= (I16)Chunk::Width; z++) {
for (I16 y = 0; y < (I16)Chunk::Height; y++) {
- Position::BlockOffset pos{x, y, z};
+ Position::BlockLocalOffset pos{x, y, z};
if (pos.fits_within_chunk()) continue;
auto [does_exist, block] = get_block_wrapping(chunk, neighbors, {pos.x(), pos.y(), pos.z()});
context.at(pos) = {does_exist, block};
@@ -205,7 +205,7 @@ Face<AO> DefaultMeshDecisions::face_ao_values(Chunk& chunk, const SurroundingCon
auto b = offsets[++offset_index]; // corner
auto c = offsets[++offset_index % 8];
- auto p = [=](auto o) -> Position::BlockOffset { return {(I16)((I16)x + o.x()), (I16)((I16)y + o.y()), (I16)((I16)z + o.z())}; };
+ auto p = [=](auto o) -> Position::BlockLocalOffset { return {(I16)x + o.x(), (I16)y + o.y(), (I16)z + o.z()}; };
auto block_a = get_block_from_chunk_or_context(chunk, context, p(a));
auto block_b = get_block_from_chunk_or_context(chunk, context, p(b));
auto block_c = get_block_from_chunk_or_context(chunk, context, p(c));
@@ -236,7 +236,7 @@ Vector<3, I32> DefaultMeshDecisions::get_face_normal(BlockSide side) {
}
SurroundingContext::Block DefaultMeshDecisions::get_block_from_chunk_or_context(
- const Chunk& chunk, const SurroundingContext& context, Position::BlockOffset pos
+ const Chunk& chunk, const SurroundingContext& context, Position::BlockLocalOffset pos
) {
if (pos.fits_within_chunk()) return {true, chunk.at(pos)};
return context.at(pos);
diff --git a/src/World/Generation/ChunkMeshing.hpp b/src/World/Generation/ChunkMeshing.hpp
index 5401580..c745a3b 100644
--- a/src/World/Generation/ChunkMeshing.hpp
+++ b/src/World/Generation/ChunkMeshing.hpp
@@ -19,10 +19,10 @@ class SurroundingContext {
public:
struct Block { Bool does_exist; Chunk::BlockData block; };
- Block& at(Position::BlockOffset p);
- const Block& at(Position::BlockOffset p) const;
+ Block& at(Position::BlockLocalOffset p);
+ const Block& at(Position::BlockLocalOffset p) const;
private:
- static USize pos(Position::BlockOffset p);
+ static USize pos(Position::BlockLocalOffset p);
static constexpr USize surrounding_block_count = Chunk::Width * 4 + 4;
Block m_blocks[surrounding_block_count * Chunk::Height] = {};
@@ -83,7 +83,7 @@ public:
static Face<AO> face_ao_values(Chunk& chunk, const SurroundingContext& context, U32 x, U32 y, U32 z, BlockSide side);
static Vector<3, I32> get_face_normal(BlockSide side);
- static SurroundingContext::Block get_block_from_chunk_or_context(const Chunk& chunk, const SurroundingContext& context, Position::BlockOffset pos);
+ static SurroundingContext::Block get_block_from_chunk_or_context(const Chunk& chunk, const SurroundingContext& context, Position::BlockLocalOffset pos);
static SurroundingContext::Block get_opposing_neighbor(const Chunk& chunk, const SurroundingContext& context, U32 x, U32 y, U32 z, BlockSide side);
static Bool is_face_visible(Chunk& chunk, const SurroundingContext& context, U32 x, U32 y, U32 z, BlockSide side);
diff --git a/src/World/Position.hpp b/src/World/Position.hpp
index 07de6f3..bc874c0 100644
--- a/src/World/Position.hpp
+++ b/src/World/Position.hpp
@@ -2,38 +2,36 @@
#include "array"
#include "ChunkDimensions.hpp"
+#include "../Math/Mod.hpp"
+#include "../Math/Random.hpp"
#include "../Math/Vector.hpp"
namespace MC::Position {
-// Position within entire world.
-using World = Vector<3>;
-
-// Offset between two world positions.
-using WorldOffset = Vector<3>;
+#define MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(name, t) \
+ name() = default; \
+ template<typename ...Args, std::enable_if_t<sizeof...(Args) == 3, Int> = 0> \
+ name(Args... args) : Vector{ static_cast<t>(args)... } {} \
+ name(Vector v) : Vector(v) {}
// Offset between block positions within single chunk.
-class BlockOffset : public Vector<3, I16> {
+class BlockLocalOffset : public Vector<3, I16> {
public:
- BlockOffset(I16 x, I16 y, I16 z) : Vector(x, y, z) {}
+ MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockLocalOffset, I16)
+
Bool fits_within_chunk() const {
using namespace MC::World::ChunkDimensions;
return x() >= 0 && x() < Width && y() >= 0 && y() < Height && z() >= 0 && z() < Width;
}
};
-// Position of a block within entire world.
-class BlockWorld : public Vector<3, I64> {
-public:
- BlockWorld(I64 x, I64 y, I64 z) : Vector(x, y, z) {}
-};
-
// Position of a block within single chunk.
class BlockLocal : public Vector<3, U8> {
public:
- BlockLocal(U8 x, U8 y, U8 z) : Vector(x, y, z) {}
- BlockLocal(BlockOffset offset) : BlockLocal(offset.x(), offset.y(), offset.z()) {}
- BlockOffset offset(BlockOffset by) {
+ MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockLocal, U8)
+ BlockLocal(BlockLocalOffset offset) : BlockLocal(offset.x(), offset.y(), offset.z()) {}
+
+ BlockLocalOffset offset(BlockLocalOffset by) {
return {
static_cast<I8>(x() + by.x()),
static_cast<I8>(y() + by.y()),
@@ -42,8 +40,42 @@ public:
}
};
-const std::array<BlockOffset, 6> axis_directions = {{
+// Offset between block positions within entire world.
+class BlockWorldOffset : public Vector<3, I64> {
+public:
+ MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockWorldOffset, I64)
+};
+
+// Position of a block within entire world.
+class BlockWorld : public Vector<3, I64> {
+public:
+ MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockWorld, I64)
+
+ BlockLocal to_local() const {
+ using namespace MC::World::ChunkDimensions;
+ return {Math::mod(x(), Width), y(), Math::mod(z(), Width)};
+ }
+};
+
+const std::array<BlockLocalOffset, 6> axis_directions = {{
{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1},
}};
+// Offset between two world positions.
+class WorldOffset : public Vector<3> {
+public:
+ MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(WorldOffset, Real)
+};
+
+// Position within entire world.
+class World : public Vector<3> {
+public:
+ MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(World, Real)
+
+ BlockWorld round_to_block() const {
+ auto rounded = map([](auto x) { return std::round(x); });
+ return {rounded.x(), rounded.y(), rounded.z()};
+ }
+};
+
}
diff --git a/src/World/World.cpp b/src/World/World.cpp
index 3ff0cf4..089c498 100644
--- a/src/World/World.cpp
+++ b/src/World/World.cpp
@@ -42,8 +42,7 @@ std::vector<ChunkRegistry::Data*> World::get_visible_chunks(Position::World posi
}
std::vector<ChunkIndex> World::get_visible_chunk_indices(const Position::World position) const {
- I32 center_x = std::round(position.x() / Chunk::Width);
- I32 center_y = std::round(position.z() / Chunk::Width);
+ ChunkIndex center = ChunkIndex::from_position(position.round_to_block());
std::vector<ChunkIndex> indices{};
indices.reserve(m_view_distance_radius * m_view_distance_radius * 4);
@@ -52,8 +51,8 @@ std::vector<ChunkIndex> World::get_visible_chunk_indices(const Position::World p
I32 height = std::round(std::sqrt(radius * radius - x * x) + 0.5);
for (I32 y = -height; y <= height; y++) {
// Needed so that this function and is_chunk_in_radius forcibly agree.
- if (!is_chunk_in_radius(position, {x + center_x, y + center_y})) continue;
- indices.emplace_back(x + center_x, y + center_y);
+ if (!is_chunk_in_radius(position, {x + center.x, y + center.y})) continue;
+ indices.emplace_back(x + center.x, y + center.y);
}
}