#include "Generator.hpp"
#include "WorldCollision.hpp"
-#include "WorldSave.hpp"
+#include "../io/WorldSave.hpp"
#include <algorithm>
#include <limits>
, neighbor{0}
, blocks{}
, light{0}
-, model()
, position(0, 0, 0)
, dirty_model(false)
, dirty_save(false) {
Chunk::Chunk(Chunk &&other) noexcept
: types(other.types)
-, model(std::move(other.model))
, position(other.position)
, dirty_model(other.dirty_model)
, dirty_save(other.dirty_save) {
std::copy(other.neighbor, other.neighbor + sizeof(neighbor), neighbor);
std::copy(other.blocks, other.blocks + sizeof(blocks), blocks);
std::copy(other.light, other.light + sizeof(light), light);
- model = std::move(other.model);
position = other.position;
dirty_model = other.dirty_save;
dirty_save = other.dirty_save;
}
-void Chunk::Draw() noexcept {
- if (ShouldUpdateModel()) {
- Update();
- }
- model.Draw();
-}
-
-
bool Chunk::Intersection(
const Ray &ray,
const glm::mat4 &M,
- int &blkid,
- float &dist,
- glm::vec3 &normal
-) const noexcept {
+ WorldCollision &coll
+) noexcept {
int idx = 0;
- blkid = -1;
- dist = std::numeric_limits<float>::infinity();
+ 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) {
float cur_dist;
glm::vec3 cur_norm;
if (type.shape->Intersects(ray, M * ToTransform(Pos(x, y, z), idx), cur_dist, cur_norm)) {
- if (cur_dist < dist) {
- blkid = idx;
- dist = cur_dist;
- normal = cur_norm;
+ if (cur_dist < coll.depth) {
+ coll.block = idx;
+ coll.depth = cur_dist;
+ coll.normal = cur_norm;
}
}
}
}
}
- if (blkid < 0) {
+ if (coll.block < 0) {
return false;
} else {
- normal = glm::vec3(BlockAt(blkid).Transform() * glm::vec4(normal, 0.0f));
+ coll.normal = glm::vec3(BlockAt(coll.block).Transform() * glm::vec4(coll.normal, 0.0f));
return true;
}
}
const glm::mat4 &Mbox,
const glm::mat4 &Mchunk,
std::vector<WorldCollision> &col
-) const noexcept {
+) noexcept {
bool any = false;
float penetration;
glm::vec3 normal;
}
-void Chunk::CheckUpdate() noexcept {
- if (ShouldUpdateModel()) {
- Update();
- }
-}
-
-void Chunk::Update() noexcept {
+void Chunk::Update(BlockModel &model) noexcept {
int vtx_count = 0, idx_count = 0;
for (const auto &block : blocks) {
const Shape *shape = Type(block).shape;
++next;
// unlink neighbors so they won't reference a dead chunk
chunk->ClearNeighbors();
+ // if it should be saved, do it now
+ if (chunk->ShouldUpdateSave()) {
+ save.Write(*chunk);
+ }
// and move it from loaded to free list
to_free.splice(to_free.end(), loaded, chunk);
return next;
}
void ChunkLoader::Update(int dt) {
- // check if a chunk generation is scheduled for this frame
- // and if there's a chunk waiting to be generated
+ // check if a chunk load is scheduled for this frame
+ // and if there's chunks waiting to be loaded
gen_timer.Update(dt);
if (gen_timer.Hit()) {
- LoadOne();
+ // we may
+ // load until one of load or generation limits was hit
+ constexpr int max_load = 10;
+ constexpr int max_gen = 1;
+ int loaded = 0;
+ int generated = 0;
+ while (!to_load.empty() && loaded < max_load && generated < max_gen) {
+ if (LoadOne()) {
+ ++generated;
+ } else {
+ ++loaded;
+ }
+ }
}
constexpr int max_save = 10;
}
}
-void ChunkLoader::LoadOne() {
- if (to_load.empty()) return;
+bool ChunkLoader::LoadOne() {
+ if (to_load.empty()) return false;
// take position of next chunk in queue
Chunk::Pos pos(to_load.front());
if (iter->Position() == pos) {
loaded.splice(loaded.end(), to_free, iter);
Insert(loaded.back());
- return;
+ return false;
}
}
loaded.splice(loaded.end(), to_free, to_free.begin());
}
+ bool generated = false;
Chunk &chunk = loaded.back();
chunk.Position(pos);
if (save.Exists(pos)) {
save.Read(chunk);
} else {
gen(chunk);
+ generated = true;
}
Insert(chunk);
+ return generated;
}
}