// 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) {
// 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));
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);
}
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);
}
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?
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;
}
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;
}
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);
--- /dev/null
+#ifndef BLANK_GEOMETRY_LOCATION_HPP_
+#define BLANK_GEOMETRY_LOCATION_HPP_
+
+#include <glm/glm.hpp>
+
+
+namespace blank {
+
+template<class T>
+struct Location {
+
+ using Coarse = glm::ivec3;
+ using CoarseScalar = int;
+ using Fine = glm::tvec3<T>;
+ using FineScalar = T;
+ using Self = Location<T>;
+
+
+ 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<class T>
+inline Location<T> &Location<T>::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<class T>
+inline Location<T> &Location<T>::Sanitize() noexcept {
+ Coarse diff = Coarse(block) / Extent();
+ chunk += diff;
+ block -= diff * Extent();
+ // may leave negative coordinates in block
+ return Correct();
+}
+
+using ExactLocation = Location<float>;
+using RoughLocation = Location<int>;
+
+}
+
+#endif
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") {
}
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;
}
-bool WorldSave::Exists(const Chunk::Pos &pos) const noexcept {
+bool WorldSave::Exists(const ExactLocation::Coarse &pos) const noexcept {
return is_file(ChunkPath(pos));
}
}
-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();
}
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;
}
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);
}
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);
}
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;
}
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()) {
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);
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);
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);
}
struct Block {
using Type = unsigned short;
- using Pos = glm::vec3;
enum Face {
FACE_UP,
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()); }
private:
Chunk *chunk;
- Chunk::Pos pos;
+ RoughLocation::Fine pos;
};
#include "Block.hpp"
#include "BlockTypeRegistry.hpp"
+#include "../geometry/Location.hpp"
#include "../geometry/primitive.hpp"
#include <vector>
/// 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]; }
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,
const glm::mat4 &Mchunk,
std::vector<WorldCollision> &) 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]; }
bool generated;
bool lighted;
- Pos position;
+ ExactLocation::Coarse position;
int ref_count;
bool dirty_mesh;
bool dirty_save;
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]; }
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;
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;
private:
ChunkStore &store;
- Chunk::Pos base;
+ ExactLocation::Coarse base;
int extent;
int side_length;
int total_length;
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<Chunk>::iterator begin() noexcept { return loaded.begin(); }
std::list<Chunk>::iterator end() noexcept { return loaded.end(); }
/// 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();
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();
/// 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; }
#ifndef BLANK_WORLD_ENTITYSTATE_HPP_
#define BLANK_WORLD_ENTITYSTATE_HPP_
-#include "Chunk.hpp"
+#include "../geometry/Location.hpp"
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
struct EntityState {
- glm::ivec3 chunk_pos;
- glm::vec3 block_pos;
+ ExactLocation pos;
glm::vec3 velocity;
glm::quat orient;
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
}
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)));
}
}
}
bool Intersection(
const Ray &,
const glm::mat4 &M,
- const Chunk::Pos &reference,
+ const ExactLocation::Coarse &reference,
WorldCollision &);
/// check if this ray hits an entity
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); }
};
namespace blank {
-constexpr int Chunk::width;
-constexpr int Chunk::height;
-constexpr int Chunk::depth;
+constexpr int Chunk::side;
constexpr int Chunk::size;
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); }
int level;
- UnsetNode(Chunk *chunk, Chunk::Pos pos)
+ UnsetNode(Chunk *chunk, RoughLocation::Fine pos)
: SetNode(chunk, pos), level(Get()) { }
UnsetNode(const SetNode &set)
} 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) {
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);
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);
}
-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;
coll.chunk = this;
coll.block = -1;
coll.depth = std::numeric_limits<float>::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;
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;
}
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;
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) {
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;
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;
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;
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;
}
}
-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);
}
}
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?
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;
}
-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)
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;
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)
+ 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;
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 {
}
}
-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 {
}
}
-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
}
}
-Chunk::Pos ChunkIndex::NextMissing() noexcept {
+ExactLocation::Coarse ChunkIndex::NextMissing() noexcept {
if (MissingChunks() > 0) {
int roundtrip = last_missing;
last_missing = (last_missing + 1) % total_length;
}
-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();
}
}
}
-ChunkIndex *ChunkStore::ClosestIndex(const Chunk::Pos &pos) {
+ChunkIndex *ChunkStore::ClosestIndex(const ExactLocation::Coarse &pos) {
ChunkIndex *closest_index = nullptr;
int closest_distance = std::numeric_limits<int>::max();
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) {
return nullptr;
}
-Chunk *ChunkStore::Allocate(const Chunk::Pos &pos) {
+Chunk *ChunkStore::Allocate(const ExactLocation::Coarse &pos) {
Chunk *chunk = Get(pos);
if (chunk) {
return chunk;
}
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);
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() {
}
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();
}
}
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]) };
}
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)
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)
}
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 {
bool World::Intersection(
const Ray &ray,
const glm::mat4 &M,
- const Chunk::Pos &reference,
+ const ExactLocation::Coarse &reference,
WorldCollision &coll
) {
candidates.clear();
bool World::Intersection(const Entity &e, const EntityState &s, std::vector<WorldCollision> &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);
}
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();
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();
--- /dev/null
+#include "LocationTest.hpp"
+
+#include <limits>
+#include <glm/gtx/io.hpp>
+
+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<float>::epsilon()
+ );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ msg + " Y",
+ expected.y, actual.y, std::numeric_limits<float>::epsilon()
+ );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ msg + " Z",
+ expected.z, actual.z, std::numeric_limits<float>::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
+ );
+}
+
+}
+}
--- /dev/null
+#ifndef BLANK_TEST_GEOMETRY_LOCATIONTEST_HPP_
+#define BLANK_TEST_GEOMETRY_LOCATIONTEST_HPP_
+
+#include "geometry/Location.hpp"
+
+#include <string>
+#include <glm/glm.hpp>
+#include <cppunit/extensions/HelperMacros.h>
+
+
+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
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;
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);
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;
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;
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;
) {
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",
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)))
);
}
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))
);
}