From: Daniel Karbach Date: Tue, 3 Nov 2015 15:54:08 +0000 (+0100) Subject: unified location handling X-Git-Url: http://git.localhorst.tv/?a=commitdiff_plain;h=4727825186798902f68df5b99a6a32f0ef618454;p=blank.git unified location handling --- diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 8386c59..a2f5938 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -84,7 +84,7 @@ void AIController::Update(Entity &e, float dt) { // our box is oriented for -Z velocity obstacle_transform = glm::mat4(find_rotation(glm::vec3(0.0f, 0.0f, -1.0f), e.Heading())); // and positioned relative to the entity's chunk - obstacle_transform[3] = glm::vec4(e.GetState().block_pos, 1.0f); + obstacle_transform[3] = glm::vec4(e.GetState().pos.block, 1.0f); } if (wandering) { @@ -297,7 +297,7 @@ glm::vec3 AIController::GetObstacleAvoidanceForce(const Entity &e, const EntityS // point on the "velocity ray" closest to obstacle float to_go = dot(difference, e.Heading()); // point is our future position if we keep going our way - glm::vec3 point(e.GetState().block_pos + e.Heading() * to_go); + glm::vec3 point(e.GetState().pos.block + e.Heading() * to_go); // now steer away in the direction of (point - block) // with a magniture proportional to speed/distance return normalize(point - nearest->BlockCoords()) * (e.Speed() / std::sqrt(distance)); @@ -429,7 +429,7 @@ glm::vec3 AIController::GetEvadeForce(const Entity &, const EntityState &state) glm::vec3 cur_diff(state.Diff(GetEvadeTarget().GetState())); float time_estimate = length(cur_diff) / evade_speed; EntityState pred_state(GetEvadeTarget().GetState()); - pred_state.block_pos += pred_state.velocity * time_estimate; + pred_state.pos.block += pred_state.velocity * time_estimate; return Flee(state, pred_state, evade_speed, 2.0f); } @@ -475,7 +475,7 @@ glm::vec3 AIController::GetPursuitForce(const Entity &, const EntityState &state glm::vec3 cur_diff(state.Diff(GetPursuitTarget().GetState())); float time_estimate = length(cur_diff) / pursuit_speed; EntityState pred_state(GetPursuitTarget().GetState()); - pred_state.block_pos += pred_state.velocity * time_estimate; + pred_state.pos.block += pred_state.velocity * time_estimate; return Seek(state, pred_state, pursuit_speed, 2.0f); } diff --git a/src/client/net.cpp b/src/client/net.cpp index 1c13f9e..d7a2661 100644 --- a/src/client/net.cpp +++ b/src/client/net.cpp @@ -62,7 +62,7 @@ int ChunkReceiver::ToLoad() const noexcept { void ChunkReceiver::LoadOne() { if (!store.HasMissing()) return; - Chunk::Pos pos = store.NextMissing(); + ExactLocation::Coarse pos = store.NextMissing(); Chunk *chunk = store.Allocate(pos); if (!chunk) { // chunk store corrupted? @@ -392,8 +392,7 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr replay.SetState(corrected_state); if (entry != end) { - entry->state.chunk_pos = replay.GetState().chunk_pos; - entry->state.block_pos = replay.GetState().block_pos; + entry->state.pos = replay.GetState().pos; ++entry; } @@ -401,8 +400,7 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr while (entry != end) { SetMovement(entry->movement); GetWorld().Update(replay, entry->delta_t); - entry->state.chunk_pos = replay.GetState().chunk_pos; - entry->state.block_pos = replay.GetState().block_pos; + entry->state.pos = replay.GetState().pos; ++entry; } @@ -421,13 +419,12 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr constexpr float max_disp = 0.0001f; // (1/100)^2 if (disp_squared > warp_thresh) { - player_state.chunk_pos = replay.GetState().chunk_pos; - player_state.block_pos = replay.GetState().block_pos; + player_state.pos = replay.GetState().pos; } else if (disp_squared < max_disp) { - player_state.block_pos += displacement; + player_state.pos.block += displacement; } else { displacement *= 0.01f / sqrt(disp_squared); - player_state.block_pos += displacement; + player_state.pos.block += displacement; } GetPlayer().GetEntity().SetState(player_state); SetMovement(restore_movement); diff --git a/src/geometry/Location.hpp b/src/geometry/Location.hpp new file mode 100644 index 0000000..7dbff69 --- /dev/null +++ b/src/geometry/Location.hpp @@ -0,0 +1,106 @@ +#ifndef BLANK_GEOMETRY_LOCATION_HPP_ +#define BLANK_GEOMETRY_LOCATION_HPP_ + +#include + + +namespace blank { + +template +struct Location { + + using Coarse = glm::ivec3; + using CoarseScalar = int; + using Fine = glm::tvec3; + using FineScalar = T; + using Self = Location; + + + Coarse chunk; + Fine block; + + + /// scale of coarse vs fine coordinates + static constexpr CoarseScalar scale = 16; + /// scale with same type as fine + static constexpr FineScalar fscale = scale; + /// scale in three dimensions + static Coarse Extent() noexcept { return Coarse(scale); } + /// extent with same type as fine + static Fine FExtent() noexcept { return Fine(fscale); } + + + Location() noexcept : chunk(CoarseScalar(0)), block(FineScalar(0)) { } + Location(const Coarse &c, const Fine &b) noexcept : chunk(c), block(b) { } + + /// from absolute position + /// not sanitized + explicit Location(const Fine &b) noexcept : chunk(CoarseScalar(0)), block(b) { } + + /// make sure fine coordinates are within [0,scale) + /// use this if block isn't too far out of range + Self &Correct() noexcept; + /// use this if block is way out of range + Self &Sanitize() noexcept; + + /// resolve absolute position + Fine Absolute() const noexcept { + return Fine(chunk * Extent()) + block; + } + /// get location relative to given coarse coordinates + Self Relative(const Coarse &reference) const noexcept { + return Self(chunk - reference, block); + } + /// get difference between this and given location + /// (= this - given, points from given to this) + /// returned location is not sanitized + Self Difference(const Location &other) const noexcept { + return Self(chunk - other.chunk, block - other.block); + } + +}; + +template +inline Location &Location::Correct() noexcept { + while (block.x >= fscale) { + block.x -= fscale; + ++chunk.x; + } + while (block.x < 0) { + block.x += fscale; + --chunk.x; + } + while (block.y >= fscale) { + block.y -= fscale; + ++chunk.y; + } + while (block.y < 0) { + block.y += fscale; + --chunk.y; + } + while (block.z >= fscale) { + block.z -= fscale; + ++chunk.z; + } + while (block.z < 0) { + block.z += fscale; + --chunk.z; + } + return *this; +} + +template +inline Location &Location::Sanitize() noexcept { + Coarse diff = Coarse(block) / Extent(); + chunk += diff; + block -= diff * Extent(); + // may leave negative coordinates in block + return Correct(); +} + +using ExactLocation = Location; +using RoughLocation = Location; + +} + +#endif diff --git a/src/io/WorldSave.cpp b/src/io/WorldSave.cpp index 8653278..8422623 100644 --- a/src/io/WorldSave.cpp +++ b/src/io/WorldSave.cpp @@ -125,9 +125,9 @@ void WorldSave::Read(Player &player) const { in.ReadIdentifier(name); in.Skip(Token::EQUALS); if (name == "chunk") { - in.ReadVec(state.chunk_pos); + in.ReadVec(state.pos.chunk); } else if (name == "position") { - in.ReadVec(state.block_pos); + in.ReadVec(state.pos.block); } else if (name == "orientation") { in.ReadQuat(state.orient); } else if (name == "pitch") { @@ -152,8 +152,8 @@ void WorldSave::Write(const Player &player) const { } const EntityState &state = player.GetEntity().GetState(); ofstream out(PlayerPath(player)); - out << "chunk = " << state.chunk_pos << ';' << endl; - out << "position = " << state.block_pos << ';' << endl; + out << "chunk = " << state.pos.chunk << ';' << endl; + out << "position = " << state.pos.block << ';' << endl; out << "orientation = " << state.orient << ';' << endl; out << "pitch = " << state.pitch << ';' << endl; out << "yaw = " << state.yaw << ';' << endl; @@ -167,7 +167,7 @@ string WorldSave::PlayerPath(const Player &player) const { } -bool WorldSave::Exists(const Chunk::Pos &pos) const noexcept { +bool WorldSave::Exists(const ExactLocation::Coarse &pos) const noexcept { return is_file(ChunkPath(pos)); } @@ -217,7 +217,7 @@ void WorldSave::Write(Chunk &chunk) const { } -const char *WorldSave::ChunkPath(const Chunk::Pos &pos) const { +const char *WorldSave::ChunkPath(const ExactLocation::Coarse &pos) const { snprintf(chunk_buf.get(), chunk_bufsiz, chunk_path.c_str(), pos.x, pos.y, pos.z); return chunk_buf.get(); } diff --git a/src/io/WorldSave.hpp b/src/io/WorldSave.hpp index d12de95..12a56b0 100644 --- a/src/io/WorldSave.hpp +++ b/src/io/WorldSave.hpp @@ -33,10 +33,10 @@ public: std::string PlayerPath(const Player &) const; // single chunk - bool Exists(const Chunk::Pos &) const noexcept; + bool Exists(const ExactLocation::Coarse &) const noexcept; void Read(Chunk &) const; void Write(Chunk &) const; - const char *ChunkPath(const Chunk::Pos &) const; + const char *ChunkPath(const ExactLocation::Coarse &) const; private: std::string root_path; diff --git a/src/net/net.cpp b/src/net/net.cpp index 9130e8e..5d06234 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -446,8 +446,8 @@ void Packet::Payload::Read(glm::quat &val, size_t off) const noexcept { } void Packet::Payload::Write(const EntityState &state, size_t off) noexcept { - Write(state.chunk_pos, off); - WritePackU(state.block_pos * (1.0f / 16.0f), off + 12); + Write(state.pos.chunk, off); + WritePackU(state.pos.block * (1.0f / ExactLocation::fscale), off + 12); Write(state.velocity, off + 18); Write(state.orient, off + 30); WritePackN(state.pitch * PI_0p5_inv, off + 38); @@ -455,20 +455,20 @@ void Packet::Payload::Write(const EntityState &state, size_t off) noexcept { } void Packet::Payload::Read(EntityState &state, size_t off) const noexcept { - Read(state.chunk_pos, off); - ReadPackU(state.block_pos, off + 12); + Read(state.pos.chunk, off); + ReadPackU(state.pos.block, off + 12); Read(state.velocity, off + 18); Read(state.orient, off + 30); ReadPackN(state.pitch, off + 38); ReadPackN(state.yaw, off + 40); - state.block_pos *= 16.0f; + state.pos.block *= ExactLocation::fscale; state.pitch *= PI_0p5; state.yaw *= PI; } void Packet::Payload::Write(const EntityState &state, const glm::ivec3 &base, size_t off) noexcept { - WritePackB(state.chunk_pos - base, off); - WritePackU(state.block_pos * (1.0f / 16.0f), off + 3); + WritePackB(state.pos.chunk - base, off); + WritePackU(state.pos.block * (1.0f / ExactLocation::fscale), off + 3); Write(state.velocity, off + 9); Write(state.orient, off + 21); WritePackN(state.pitch * PI_0p5_inv, off + 29); @@ -476,14 +476,14 @@ void Packet::Payload::Write(const EntityState &state, const glm::ivec3 &base, si } void Packet::Payload::Read(EntityState &state, const glm::ivec3 &base, size_t off) const noexcept { - ReadPackB(state.chunk_pos, off); - ReadPackU(state.block_pos, off + 3); + ReadPackB(state.pos.chunk, off); + ReadPackU(state.pos.block, off + 3); Read(state.velocity, off + 9); Read(state.orient, off + 21); ReadPackN(state.pitch, off + 29); ReadPackN(state.yaw, off + 31); - state.chunk_pos += base; - state.block_pos *= 16.0f; + state.pos.chunk += base; + state.pos.block *= ExactLocation::fscale; state.pitch *= PI_0p5; state.yaw *= PI; } diff --git a/src/server/net.cpp b/src/server/net.cpp index 8eba857..9eac33e 100644 --- a/src/server/net.cpp +++ b/src/server/net.cpp @@ -385,9 +385,9 @@ struct QueueCompare { void ClientConnection::CheckChunkQueue() { if (PlayerChunks().Base() != old_base) { - Chunk::Pos begin = PlayerChunks().CoordsBegin(); - Chunk::Pos end = PlayerChunks().CoordsEnd(); - for (Chunk::Pos pos = begin; pos.z < end.z; ++pos.z) { + ExactLocation::Coarse begin = PlayerChunks().CoordsBegin(); + ExactLocation::Coarse end = PlayerChunks().CoordsEnd(); + for (ExactLocation::Coarse pos = begin; pos.z < end.z; ++pos.z) { for (pos.y = begin.y; pos.y < end.y; ++pos.y) { for (pos.x = begin.x; pos.x < end.x; ++pos.x) { if (manhattan_radius(pos - old_base) > PlayerChunks().Extent()) { @@ -412,7 +412,7 @@ void ClientConnection::CheckChunkQueue() { int count = 0; constexpr int max = 64; while (count < max && !chunk_queue.empty()) { - Chunk::Pos pos = chunk_queue.front(); + ExactLocation::Coarse pos = chunk_queue.front(); chunk_queue.pop_front(); if (PlayerChunks().InRange(pos)) { Chunk *chunk = PlayerChunks().Get(pos); @@ -434,9 +434,9 @@ void ClientConnection::AttachPlayer(Player &player) { PlayerEntity().Ref(); old_base = PlayerChunks().Base(); - Chunk::Pos begin = PlayerChunks().CoordsBegin(); - Chunk::Pos end = PlayerChunks().CoordsEnd(); - for (Chunk::Pos pos = begin; pos.z < end.z; ++pos.z) { + ExactLocation::Coarse begin = PlayerChunks().CoordsBegin(); + ExactLocation::Coarse end = PlayerChunks().CoordsEnd(); + for (ExactLocation::Coarse pos = begin; pos.z < end.z; ++pos.z) { for (pos.y = begin.y; pos.y < end.y; ++pos.y) { for (pos.x = begin.x; pos.x < end.x; ++pos.x) { chunk_queue.push_back(pos); diff --git a/src/shared/cli.cpp b/src/shared/cli.cpp index aa6629f..6942f78 100644 --- a/src/shared/cli.cpp +++ b/src/shared/cli.cpp @@ -72,12 +72,8 @@ CLI::Command::~Command() { void TeleportCommand::Execute(CLI &cli, Player &player, TokenStreamReader &args) { glm::vec3 pos(args.GetFloat(), args.GetFloat(), args.GetFloat()); - glm::ivec3 chunk(pos); - chunk /= Chunk::Extent(); - pos -= chunk; EntityState state = player.GetEntity().GetState(); - state.chunk_pos = chunk; - state.block_pos = pos; + state.pos = ExactLocation(pos).Sanitize(); player.GetEntity().SetState(state); } diff --git a/src/world/Block.hpp b/src/world/Block.hpp index 4b4ea21..ea3de59 100644 --- a/src/world/Block.hpp +++ b/src/world/Block.hpp @@ -11,7 +11,6 @@ namespace blank { struct Block { using Type = unsigned short; - using Pos = glm::vec3; enum Face { FACE_UP, diff --git a/src/world/BlockLookup.hpp b/src/world/BlockLookup.hpp index 605b896..3d7aa04 100644 --- a/src/world/BlockLookup.hpp +++ b/src/world/BlockLookup.hpp @@ -11,19 +11,19 @@ class BlockLookup { public: /// resolve chunk/position from oob coordinates - BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept; + BlockLookup(Chunk *c, const RoughLocation::Fine &p) noexcept; /// resolve chunk/position from ib coordinates and direction - BlockLookup(Chunk *c, const Chunk::Pos &p, Block::Face dir) noexcept; + BlockLookup(Chunk *c, const RoughLocation::Fine &p, Block::Face dir) noexcept; /// check if lookup was successful operator bool() const { return chunk; } // only valid if lookup was successful Chunk &GetChunk() const noexcept { return *chunk; } - const Chunk::Pos &GetBlockPos() const noexcept { return pos; } + const RoughLocation::Fine &GetBlockPos() const noexcept { return pos; } int GetBlockIndex() const noexcept { return Chunk::ToIndex(pos); } - Block::Pos GetBlockCoords() const noexcept { return Chunk::ToCoords(pos); } + ExactLocation::Fine GetBlockCoords() const noexcept { return Chunk::ToCoords(pos); } const Block &GetBlock() const noexcept { return GetChunk().BlockAt(GetBlockPos()); } const BlockType &GetType() const noexcept { return GetChunk().Type(GetBlock()); } int GetLight() const noexcept { return GetChunk().GetLight(GetBlockPos()); } @@ -35,7 +35,7 @@ public: private: Chunk *chunk; - Chunk::Pos pos; + RoughLocation::Fine pos; }; diff --git a/src/world/Chunk.hpp b/src/world/Chunk.hpp index b6298b3..6e87a09 100644 --- a/src/world/Chunk.hpp +++ b/src/world/Chunk.hpp @@ -3,6 +3,7 @@ #include "Block.hpp" #include "BlockTypeRegistry.hpp" +#include "../geometry/Location.hpp" #include "../geometry/primitive.hpp" #include @@ -18,86 +19,81 @@ class WorldCollision; /// cube of size 16 (256 tiles, 4096 blocks) class Chunk { -public: - using Pos = glm::ivec3; - public: explicit Chunk(const BlockTypeRegistry &) noexcept; Chunk(Chunk &&) noexcept; Chunk &operator =(Chunk &&) noexcept; - static constexpr int width = 16; - static constexpr int height = 16; - static constexpr int depth = 16; - static Pos Extent() noexcept { return { width, height, depth }; } - static constexpr int size = width * height * depth; + static constexpr int side = ExactLocation::scale; + static constexpr float fside = ExactLocation::fscale; + static constexpr int size = side * side * side; - static AABB Bounds() noexcept { return AABB{ { 0, 0, 0 }, Extent() }; } + static AABB Bounds() noexcept { return AABB{ { 0.0f, 0.0f, 0.0f }, ExactLocation::FExtent() }; } - static constexpr bool InBounds(const Block::Pos &pos) noexcept { + static constexpr bool InBounds(const ExactLocation::Fine &pos) noexcept { return - pos.x >= 0 && pos.x < width && - pos.y >= 0 && pos.y < height && - pos.z >= 0 && pos.z < depth; + pos.x >= 0.0f && pos.x < fside && + pos.y >= 0.0f && pos.y < fside && + pos.z >= 0.0f && pos.z < fside; } - static constexpr bool InBounds(const Pos &pos) noexcept { + static constexpr bool InBounds(const RoughLocation::Fine &pos) noexcept { return - pos.x >= 0 && pos.x < width && - pos.y >= 0 && pos.y < height && - pos.z >= 0 && pos.z < depth; + pos.x >= 0 && pos.x < side && + pos.y >= 0 && pos.y < side && + pos.z >= 0 && pos.z < side; } - static constexpr int ToIndex(const Pos &pos) noexcept { - return pos.x + pos.y * width + pos.z * width * height; + static constexpr int ToIndex(const RoughLocation::Fine &pos) noexcept { + return pos.x + pos.y * side + pos.z * side * side; } static constexpr bool InBounds(int idx) noexcept { return idx >= 0 && idx < size; } - static Block::Pos ToCoords(int idx) noexcept { - return Block::Pos( - 0.5f + (idx % width), - 0.5f + ((idx / width) % height), - 0.5f + (idx / (width * height)) + static ExactLocation::Fine ToCoords(int idx) noexcept { + return ExactLocation::Fine( + 0.5f + (idx % side), + 0.5f + ((idx / side) % side), + 0.5f + (idx / (side * side)) ); } - static Block::Pos ToCoords(const Pos &pos) noexcept { - return Block::Pos(pos) + 0.5f; + static ExactLocation::Fine ToCoords(const RoughLocation::Fine &pos) noexcept { + return ExactLocation::Fine(pos) + 0.5f; } - static Pos ToPos(int idx) noexcept { - return Pos( - (idx % width), - ((idx / width) % height), - (idx / (width * height)) + static RoughLocation::Fine ToPos(int idx) noexcept { + return RoughLocation::Fine( + (idx % side), + ((idx / side) % side), + (idx / (side * side)) ); } - glm::mat4 ToTransform(const Pos &pos, int idx) const noexcept; + glm::mat4 ToTransform(const RoughLocation::Fine &pos, int idx) const noexcept; - Block::Pos ToSceneCoords(const Pos &base, const Block::Pos &pos) const noexcept { - return Block::Pos((position - base) * Extent()) + pos; + ExactLocation::Fine ToSceneCoords(const ExactLocation::Coarse &base, const ExactLocation::Fine &pos) const noexcept { + return ExactLocation::Fine((position - base) * ExactLocation::Extent()) + pos; } - static bool IsBorder(const Pos &pos) noexcept { + static bool IsBorder(const RoughLocation::Fine &pos) noexcept { return pos.x == 0 || - pos.x == width - 1 || + pos.x == side - 1 || pos.y == 0 || - pos.y == height - 1 || + pos.y == side - 1 || pos.z == 0 || - pos.z == depth - 1; + pos.z == side - 1; } static constexpr bool IsBorder(int idx) noexcept { return - idx < width * height || // low Z plane - idx % width == 0 || // low X plane - (idx / (width * height)) == depth - 1 || // high Z plane - idx % width == width - 1 || // high X plane - (idx / width) % height == 0 || // low Y plane - (idx / width) % height == height - 1; // high Y plane + idx < side * side || // low Z plane + idx % side == 0 || // low X plane + (idx / (side * side)) == side - 1 || // high Z plane + idx % side == side - 1 || // high X plane + (idx / side) % side == 0 || // low Y plane + (idx / side) % side == side - 1; // high Y plane } bool IsSurface(int index) const noexcept { return IsSurface(ToPos(index)); } - bool IsSurface(const Block::Pos &pos) const noexcept { return IsSurface(Pos(pos)); } - bool IsSurface(const Pos &pos) const noexcept; + bool IsSurface(const ExactLocation::Fine &pos) const noexcept { return IsSurface(RoughLocation::Fine(pos)); } + bool IsSurface(const RoughLocation::Fine &pos) const noexcept; void SetNeighbor(Block::Face, Chunk &) noexcept; bool HasNeighbor(Block::Face f) const noexcept { return neighbor[f]; } @@ -106,28 +102,28 @@ public: void Unlink() noexcept; // check which faces of a block at given index are obstructed (and therefore invisible) - Block::FaceSet Obstructed(const Pos &) const noexcept; + Block::FaceSet Obstructed(const RoughLocation::Fine &) const noexcept; void SetBlock(int index, const Block &) noexcept; - void SetBlock(const Block::Pos &pos, const Block &block) noexcept { SetBlock(ToIndex(pos), block); } - void SetBlock(const Pos &pos, const Block &block) noexcept { SetBlock(ToIndex(pos), block); } + void SetBlock(const ExactLocation::Fine &pos, const Block &block) noexcept { SetBlock(ToIndex(pos), block); } + void SetBlock(const RoughLocation::Fine &pos, const Block &block) noexcept { SetBlock(ToIndex(pos), block); } const Block &BlockAt(int index) const noexcept { return blocks[index]; } - const Block &BlockAt(const Block::Pos &pos) const noexcept { return BlockAt(ToIndex(pos)); } - const Block &BlockAt(const Pos &pos) const noexcept { return BlockAt(ToIndex(pos)); } + const Block &BlockAt(const ExactLocation::Fine &pos) const noexcept { return BlockAt(ToIndex(pos)); } + const Block &BlockAt(const RoughLocation::Fine &pos) const noexcept { return BlockAt(ToIndex(pos)); } const BlockType &Type(const Block &b) const noexcept { return types->Get(b.type); } const BlockType &Type(int index) const noexcept { return Type(BlockAt(index)); } void SetLight(int index, int level) noexcept; - void SetLight(const Pos &pos, int level) noexcept { SetLight(ToIndex(pos), level); } - void SetLight(const Block::Pos &pos, int level) noexcept { SetLight(ToIndex(pos), level); } + void SetLight(const ExactLocation::Fine &pos, int level) noexcept { SetLight(ToIndex(pos), level); } + void SetLight(const RoughLocation::Fine &pos, int level) noexcept { SetLight(ToIndex(pos), level); } int GetLight(int index) const noexcept; - int GetLight(const Pos &pos) const noexcept { return GetLight(ToIndex(pos)); } - int GetLight(const Block::Pos &pos) const noexcept { return GetLight(ToIndex(pos)); } + int GetLight(const ExactLocation::Fine &pos) const noexcept { return GetLight(ToIndex(pos)); } + int GetLight(const RoughLocation::Fine &pos) const noexcept { return GetLight(ToIndex(pos)); } - float GetVertexLight(const Pos &, const BlockMesh::Position &, const EntityMesh::Normal &) const noexcept; + float GetVertexLight(const RoughLocation::Fine &, const BlockMesh::Position &, const EntityMesh::Normal &) const noexcept; bool Intersection( const Ray &ray, @@ -148,10 +144,10 @@ public: const glm::mat4 &Mchunk, std::vector &) noexcept; - void Position(const Pos &pos) noexcept { position = pos; } - const Pos &Position() const noexcept { return position; } - glm::mat4 Transform(const Pos &offset) const noexcept { - return glm::translate((position - offset) * Extent()); + void Position(const ExactLocation::Coarse &pos) noexcept { position = pos; } + const ExactLocation::Coarse &Position() const noexcept { return position; } + glm::mat4 Transform(const ExactLocation::Coarse &offset) const noexcept { + return glm::translate((position - offset) * ExactLocation::Extent()); } void *BlockData() noexcept { return &blocks[0]; } @@ -185,7 +181,7 @@ private: bool generated; bool lighted; - Pos position; + ExactLocation::Coarse position; int ref_count; bool dirty_mesh; bool dirty_save; diff --git a/src/world/ChunkIndex.hpp b/src/world/ChunkIndex.hpp index 97956e9..1823de7 100644 --- a/src/world/ChunkIndex.hpp +++ b/src/world/ChunkIndex.hpp @@ -15,26 +15,26 @@ class ChunkStore; class ChunkIndex { public: - ChunkIndex(ChunkStore &, const Chunk::Pos &base, int extent); + ChunkIndex(ChunkStore &, const ExactLocation::Coarse &base, int extent); ~ChunkIndex(); ChunkIndex(const ChunkIndex &) = delete; ChunkIndex &operator =(const ChunkIndex &) = delete; public: - bool InRange(const Chunk::Pos &) const noexcept; - bool IsBorder(const Chunk::Pos &) const noexcept; - int Distance(const Chunk::Pos &) const noexcept; + bool InRange(const ExactLocation::Coarse &) const noexcept; + bool IsBorder(const ExactLocation::Coarse &) const noexcept; + int Distance(const ExactLocation::Coarse &) const noexcept; - bool HasAllSurrounding(const Chunk::Pos &) const noexcept; + bool HasAllSurrounding(const ExactLocation::Coarse &) const noexcept; - int IndexOf(const Chunk::Pos &) const noexcept; - Chunk::Pos PositionOf(int) const noexcept; + int IndexOf(const ExactLocation::Coarse &) const noexcept; + ExactLocation::Coarse PositionOf(int) const noexcept; /// returns nullptr if given position is out of range or the chunk /// is not loaded, so also works as a "has" function - Chunk *Get(const Chunk::Pos &) noexcept; - const Chunk *Get(const Chunk::Pos &) const noexcept; + Chunk *Get(const ExactLocation::Coarse &) noexcept; + const Chunk *Get(const ExactLocation::Coarse &) const noexcept; Chunk *operator [](int i) noexcept { return chunks[i]; } const Chunk *operator [](int i) const noexcept { return chunks[i]; } @@ -47,8 +47,8 @@ public: int Extent() const noexcept { return extent; } - Chunk::Pos CoordsBegin() const noexcept { return base - Chunk::Pos(extent); } - Chunk::Pos CoordsEnd() const noexcept { return base + Chunk::Pos(extent + 1); } + ExactLocation::Coarse CoordsBegin() const noexcept { return base - ExactLocation::Coarse(extent); } + ExactLocation::Coarse CoordsEnd() const noexcept { return base + ExactLocation::Coarse(extent + 1); } void Register(Chunk &) noexcept; @@ -56,10 +56,10 @@ public: int IndexedChunks() const noexcept { return total_indexed; } int MissingChunks() const noexcept { return total_length - total_indexed; } - Chunk::Pos NextMissing() noexcept; + ExactLocation::Coarse NextMissing() noexcept; - const Chunk::Pos &Base() const noexcept { return base; } - void Rebase(const Chunk::Pos &); + const ExactLocation::Coarse &Base() const noexcept { return base; } + void Rebase(const ExactLocation::Coarse &); private: int GetCol(int) const noexcept; @@ -74,7 +74,7 @@ private: private: ChunkStore &store; - Chunk::Pos base; + ExactLocation::Coarse base; int extent; int side_length; int total_length; diff --git a/src/world/ChunkStore.hpp b/src/world/ChunkStore.hpp index 3bbe96d..12debef 100644 --- a/src/world/ChunkStore.hpp +++ b/src/world/ChunkStore.hpp @@ -20,15 +20,15 @@ public: ChunkStore &operator =(const ChunkStore &) = delete; public: - ChunkIndex &MakeIndex(const Chunk::Pos &base, int extent); + ChunkIndex &MakeIndex(const ExactLocation::Coarse &base, int extent); void UnregisterIndex(ChunkIndex &); - ChunkIndex *ClosestIndex(const Chunk::Pos &pos); + ChunkIndex *ClosestIndex(const ExactLocation::Coarse &pos); /// returns nullptr if given position is not loaded - Chunk *Get(const Chunk::Pos &); + Chunk *Get(const ExactLocation::Coarse &); /// returns nullptr if given position is not indexed - Chunk *Allocate(const Chunk::Pos &); + Chunk *Allocate(const ExactLocation::Coarse &); std::list::iterator begin() noexcept { return loaded.begin(); } std::list::iterator end() noexcept { return loaded.end(); } @@ -44,7 +44,7 @@ public: /// get coordinates of a missing chunk /// this will return garbage if none are actually missing - Chunk::Pos NextMissing() noexcept; + ExactLocation::Coarse NextMissing() noexcept; void Clean(); diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index 4b24944..2a4ef89 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -63,11 +63,11 @@ public: const glm::vec3 &Velocity() const noexcept { return state.velocity; } - const glm::vec3 &Position() const noexcept { return state.block_pos; } - void Position(const glm::ivec3 &, const glm::vec3 &) noexcept; - void Position(const glm::vec3 &) noexcept; + const ExactLocation::Fine &Position() const noexcept { return state.pos.block; } + void Position(const ExactLocation::Coarse &, const ExactLocation::Fine &) noexcept; + void Position(const ExactLocation::Fine &) noexcept; - const glm::ivec3 ChunkCoords() const noexcept { return state.chunk_pos; } + const glm::ivec3 ChunkCoords() const noexcept { return state.pos.chunk; } glm::vec3 AbsolutePosition() const noexcept { return state.AbsolutePosition(); @@ -92,7 +92,7 @@ public: /// get a transform for this entity's view space relative to reference chunk glm::mat4 ViewTransform(const glm::ivec3 &reference) const noexcept; /// get a ray in entity's face direction originating from center of vision - Ray Aim(const Chunk::Pos &chunk_offset) const noexcept; + Ray Aim(const ExactLocation::Coarse &chunk_offset) const noexcept; /// true if this entity's position will change (significantly) the next update bool Moving() const noexcept { return speed > 0.0f; } diff --git a/src/world/EntityState.hpp b/src/world/EntityState.hpp index 21b60dd..ee99c76 100644 --- a/src/world/EntityState.hpp +++ b/src/world/EntityState.hpp @@ -1,7 +1,7 @@ #ifndef BLANK_WORLD_ENTITYSTATE_HPP_ #define BLANK_WORLD_ENTITYSTATE_HPP_ -#include "Chunk.hpp" +#include "../geometry/Location.hpp" #include #include @@ -11,8 +11,7 @@ namespace blank { struct EntityState { - glm::ivec3 chunk_pos; - glm::vec3 block_pos; + ExactLocation pos; glm::vec3 velocity; glm::quat orient; @@ -21,23 +20,23 @@ struct EntityState { EntityState(); - /// make sure block_pos is within chunk bounds + /// make sure pos.block is within chunk bounds void AdjustPosition() noexcept; /// make sure pitch and yaw are normalized void AdjustHeading() noexcept; /// get a position vector relative to the (0,0,0) chunk glm::vec3 AbsolutePosition() const noexcept { - return glm::vec3(chunk_pos * Chunk::Extent()) + block_pos; + return pos.Absolute(); } /// get a position vector relative to given reference chunk glm::vec3 RelativePosition(const glm::ivec3 &reference) const noexcept { - return glm::vec3((chunk_pos - reference) * Chunk::Extent()) + block_pos; + return pos.Relative(reference).Absolute(); } /// get the difference between this and the given position glm::vec3 Diff(const EntityState &other) const noexcept { - return RelativePosition(other.chunk_pos) - other.block_pos; + return pos.Difference(other.pos).Absolute(); } /// get entity state as a matrix tranform relative to given reference chunk diff --git a/src/world/Generator.cpp b/src/world/Generator.cpp index 88ac1eb..466139b 100644 --- a/src/world/Generator.cpp +++ b/src/world/Generator.cpp @@ -50,13 +50,13 @@ void Generator::LoadTypes(const BlockTypeRegistry ®) { } void Generator::operator ()(Chunk &chunk) const noexcept { - Chunk::Pos pos(chunk.Position()); - glm::vec3 coords(pos * Chunk::Extent()); - for (int z = 0; z < Chunk::depth; ++z) { - for (int y = 0; y < Chunk::height; ++y) { - for (int x = 0; x < Chunk::width; ++x) { - Block::Pos block_pos(x, y, z); - chunk.SetBlock(block_pos, Generate(coords + block_pos)); + ExactLocation::Coarse pos(chunk.Position()); + ExactLocation::Fine coords(pos * ExactLocation::Extent()); + for (int z = 0; z < Chunk::side; ++z) { + for (int y = 0; y < Chunk::side; ++y) { + for (int x = 0; x < Chunk::side; ++x) { + ExactLocation::Fine block_pos(x, y, z); + chunk.SetBlock(RoughLocation::Fine(x, y, z), Generate(coords + ExactLocation::Fine(x, y, z))); } } } diff --git a/src/world/World.hpp b/src/world/World.hpp index 273bfa6..8754d39 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -49,7 +49,7 @@ public: bool Intersection( const Ray &, const glm::mat4 &M, - const Chunk::Pos &reference, + const ExactLocation::Coarse &reference, WorldCollision &); /// check if this ray hits an entity diff --git a/src/world/WorldCollision.hpp b/src/world/WorldCollision.hpp index ac7dbbf..65cba9d 100644 --- a/src/world/WorldCollision.hpp +++ b/src/world/WorldCollision.hpp @@ -35,10 +35,10 @@ struct WorldCollision { bool Blocks() const noexcept { return chunk->Type(block).collide_block; } - const Chunk::Pos &ChunkPos() const noexcept { return GetChunk().Position(); } + const ExactLocation::Coarse &ChunkPos() const noexcept { return GetChunk().Position(); } - glm::ivec3 BlockPos() const noexcept { return Chunk::ToPos(block); } - glm::vec3 BlockCoords() const noexcept { return Chunk::ToCoords(block); } + RoughLocation::Fine BlockPos() const noexcept { return Chunk::ToPos(block); } + ExactLocation::Fine BlockCoords() const noexcept { return Chunk::ToCoords(block); } glm::mat4 BlockTransform() const noexcept { return GetChunk().ToTransform(BlockPos(), block); } }; diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index 8340d56..cedc532 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -22,9 +22,7 @@ namespace blank { -constexpr int Chunk::width; -constexpr int Chunk::height; -constexpr int Chunk::depth; +constexpr int Chunk::side; constexpr int Chunk::size; @@ -76,9 +74,9 @@ namespace { struct SetNode { Chunk *chunk; - Chunk::Pos pos; + RoughLocation::Fine pos; - SetNode(Chunk *chunk, Chunk::Pos pos) + SetNode(Chunk *chunk, RoughLocation::Fine pos) : chunk(chunk), pos(pos) { } int Get() const noexcept { return chunk->GetLight(pos); } @@ -104,7 +102,7 @@ struct UnsetNode int level; - UnsetNode(Chunk *chunk, Chunk::Pos pos) + UnsetNode(Chunk *chunk, RoughLocation::Fine pos) : SetNode(chunk, pos), level(Get()) { } UnsetNode(const SetNode &set) @@ -195,7 +193,7 @@ void Chunk::SetBlock(int index, const Block &block) noexcept { } else if (!new_type.block_light && old_type.block_light) { // obstacle removed int level = 0; - Pos pos(ToPos(index)); + RoughLocation::Fine pos(ToPos(index)); for (int face = 0; face < Block::FACE_COUNT; ++face) { BlockLookup next_block(this, pos, Block::Face(face)); if (next_block) { @@ -212,10 +210,10 @@ void Chunk::SetBlock(int index, const Block &block) noexcept { void Chunk::ScanLights() { int idx = 0; - Pos pos(0, 0, 0); - for (; pos.z < depth; ++pos.z) { - for (pos.y = 0; pos.y < height; ++pos.y) { - for (pos.x = 0; pos.x < width; ++pos.x, ++idx) { + RoughLocation::Fine pos(0, 0, 0); + for (; pos.z < side; ++pos.z) { + for (pos.y = 0; pos.y < side; ++pos.y) { + for (pos.x = 0; pos.x < side; ++pos.x, ++idx) { const BlockType &type = Type(blocks[idx]); if (type.luminosity) { SetLight(idx, type.luminosity); @@ -254,7 +252,7 @@ int Chunk::GetLight(int index) const noexcept { return light[index]; } -float Chunk::GetVertexLight(const Pos &pos, const BlockMesh::Position &vtx, const EntityMesh::Normal &norm) const noexcept { +float Chunk::GetVertexLight(const RoughLocation::Fine &pos, const BlockMesh::Position &vtx, const EntityMesh::Normal &norm) const noexcept { int index = ToIndex(pos); float light = GetLight(index); @@ -344,7 +342,7 @@ float Chunk::GetVertexLight(const Pos &pos, const BlockMesh::Position &vtx, cons } -bool Chunk::IsSurface(const Pos &pos) const noexcept { +bool Chunk::IsSurface(const RoughLocation::Fine &pos) const noexcept { const Block &block = BlockAt(pos); if (!Type(block).visible) { return false; @@ -368,16 +366,16 @@ bool Chunk::Intersection( coll.chunk = this; coll.block = -1; coll.depth = std::numeric_limits::infinity(); - for (int z = 0; z < depth; ++z) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x, ++idx) { + for (int z = 0; z < side; ++z) { + for (int y = 0; y < side; ++y) { + for (int x = 0; x < side; ++x, ++idx) { const BlockType &type = Type(idx); if (!type.collision || !type.shape) { continue; } float cur_dist; glm::vec3 cur_norm; - if (type.shape->Intersects(ray, M * ToTransform(Pos(x, y, z), idx), cur_dist, cur_norm)) { + if (type.shape->Intersects(ray, M * ToTransform(RoughLocation::Fine(x, y, z), idx), cur_dist, cur_norm)) { if (cur_dist < coll.depth) { coll.block = idx; coll.depth = cur_dist; @@ -409,14 +407,14 @@ bool Chunk::Intersection( if (!blank::Intersection(box, Mbox, Bounds(), Mchunk, penetration, normal)) { return false; } - for (int idx = 0, z = 0; z < depth; ++z) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x, ++idx) { + for (int idx = 0, z = 0; z < side; ++z) { + for (int y = 0; y < side; ++y) { + for (int x = 0; x < side; ++x, ++idx) { const BlockType &type = Type(idx); if (!type.collision || !type.shape) { continue; } - if (type.shape->Intersects(Mchunk * ToTransform(Pos(x, y, z), idx), box, Mbox, penetration, normal)) { + if (type.shape->Intersects(Mchunk * ToTransform(RoughLocation::Fine(x, y, z), idx), box, Mbox, penetration, normal)) { col.emplace_back(this, idx, penetration, normal); any = true; } @@ -448,11 +446,11 @@ void Chunk::Update(BlockMesh &model) noexcept { if (idx_count > 0) { int idx = 0; BlockMesh::Index vtx_counter = 0; - for (size_t z = 0; z < depth; ++z) { - for (size_t y = 0; y < height; ++y) { - for (size_t x = 0; x < width; ++x, ++idx) { + for (size_t z = 0; z < side; ++z) { + for (size_t y = 0; y < side; ++y) { + for (size_t x = 0; x < side; ++x, ++idx) { const BlockType &type = Type(BlockAt(idx)); - const Pos pos(x, y, z); + const RoughLocation::Fine pos(x, y, z); if (!type.visible || !type.shape || Obstructed(pos).All()) continue; @@ -476,7 +474,7 @@ void Chunk::Update(BlockMesh &model) noexcept { ClearMesh(); } -Block::FaceSet Chunk::Obstructed(const Pos &pos) const noexcept { +Block::FaceSet Chunk::Obstructed(const RoughLocation::Fine &pos) const noexcept { Block::FaceSet result; for (int f = 0; f < Block::FACE_COUNT; ++f) { @@ -490,17 +488,17 @@ Block::FaceSet Chunk::Obstructed(const Pos &pos) const noexcept { return result; } -glm::mat4 Chunk::ToTransform(const Pos &pos, int idx) const noexcept { +glm::mat4 Chunk::ToTransform(const RoughLocation::Fine &pos, int idx) const noexcept { return glm::translate(ToCoords(pos)) * BlockAt(idx).Transform(); } -BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept +BlockLookup::BlockLookup(Chunk *c, const RoughLocation::Fine &p) noexcept : chunk(c), pos(p) { - while (pos.x >= Chunk::width) { + while (pos.x >= Chunk::side) { if (chunk->HasNeighbor(Block::FACE_RIGHT)) { chunk = &chunk->GetNeighbor(Block::FACE_RIGHT); - pos.x -= Chunk::width; + pos.x -= Chunk::side; } else { chunk = nullptr; return; @@ -509,16 +507,16 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept while (pos.x < 0) { if (chunk->HasNeighbor(Block::FACE_LEFT)) { chunk = &chunk->GetNeighbor(Block::FACE_LEFT); - pos.x += Chunk::width; + pos.x += Chunk::side; } else { chunk = nullptr; return; } } - while (pos.y >= Chunk::height) { + while (pos.y >= Chunk::side) { if (chunk->HasNeighbor(Block::FACE_UP)) { chunk = &chunk->GetNeighbor(Block::FACE_UP); - pos.y -= Chunk::height; + pos.y -= Chunk::side; } else { chunk = nullptr; return; @@ -527,16 +525,16 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept while (pos.y < 0) { if (chunk->HasNeighbor(Block::FACE_DOWN)) { chunk = &chunk->GetNeighbor(Block::FACE_DOWN); - pos.y += Chunk::height; + pos.y += Chunk::side; } else { chunk = nullptr; return; } } - while (pos.z >= Chunk::depth) { + while (pos.z >= Chunk::side) { if (chunk->HasNeighbor(Block::FACE_FRONT)) { chunk = &chunk->GetNeighbor(Block::FACE_FRONT); - pos.z -= Chunk::depth; + pos.z -= Chunk::side; } else { chunk = nullptr; return; @@ -545,7 +543,7 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept while (pos.z < 0) { if (chunk->HasNeighbor(Block::FACE_BACK)) { chunk = &chunk->GetNeighbor(Block::FACE_BACK); - pos.z += Chunk::depth; + pos.z += Chunk::side; } else { chunk = nullptr; return; @@ -553,11 +551,11 @@ BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p) noexcept } } -BlockLookup::BlockLookup(Chunk *c, const Chunk::Pos &p, Block::Face face) noexcept +BlockLookup::BlockLookup(Chunk *c, const RoughLocation::Fine &p, Block::Face face) noexcept : chunk(c), pos(p) { pos += Block::FaceNormal(face); if (!Chunk::InBounds(pos)) { - pos -= Block::FaceNormal(face) * Chunk::Extent(); + pos -= Block::FaceNormal(face) * ExactLocation::Extent(); chunk = &chunk->GetNeighbor(face); } } @@ -610,7 +608,7 @@ int ChunkLoader::ToLoad() const noexcept { bool ChunkLoader::LoadOne() { if (!store.HasMissing()) return false; - Chunk::Pos pos = store.NextMissing(); + ExactLocation::Coarse pos = store.NextMissing(); Chunk *chunk = store.Allocate(pos); if (!chunk) { // chunk store corrupted? @@ -630,9 +628,9 @@ bool ChunkLoader::LoadOne() { return generated; } - Chunk::Pos begin(pos - Chunk::Pos(1)); - Chunk::Pos end(pos + Chunk::Pos(2)); - for (Chunk::Pos iter(begin); iter.z < end.z; ++iter.z) { + ExactLocation::Coarse begin(pos - ExactLocation::Coarse(1)); + ExactLocation::Coarse end(pos + ExactLocation::Coarse(2)); + for (ExactLocation::Coarse iter(begin); iter.z < end.z; ++iter.z) { for (iter.y = begin.y; iter.y < end.y; ++iter.y) { for (iter.x = begin.x; iter.x < end.x; ++iter.x) { if (index->IsBorder(iter)) continue; @@ -715,7 +713,7 @@ void ChunkRenderer::Render(Viewport &viewport) { } -ChunkIndex::ChunkIndex(ChunkStore &store, const Chunk::Pos &base, int extent) +ChunkIndex::ChunkIndex(ChunkStore &store, const ExactLocation::Coarse &base, int extent) : store(store) , base(base) , extent(extent) @@ -732,22 +730,22 @@ ChunkIndex::~ChunkIndex() { Clear(); } -bool ChunkIndex::InRange(const Chunk::Pos &pos) const noexcept { +bool ChunkIndex::InRange(const ExactLocation::Coarse &pos) const noexcept { return Distance(pos) <= extent; } -bool ChunkIndex::IsBorder(const Chunk::Pos &pos) const noexcept { +bool ChunkIndex::IsBorder(const ExactLocation::Coarse &pos) const noexcept { return Distance(pos) == extent; } -int ChunkIndex::Distance(const Chunk::Pos &pos) const noexcept { +int ChunkIndex::Distance(const ExactLocation::Coarse &pos) const noexcept { return manhattan_radius(pos - base); } -bool ChunkIndex::HasAllSurrounding(const Chunk::Pos &pos) const noexcept { - Chunk::Pos begin(pos - Chunk::Pos(1)); - Chunk::Pos end(pos + Chunk::Pos(2)); - for (Chunk::Pos iter(begin); iter.z < end.z; ++iter.z) { +bool ChunkIndex::HasAllSurrounding(const ExactLocation::Coarse &pos) const noexcept { + ExactLocation::Coarse begin(pos - ExactLocation::Coarse(1)); + ExactLocation::Coarse end(pos + ExactLocation::Coarse(2)); + for (ExactLocation::Coarse iter(begin); iter.z < end.z; ++iter.z) { for (iter.y = begin.y; iter.y < end.y; ++iter.y) { for (iter.x = begin.x; iter.x < end.x; ++iter.x) { if (!Get(iter)) return false; @@ -757,8 +755,8 @@ bool ChunkIndex::HasAllSurrounding(const Chunk::Pos &pos) const noexcept { return true; } -int ChunkIndex::IndexOf(const Chunk::Pos &pos) const noexcept { - Chunk::Pos mod_pos( +int ChunkIndex::IndexOf(const ExactLocation::Coarse &pos) const noexcept { + ExactLocation::Coarse mod_pos( GetCol(pos.x), GetCol(pos.y), GetCol(pos.z) @@ -768,18 +766,18 @@ int ChunkIndex::IndexOf(const Chunk::Pos &pos) const noexcept { + mod_pos.z * stride.z; } -Chunk::Pos ChunkIndex::PositionOf(int i) const noexcept { - Chunk::Pos zero_pos( +ExactLocation::Coarse ChunkIndex::PositionOf(int i) const noexcept { + ExactLocation::Coarse zero_pos( (i / stride.x) % side_length, (i / stride.y) % side_length, (i / stride.z) % side_length ); - Chunk::Pos zero_base( + ExactLocation::Coarse zero_base( GetCol(base.x), GetCol(base.y), GetCol(base.z) ); - Chunk::Pos base_relative(zero_pos - zero_base); + ExactLocation::Coarse base_relative(zero_pos - zero_base); if (base_relative.x > extent) base_relative.x -= side_length; else if (base_relative.x < -extent) base_relative.x += side_length; if (base_relative.y > extent) base_relative.y -= side_length; @@ -789,7 +787,7 @@ Chunk::Pos ChunkIndex::PositionOf(int i) const noexcept { return base + base_relative; } -Chunk *ChunkIndex::Get(const Chunk::Pos &pos) noexcept { +Chunk *ChunkIndex::Get(const ExactLocation::Coarse &pos) noexcept { if (InRange(pos)) { return chunks[IndexOf(pos)]; } else { @@ -797,7 +795,7 @@ Chunk *ChunkIndex::Get(const Chunk::Pos &pos) noexcept { } } -const Chunk *ChunkIndex::Get(const Chunk::Pos &pos) const noexcept { +const Chunk *ChunkIndex::Get(const ExactLocation::Coarse &pos) const noexcept { if (InRange(pos)) { return chunks[IndexOf(pos)]; } else { @@ -805,10 +803,10 @@ const Chunk *ChunkIndex::Get(const Chunk::Pos &pos) const noexcept { } } -void ChunkIndex::Rebase(const Chunk::Pos &new_base) { +void ChunkIndex::Rebase(const ExactLocation::Coarse &new_base) { if (new_base == base) return; - Chunk::Pos diff(new_base - base); + ExactLocation::Coarse diff(new_base - base); if (manhattan_radius(diff) > extent) { // that's more than half, so probably not worth shifting @@ -907,7 +905,7 @@ void ChunkIndex::Unset(int index) noexcept { } } -Chunk::Pos ChunkIndex::NextMissing() noexcept { +ExactLocation::Coarse ChunkIndex::NextMissing() noexcept { if (MissingChunks() > 0) { int roundtrip = last_missing; last_missing = (last_missing + 1) % total_length; @@ -934,7 +932,7 @@ ChunkStore::~ChunkStore() { } -ChunkIndex &ChunkStore::MakeIndex(const Chunk::Pos &pos, int extent) { +ChunkIndex &ChunkStore::MakeIndex(const ExactLocation::Coarse &pos, int extent) { indices.emplace_back(*this, pos, extent); return indices.back(); } @@ -950,7 +948,7 @@ void ChunkStore::UnregisterIndex(ChunkIndex &index) { } } -ChunkIndex *ChunkStore::ClosestIndex(const Chunk::Pos &pos) { +ChunkIndex *ChunkStore::ClosestIndex(const ExactLocation::Coarse &pos) { ChunkIndex *closest_index = nullptr; int closest_distance = std::numeric_limits::max(); @@ -965,7 +963,7 @@ ChunkIndex *ChunkStore::ClosestIndex(const Chunk::Pos &pos) { return closest_index; } -Chunk *ChunkStore::Get(const Chunk::Pos &pos) { +Chunk *ChunkStore::Get(const ExactLocation::Coarse &pos) { for (ChunkIndex &index : indices) { Chunk *chunk = index.Get(pos); if (chunk) { @@ -975,7 +973,7 @@ Chunk *ChunkStore::Get(const Chunk::Pos &pos) { return nullptr; } -Chunk *ChunkStore::Allocate(const Chunk::Pos &pos) { +Chunk *ChunkStore::Allocate(const ExactLocation::Coarse &pos) { Chunk *chunk = Get(pos); if (chunk) { return chunk; @@ -995,7 +993,7 @@ Chunk *ChunkStore::Allocate(const Chunk::Pos &pos) { } for (int i = 0; i < Block::FACE_COUNT; ++i) { Block::Face face = Block::Face(i); - Chunk::Pos neighbor_pos(pos + Block::FaceNormal(face)); + ExactLocation::Coarse neighbor_pos(pos + Block::FaceNormal(face)); Chunk *neighbor = Get(neighbor_pos); if (neighbor) { chunk->SetNeighbor(face, *neighbor); @@ -1021,13 +1019,13 @@ int ChunkStore::EstimateMissing() const noexcept { return missing; } -Chunk::Pos ChunkStore::NextMissing() noexcept { +ExactLocation::Coarse ChunkStore::NextMissing() noexcept { for (ChunkIndex &index : indices) { if (index.MissingChunks()) { return index.NextMissing(); } } - return Chunk::Pos(0, 0, 0); + return ExactLocation::Coarse(0, 0, 0); } void ChunkStore::Clean() { diff --git a/src/world/world.cpp b/src/world/world.cpp index 9372031..51c060c 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -96,12 +96,12 @@ glm::vec3 Entity::ControlForce(const EntityState &s) const noexcept { } void Entity::Position(const glm::ivec3 &c, const glm::vec3 &b) noexcept { - state.chunk_pos = c; - state.block_pos = b; + state.pos.chunk = c; + state.pos.block = b; } void Entity::Position(const glm::vec3 &pos) noexcept { - state.block_pos = pos; + state.pos.block = pos; state.AdjustPosition(); } @@ -115,14 +115,14 @@ void Entity::SetHead(float p, float y) noexcept { } glm::mat4 Entity::Transform(const glm::ivec3 &reference) const noexcept { - return glm::translate(glm::vec3((state.chunk_pos - reference) * Chunk::Extent())) * model_transform; + return glm::translate(glm::vec3((state.pos.chunk - reference) * ExactLocation::Extent())) * model_transform; } glm::mat4 Entity::ViewTransform(const glm::ivec3 &reference) const noexcept { return Transform(reference) * view_transform; } -Ray Entity::Aim(const Chunk::Pos &chunk_offset) const noexcept { +Ray Entity::Aim(const ExactLocation::Coarse &chunk_offset) const noexcept { glm::mat4 transform = ViewTransform(chunk_offset); return Ray{ glm::vec3(transform[3]), -glm::vec3(transform[2]) }; } @@ -138,7 +138,7 @@ void Entity::Update(float dt) { void Entity::UpdateTransforms() noexcept { // model transform is the one given by current state - model_transform = state.Transform(state.chunk_pos); + model_transform = state.Transform(state.pos.chunk); // view transform is either the model's eyes transform or, // should the entity have no model, the pitch (yaw already is // in model transform) @@ -268,8 +268,7 @@ bool EntityController::MaxOutForce( EntityState::EntityState() -: chunk_pos(0) -, block_pos(0.0f) +: pos() , velocity(0.0f) , orient(1.0f, 0.0f, 0.0f, 0.0f) , pitch(0.0f) @@ -278,30 +277,7 @@ EntityState::EntityState() } void EntityState::AdjustPosition() noexcept { - while (block_pos.x >= Chunk::width) { - block_pos.x -= Chunk::width; - ++chunk_pos.x; - } - while (block_pos.x < 0) { - block_pos.x += Chunk::width; - --chunk_pos.x; - } - while (block_pos.y >= Chunk::height) { - block_pos.y -= Chunk::height; - ++chunk_pos.y; - } - while (block_pos.y < 0) { - block_pos.y += Chunk::height; - --chunk_pos.y; - } - while (block_pos.z >= Chunk::depth) { - block_pos.z -= Chunk::depth; - ++chunk_pos.z; - } - while (block_pos.z < 0) { - block_pos.z += Chunk::depth; - --chunk_pos.z; - } + pos.Correct(); } void EntityState::AdjustHeading() noexcept { @@ -483,7 +459,7 @@ std::vector candidates; bool World::Intersection( const Ray &ray, const glm::mat4 &M, - const Chunk::Pos &reference, + const ExactLocation::Coarse &reference, WorldCollision &coll ) { candidates.clear(); @@ -545,7 +521,7 @@ bool World::Intersection( bool World::Intersection(const Entity &e, const EntityState &s, std::vector &col) { AABB box = e.Bounds(); - Chunk::Pos reference = s.chunk_pos; + glm::ivec3 reference = s.pos.chunk; glm::mat4 M = s.Transform(reference); return Intersection(box, M, reference, col); } @@ -603,7 +579,7 @@ void World::Update(Entity &entity, float dt) { f.position = sixth * ((a.position + 2.0f * (b.position + c.position)) + d.position); f.velocity = sixth * ((a.velocity + 2.0f * (b.velocity + c.velocity)) + d.velocity); - state.block_pos += f.position * dt; + state.pos.block += f.position * dt; state.velocity += f.velocity * dt; state.AdjustPosition(); @@ -617,7 +593,7 @@ EntityDerivative World::CalculateStep( const EntityDerivative &delta ) { EntityState next(cur); - next.block_pos += delta.position * dt; + next.pos.block += delta.position * dt; next.velocity += delta.velocity * dt; next.AdjustPosition(); diff --git a/tst/geometry/LocationTest.cpp b/tst/geometry/LocationTest.cpp new file mode 100644 index 0000000..c21c732 --- /dev/null +++ b/tst/geometry/LocationTest.cpp @@ -0,0 +1,474 @@ +#include "LocationTest.hpp" + +#include +#include + +CPPUNIT_TEST_SUITE_REGISTRATION(blank::test::LocationTest); + + +namespace blank { +namespace test { + +void LocationTest::setUp() { +} + +void LocationTest::tearDown() { +} + + +void LocationTest::testSanitize() { + { + RoughLocation loc({ 0, 0, 0 }, { 0, 0, 0 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough zero location", + RoughLocation({ 0, 0, 0 }, { 0, 0, 0 }), loc + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact zero location", + ExactLocation({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }), loc + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 15.9f, 0.0f, 0.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact location near upper boundary", + ExactLocation({ 0, 0, 0 }, { 15.9f, 0.0f, 0.0f }), loc + ); + } + { + RoughLocation loc({ 0, 0, 0 }, { 0, 16, 0 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough location", + RoughLocation({ 0, 1, 0 }, { 0, 0, 0 }), loc + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 16.0f, 0.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact location", + ExactLocation({ 0, 1, 0 }, { 0.0f, 0.0f, 0.0f }), loc + ); + } + { + RoughLocation loc({ 0, 0, 0 }, { 0, 0, -1 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough negative location", + RoughLocation({ 0, 0, -1 }, { 0, 0, 15 }), loc + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 0.0f, -1.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact negative location", + ExactLocation({ 0, 0, -1 }, { 0.0f, 0.0f, 15.0f }), loc + ); + } + { + RoughLocation loc({ 0, 0, 0 }, { 0, 41585, 0 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough really far location", + RoughLocation({ 0, 2599, 0 }, { 0, 1, 0 }), loc + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 41585.0f, 0.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact really far location", + ExactLocation({ 0, 2599, 0 }, { 0.0f, 1.0f, 0.0f }), loc + ); + } + { + RoughLocation loc({ 0, 0, 0 }, { -208005, 0, 0 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough really far negative location", + RoughLocation({ -13001, 0, 0 }, { 11, 0, 0 }), loc + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { -208005.0f, 0.0f, 0.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact really far negative location", + ExactLocation({ -13001, 0, 0 }, { 11.0f, 0.0f, 0.0f }), loc + ); + } + { + RoughLocation loc({ 0, -2, 0 }, { 0, 16, 0 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough location with non-zero chunk", + RoughLocation({ 0, -1, 0 }, { 0, 0, 0 }), loc + ); + } + { + ExactLocation loc({ 0, -2, 0 }, { 0.0f, 16.0f, 0.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact location with non-zero chunk", + ExactLocation({ 0, -1, 0 }, { 0.0f, 0.0f, 0.0f }), loc + ); + } + { + RoughLocation loc({ 0, 0, 5 }, { 0, 0, -33 }); + loc.Sanitize(); + AssertEqual( + "sanitize rough negative location with non-zero chunk", + RoughLocation({ 0, 0, 2 }, { 0, 0, 15 }), loc + ); + } + { + ExactLocation loc({ 0, 0, 5 }, { 0.0f, 0.0f, -33.0f }); + loc.Sanitize(); + AssertEqual( + "sanitize exact negative location with non-zero chunk", + ExactLocation({ 0, 0, 2 }, { 0.0f, 0.0f, 15.0f }), loc + ); + } +} + +void LocationTest::testAbsolute() { + { + RoughLocation loc({ 0, 0, 0 }, { 0, 0, 0 }); + AssertEqual( + "absolute of rough zero location", + RoughLocation::Fine(0, 0, 0), loc.Absolute() + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + AssertEqual( + "absolute of exact zero location", + ExactLocation::Fine(0.0f, 0.0f, 0.0f), loc.Absolute() + ); + } + { + RoughLocation loc({ 0, 2, 0 }, { 0, 5, 0 }); + AssertEqual( + "absolute of rough location", + RoughLocation::Fine(0, 37, 0), loc.Absolute() + ); + } + { + ExactLocation loc({ 0, 2, 0 }, { 0.0f, 5.0f, 0.0f }); + AssertEqual( + "absolute of exact location", + ExactLocation::Fine(0.0f, 37.0f, 0.0f), loc.Absolute() + ); + } + { + RoughLocation loc({ 0, 0, -2 }, { 0, 0, 5 }); + AssertEqual( + "absolute of rough negative location", + RoughLocation::Fine(0, 0, -27), loc.Absolute() + ); + } + { + ExactLocation loc({ 0, 0, -2 }, { 0.0f, 0.0f, 5.0f }); + AssertEqual( + "absolute of exact negative location", + ExactLocation::Fine(0.0f, 0.0f, -27.0f), loc.Absolute() + ); + } +} + +void LocationTest::testRelative() { + glm::ivec3 base(0, 0, 0); + { + RoughLocation loc({ 0, 0, 0 }, { 0, 0, 0 }); + AssertEqual( + "relative of rough zero location with zero base", + RoughLocation::Fine(0, 0, 0), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + AssertEqual( + "relative of exact zero location with zero base", + ExactLocation::Fine(0.0f, 0.0f, 0.0f), loc.Relative(base).Absolute() + ); + } + { + RoughLocation loc({ 0, 2, 0 }, { 0, 5, 0 }); + AssertEqual( + "relative of rough location with zero base", + RoughLocation::Fine(0, 37, 0), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 2, 0 }, { 0.0f, 5.0f, 0.0f }); + AssertEqual( + "relative of exact location with zero base", + ExactLocation::Fine(0.0f, 37.0f, 0.0f), loc.Relative(base).Absolute() + ); + } + { + RoughLocation loc({ 0, 0, -2 }, { 0, 0, 5 }); + AssertEqual( + "relative of rough negative location with zero base", + RoughLocation::Fine(0, 0, -27), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 0, -2 }, { 0.0f, 0.0f, 5.0f }); + AssertEqual( + "relative of exact negative location with zero base", + ExactLocation::Fine(0.0f, 0.0f, -27.0f), loc.Relative(base).Absolute() + ); + } + + base = glm::ivec3(0, 1, 0); + { + RoughLocation loc({ 0, 0, 0 }, { 0, 0, 0 }); + AssertEqual( + "relative of rough zero location with positive base", + RoughLocation::Fine(0, -16, 0), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + AssertEqual( + "relative of exact zero location with positive base", + ExactLocation::Fine(0.0f, -16.0f, 0.0f), loc.Relative(base).Absolute() + ); + } + { + RoughLocation loc({ 0, 2, 0 }, { 0, 5, 0 }); + AssertEqual( + "relative of rough location with positive base", + RoughLocation::Fine(0, 21, 0), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 2, 0 }, { 0.0f, 5.0f, 0.0f }); + AssertEqual( + "relative of exact location with positive base", + ExactLocation::Fine(0.0f, 21.0f, 0.0f), loc.Relative(base).Absolute() + ); + } + { + RoughLocation loc({ 0, 0, -2 }, { 0, 0, 5 }); + AssertEqual( + "relative of rough negative location with positive base", + RoughLocation::Fine(0, -16, -27), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 0, -2 }, { 0.0f, 0.0f, 5.0f }); + AssertEqual( + "relative of exact negative location with positive base", + ExactLocation::Fine(0.0f, -16.0f, -27.0f), loc.Relative(base).Absolute() + ); + } + + base = glm::ivec3(-2, 0, 0); + { + RoughLocation loc({ 0, 0, 0 }, { 0, 0, 0 }); + AssertEqual( + "relative of rough zero location with negative base", + RoughLocation::Fine(32, 0, 0), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + AssertEqual( + "relative of exact zero location with negative base", + ExactLocation::Fine(32.0f, 0.0f, 0.0f), loc.Relative(base).Absolute() + ); + } + { + RoughLocation loc({ 0, 2, 0 }, { 0, 5, 0 }); + AssertEqual( + "relative of rough location with negative base", + RoughLocation::Fine(32, 37, 0), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 2, 0 }, { 0.0f, 5.0f, 0.0f }); + AssertEqual( + "relative of exact location with negative base", + ExactLocation::Fine(32.0f, 37.0f, 0.0f), loc.Relative(base).Absolute() + ); + } + { + RoughLocation loc({ 0, 0, -2 }, { 0, 0, 5 }); + AssertEqual( + "relative of rough negative location with negative base", + RoughLocation::Fine(32, 0, -27), loc.Relative(base).Absolute() + ); + } + { + ExactLocation loc({ 0, 0, -2 }, { 0.0f, 0.0f, 5.0f }); + AssertEqual( + "relative of exact negative location with negative base", + ExactLocation::Fine(32.0f, 0.0f, -27.0f), loc.Relative(base).Absolute() + ); + } +} + +void LocationTest::testDifference() { + { + RoughLocation a({ 0, 0, 0 }, { 0, 0, 0 }); + RoughLocation b({ 0, 0, 0 }, { 0, 0, 0 }); + AssertEqual( + "difference between rough zero locations", + RoughLocation::Fine(0, 0, 0), a.Difference(b).Absolute() + ); + } + { + ExactLocation a({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + ExactLocation b({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + AssertEqual( + "difference between exact zero locations", + ExactLocation::Fine(0.0f, 0.0f, 0.0f), a.Difference(b).Absolute() + ); + } + { + RoughLocation a({ 0, 0, 0 }, { 5, 0, 0 }); + RoughLocation b({ 0, 0, 0 }, { 0, 0, 0 }); + AssertEqual( + "difference between rough locations", + RoughLocation::Fine(5, 0, 0), a.Difference(b).Absolute() + ); + } + { + ExactLocation a({ 0, 0, 0 }, { 5.0f, 0.0f, 0.0f }); + ExactLocation b({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + AssertEqual( + "difference between exact locations", + ExactLocation::Fine(5.0f, 0.0f, 0.0f), a.Difference(b).Absolute() + ); + } + { + RoughLocation a({ 0, 0, 0 }, { 0, 0, 0 }); + RoughLocation b({ 0, 0, 0 }, { 0, 5, 0 }); + AssertEqual( + "difference between rough locations", + RoughLocation::Fine(0, -5, 0), a.Difference(b).Absolute() + ); + } + { + ExactLocation a({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + ExactLocation b({ 0, 0, 0 }, { 0.0f, 5.0f, 0.0f }); + AssertEqual( + "difference between exact locations", + ExactLocation::Fine(0.0f, -5.0f, 0.0f), a.Difference(b).Absolute() + ); + } + { + RoughLocation a({ 0, 0, 0 }, { 0, 0, 0 }); + RoughLocation b({ 0, 0, 0 }, { 0, 0, -3 }); + AssertEqual( + "difference between rough locations", + RoughLocation::Fine(0, 0, 3), a.Difference(b).Absolute() + ); + } + { + ExactLocation a({ 0, 0, 0 }, { 0.0f, 0.0f, 0.0f }); + ExactLocation b({ 0, 0, 0 }, { 0.0f, 0.0f, -3.0f }); + AssertEqual( + "difference between exact locations", + ExactLocation::Fine(0.0f, 0.0f, 3.0f), a.Difference(b).Absolute() + ); + } + { + RoughLocation a({ 1, 0, -1 }, { 5, 14, 9 }); + RoughLocation b({ 0, 2, -1 }, { 3, 2, 0 }); + AssertEqual( + "difference between rough locations", + RoughLocation::Fine(18, -20, 9), a.Difference(b).Absolute() + ); + } + { + ExactLocation a({ 1, 0, -1 }, { 5.0f, 14.0f, 9.0f }); + ExactLocation b({ 0, 2, -1 }, { 3.0f, 2.0f, 0.0f }); + AssertEqual( + "difference between exact locations", + ExactLocation::Fine(18.0f, -20.0f, 9.0f), a.Difference(b).Absolute() + ); + } +} + + +void LocationTest::AssertEqual( + const std::string &msg, + const glm::ivec3 &expected, + const glm::ivec3 &actual +) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + msg + " X", + expected.x, actual.x + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + msg + " Y", + expected.y, actual.y + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + msg + " Z", + expected.z, actual.z + ); +} + +void LocationTest::AssertEqual( + const std::string &msg, + const glm::vec3 &expected, + const glm::vec3 &actual +) { + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + msg + " X", + expected.x, actual.x, std::numeric_limits::epsilon() + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + msg + " Y", + expected.y, actual.y, std::numeric_limits::epsilon() + ); + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( + msg + " Z", + expected.z, actual.z, std::numeric_limits::epsilon() + ); +} + +void LocationTest::AssertEqual( + const std::string &msg, + const RoughLocation &expected, + const RoughLocation &actual +) { + AssertEqual( + msg + ": bad chunk", + expected.chunk, actual.chunk + ); + AssertEqual( + msg + ": bad block", + expected.block, actual.block + ); +} + +void LocationTest::AssertEqual( + const std::string &msg, + const ExactLocation &expected, + const ExactLocation &actual +) { + AssertEqual( + msg + ": bad chunk", + expected.chunk, actual.chunk + ); + AssertEqual( + msg + ": bad block", + expected.block, actual.block + ); +} + +} +} diff --git a/tst/geometry/LocationTest.hpp b/tst/geometry/LocationTest.hpp new file mode 100644 index 0000000..d46be0b --- /dev/null +++ b/tst/geometry/LocationTest.hpp @@ -0,0 +1,58 @@ +#ifndef BLANK_TEST_GEOMETRY_LOCATIONTEST_HPP_ +#define BLANK_TEST_GEOMETRY_LOCATIONTEST_HPP_ + +#include "geometry/Location.hpp" + +#include +#include +#include + + +namespace blank { +namespace test { + +class LocationTest +: public CppUnit::TestFixture { + +CPPUNIT_TEST_SUITE(LocationTest); + +CPPUNIT_TEST(testSanitize); +CPPUNIT_TEST(testAbsolute); +CPPUNIT_TEST(testRelative); +CPPUNIT_TEST(testDifference); + +CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testSanitize(); + void testAbsolute(); + void testRelative(); + void testDifference(); + +private: + static void AssertEqual( + const std::string &msg, + const glm::ivec3 &expected, + const glm::ivec3 &actual); + static void AssertEqual( + const std::string &msg, + const glm::vec3 &expected, + const glm::vec3 &actual); + static void AssertEqual( + const std::string &msg, + const RoughLocation &expected, + const RoughLocation &actual); + static void AssertEqual( + const std::string &msg, + const ExactLocation &expected, + const ExactLocation &actual); + +}; + +} +} + +#endif diff --git a/tst/net/PacketTest.cpp b/tst/net/PacketTest.cpp index 695010d..86517ca 100644 --- a/tst/net/PacketTest.cpp +++ b/tst/net/PacketTest.cpp @@ -114,8 +114,7 @@ void PacketTest::testJoin() { Entity write_entity; write_entity.ID(534574); EntityState write_state; - write_state.chunk_pos = { 7, 2, -3 }; - write_state.block_pos = { 1.5f, 0.9f, 12.0f }; + write_state.pos = { { 7, 2, -3 }, { 1.5f, 0.9f, 12.0f } }; write_state.velocity = { 0.025f, 0.001f, 0.0f }; write_state.orient = { 1.0f, 0.0f, 0.0f, 0.0f }; write_state.pitch = 0.3f; @@ -164,8 +163,7 @@ void PacketTest::testPlayerUpdate() { AssertPacket("PlayerUpdate", 4, 50, pack); EntityState write_state; - write_state.chunk_pos = { 7, 2, -3 }; - write_state.block_pos = { 1.5f, 0.9f, 12.0f }; + write_state.pos = { { 7, 2, -3 }, { 1.5f, 0.9f, 12.0f } }; write_state.velocity = { 0.025f, 0.001f, 0.0f }; write_state.orient = { 1.0f, 0.0f, 0.0f, 0.0f }; glm::vec3 write_movement(0.5f, -1.0f, 1.0f); @@ -213,8 +211,7 @@ void PacketTest::testSpawnEntity() { model.Enumerate(); model.Instantiate(write_entity.GetModel()); EntityState write_state; - write_state.chunk_pos = { 7, 2, -3 }; - write_state.block_pos = { 1.5f, 0.9f, 12.0f }; + write_state.pos = { { 7, 2, -3 }, { 1.5f, 0.9f, 12.0f } }; write_state.velocity = { 0.025f, 0.001f, 0.0f }; write_state.pitch = 0.3f; write_state.yaw = -2.3f; @@ -304,8 +301,7 @@ void PacketTest::testEntityUpdate() { Entity write_entity; write_entity.ID(8567234); EntityState write_state; - write_state.chunk_pos = { 7, 2, -3 }; - write_state.block_pos = { 1.5f, 0.9f, 12.0f }; + write_state.pos = { { 7, 2, -3 }, { 1.5f, 0.9f, 12.0f } }; write_state.velocity = { 0.025f, 0.001f, 0.0f }; write_state.pitch = 0.3f; write_state.yaw = -2.3f; @@ -343,8 +339,7 @@ void PacketTest::testPlayerCorrection() { Entity write_entity; EntityState write_state; - write_state.chunk_pos = { 7, 2, -3 }; - write_state.block_pos = { 1.5f, 0.9f, 12.0f }; + write_state.pos = { { 7, 2, -3 }, { 1.5f, 0.9f, 12.0f } }; write_state.velocity = { 0.025f, 0.001f, 0.0f }; write_state.pitch = 0.3f; write_state.yaw = -2.3f; @@ -595,11 +590,11 @@ void PacketTest::AssertEqual( ) { AssertEqual( message + ": bad chunk position", - expected.chunk_pos, actual.chunk_pos + expected.pos.chunk, actual.pos.chunk ); AssertEqual( message + ": bad block position", - expected.block_pos, actual.block_pos, 16.0f/65535.0f // that's about the max accuracy that packing's going to give us + expected.pos.block, actual.pos.block, 16.0f/65535.0f // that's about the max accuracy that packing's going to give us ); AssertEqual( message + ": bad velocity", diff --git a/tst/world/ChunkTest.cpp b/tst/world/ChunkTest.cpp index c40f9da..46933e9 100644 --- a/tst/world/ChunkTest.cpp +++ b/tst/world/ChunkTest.cpp @@ -35,259 +35,259 @@ void ChunkTest::tearDown() { void ChunkTest::testBounds() { CPPUNIT_ASSERT_MESSAGE( "valid position out of bounds", - Chunk::InBounds(Chunk::Pos(0, 0, 0)) + Chunk::InBounds(RoughLocation::Fine(0, 0, 0)) ); CPPUNIT_ASSERT_MESSAGE( "valid position out of bounds", - Chunk::InBounds(Chunk::Pos(15, 0, 0)) + Chunk::InBounds(RoughLocation::Fine(15, 0, 0)) ); CPPUNIT_ASSERT_MESSAGE( "valid position out of bounds", - Chunk::InBounds(Chunk::Pos(0, 15, 0)) + Chunk::InBounds(RoughLocation::Fine(0, 15, 0)) ); CPPUNIT_ASSERT_MESSAGE( "valid position out of bounds", - Chunk::InBounds(Chunk::Pos(0, 0, 15)) + Chunk::InBounds(RoughLocation::Fine(0, 0, 15)) ); CPPUNIT_ASSERT_MESSAGE( "valid position out of bounds", - Chunk::InBounds(Chunk::Pos(15, 15, 15)) + Chunk::InBounds(RoughLocation::Fine(15, 15, 15)) ); CPPUNIT_ASSERT_MESSAGE( "invalid position in bounds", - !Chunk::InBounds(Chunk::Pos(-1, -1, -1)) + !Chunk::InBounds(RoughLocation::Fine(-1, -1, -1)) ); CPPUNIT_ASSERT_MESSAGE( "invalid position in bounds", - !Chunk::InBounds(Chunk::Pos(-1, 1, 0)) + !Chunk::InBounds(RoughLocation::Fine(-1, 1, 0)) ); CPPUNIT_ASSERT_MESSAGE( "invalid position in bounds", - !Chunk::InBounds(Chunk::Pos(16, -16, 0)) + !Chunk::InBounds(RoughLocation::Fine(16, -16, 0)) ); CPPUNIT_ASSERT_MESSAGE( "invalid position in bounds", - !Chunk::InBounds(Chunk::Pos(16, 16, 16)) + !Chunk::InBounds(RoughLocation::Fine(16, 16, 16)) ); } void ChunkTest::testBorder() { CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 0, 0)) + Chunk::IsBorder(RoughLocation::Fine(0, 0, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 0, 8)) + Chunk::IsBorder(RoughLocation::Fine(0, 0, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 0, 15)) + Chunk::IsBorder(RoughLocation::Fine(0, 0, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 8, 0)) + Chunk::IsBorder(RoughLocation::Fine(0, 8, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 8, 8)) + Chunk::IsBorder(RoughLocation::Fine(0, 8, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 8, 15)) + Chunk::IsBorder(RoughLocation::Fine(0, 8, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 15, 0)) + Chunk::IsBorder(RoughLocation::Fine(0, 15, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 15, 8)) + Chunk::IsBorder(RoughLocation::Fine(0, 15, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(0, 15, 15)) + Chunk::IsBorder(RoughLocation::Fine(0, 15, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 0, 0)) + Chunk::IsBorder(RoughLocation::Fine(8, 0, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 0, 8)) + Chunk::IsBorder(RoughLocation::Fine(8, 0, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 0, 15)) + Chunk::IsBorder(RoughLocation::Fine(8, 0, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 8, 0)) + Chunk::IsBorder(RoughLocation::Fine(8, 8, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position is border", - !Chunk::IsBorder(Chunk::Pos(8, 8, 8)) + !Chunk::IsBorder(RoughLocation::Fine(8, 8, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 8, 15)) + Chunk::IsBorder(RoughLocation::Fine(8, 8, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 15, 0)) + Chunk::IsBorder(RoughLocation::Fine(8, 15, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 15, 8)) + Chunk::IsBorder(RoughLocation::Fine(8, 15, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(8, 15, 15)) + Chunk::IsBorder(RoughLocation::Fine(8, 15, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 0, 0)) + Chunk::IsBorder(RoughLocation::Fine(15, 0, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 0, 8)) + Chunk::IsBorder(RoughLocation::Fine(15, 0, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 0, 15)) + Chunk::IsBorder(RoughLocation::Fine(15, 0, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 8, 0)) + Chunk::IsBorder(RoughLocation::Fine(15, 8, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 8, 8)) + Chunk::IsBorder(RoughLocation::Fine(15, 8, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 8, 15)) + Chunk::IsBorder(RoughLocation::Fine(15, 8, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 15, 0)) + Chunk::IsBorder(RoughLocation::Fine(15, 15, 0)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 15, 8)) + Chunk::IsBorder(RoughLocation::Fine(15, 15, 8)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::Pos(15, 15, 15)) + Chunk::IsBorder(RoughLocation::Fine(15, 15, 15)) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 0, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 0, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 0, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 0, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 0, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 0, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 8, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 8, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 8, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 8, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 8, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 8, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 15, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 15, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 15, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 15, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 15, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(0, 15, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 0, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 0, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 0, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 0, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 0, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 0, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 8, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 8, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position is border", - !Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 8, 8))) + !Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 8, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 8, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 8, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 15, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 15, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 15, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 15, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 15, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(8, 15, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 0, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 0, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 0, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 0, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 0, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 0, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 8, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 8, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 8, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 8, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 8, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 8, 15))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 15, 0))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 15, 0))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 15, 8))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 15, 8))) ); CPPUNIT_ASSERT_MESSAGE( "position not border", - Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 15, 15))) + Chunk::IsBorder(Chunk::ToIndex(RoughLocation::Fine(15, 15, 15))) ); } @@ -384,139 +384,139 @@ void ChunkTest::testLightPropagation() { chunk->ScanLights(); // 0 air, 1 solid, 2 solid and emits light level of 5 - chunk->SetBlock(Chunk::Pos(7, 7, 7), Block(2)); + chunk->SetBlock(RoughLocation::Fine(7, 7, 7), Block(2)); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding luminant block did not set correct light level", - 5, chunk->GetLight(Chunk::Pos(7, 7, 7)) + 5, chunk->GetLight(RoughLocation::Fine(7, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in +X", - 4, chunk->GetLight(Chunk::Pos(8, 7, 7)) + 4, chunk->GetLight(RoughLocation::Fine(8, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in -X", - 4, chunk->GetLight(Chunk::Pos(6, 7, 7)) + 4, chunk->GetLight(RoughLocation::Fine(6, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in +Y", - 4, chunk->GetLight(Chunk::Pos(7, 8, 7)) + 4, chunk->GetLight(RoughLocation::Fine(7, 8, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in -Y", - 4, chunk->GetLight(Chunk::Pos(7, 6, 7)) + 4, chunk->GetLight(RoughLocation::Fine(7, 6, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in +Z", - 4, chunk->GetLight(Chunk::Pos(7, 7, 8)) + 4, chunk->GetLight(RoughLocation::Fine(7, 7, 8)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in -Z", - 4, chunk->GetLight(Chunk::Pos(7, 7, 6)) + 4, chunk->GetLight(RoughLocation::Fine(7, 7, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in 2D diagonal", - 3, chunk->GetLight(Chunk::Pos(8, 8, 7)) + 3, chunk->GetLight(RoughLocation::Fine(8, 8, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in 2D diagonal", - 3, chunk->GetLight(Chunk::Pos(7, 6, 8)) + 3, chunk->GetLight(RoughLocation::Fine(7, 6, 8)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in 2D diagonal", - 3, chunk->GetLight(Chunk::Pos(6, 7, 8)) + 3, chunk->GetLight(RoughLocation::Fine(6, 7, 8)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in 3D diagonal", - 2, chunk->GetLight(Chunk::Pos(8, 6, 6)) + 2, chunk->GetLight(RoughLocation::Fine(8, 6, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in 3D diagonal", - 2, chunk->GetLight(Chunk::Pos(6, 6, 8)) + 2, chunk->GetLight(RoughLocation::Fine(6, 6, 8)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "light did not propagate correctly in 3D diagonal", - 2, chunk->GetLight(Chunk::Pos(6, 8, 8)) + 2, chunk->GetLight(RoughLocation::Fine(6, 8, 8)) ); // now block the light to the left - chunk->SetBlock(Chunk::Pos(6, 7, 7), Block(1)); + chunk->SetBlock(RoughLocation::Fine(6, 7, 7), Block(1)); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 5, chunk->GetLight(Chunk::Pos(7, 7, 7)) + 5, chunk->GetLight(RoughLocation::Fine(7, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 4, chunk->GetLight(Chunk::Pos(8, 7, 7)) + 4, chunk->GetLight(RoughLocation::Fine(8, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 4, chunk->GetLight(Chunk::Pos(7, 8, 7)) + 4, chunk->GetLight(RoughLocation::Fine(7, 8, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 4, chunk->GetLight(Chunk::Pos(7, 6, 7)) + 4, chunk->GetLight(RoughLocation::Fine(7, 6, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 4, chunk->GetLight(Chunk::Pos(7, 7, 8)) + 4, chunk->GetLight(RoughLocation::Fine(7, 7, 8)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 4, chunk->GetLight(Chunk::Pos(7, 7, 6)) + 4, chunk->GetLight(RoughLocation::Fine(7, 7, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 3, chunk->GetLight(Chunk::Pos(6, 6, 7)) + 3, chunk->GetLight(RoughLocation::Fine(6, 6, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 3, chunk->GetLight(Chunk::Pos(6, 8, 7)) + 3, chunk->GetLight(RoughLocation::Fine(6, 8, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 3, chunk->GetLight(Chunk::Pos(6, 7, 6)) + 3, chunk->GetLight(RoughLocation::Fine(6, 7, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 3, chunk->GetLight(Chunk::Pos(6, 7, 6)) + 3, chunk->GetLight(RoughLocation::Fine(6, 7, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 2, chunk->GetLight(Chunk::Pos(5, 6, 7)) + 2, chunk->GetLight(RoughLocation::Fine(5, 6, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 2, chunk->GetLight(Chunk::Pos(5, 8, 7)) + 2, chunk->GetLight(RoughLocation::Fine(5, 8, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 2, chunk->GetLight(Chunk::Pos(5, 7, 6)) + 2, chunk->GetLight(RoughLocation::Fine(5, 7, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle affected unrelated index", - 2, chunk->GetLight(Chunk::Pos(5, 7, 6)) + 2, chunk->GetLight(RoughLocation::Fine(5, 7, 6)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "adding obstacle resulted in unexpected light level behind it", - 1, chunk->GetLight(Chunk::Pos(5, 7, 7)) + 1, chunk->GetLight(RoughLocation::Fine(5, 7, 7)) ); // and remove it again - chunk->SetBlock(Chunk::Pos(6, 7, 7), Block(0)); + chunk->SetBlock(RoughLocation::Fine(6, 7, 7), Block(0)); CPPUNIT_ASSERT_EQUAL_MESSAGE( "removing obstacle did not refill light correctly", - 4, chunk->GetLight(Chunk::Pos(6, 7, 7)) + 4, chunk->GetLight(RoughLocation::Fine(6, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "removing obstacle did not refill light correctly", - 3, chunk->GetLight(Chunk::Pos(5, 7, 7)) + 3, chunk->GetLight(RoughLocation::Fine(5, 7, 7)) ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "removing obstacle did not refill light correctly", - 2, chunk->GetLight(Chunk::Pos(4, 7, 7)) + 2, chunk->GetLight(RoughLocation::Fine(4, 7, 7)) ); }