2020-07-10 17:49:16 +00:00
|
|
|
#include "Chunk.hpp"
|
|
|
|
|
|
|
|
#include "materials.hpp"
|
2020-07-31 17:09:44 +00:00
|
|
|
#include <algorithm>
|
2020-08-02 20:15:53 +00:00
|
|
|
#include "../data/math.hpp"
|
2020-07-10 17:49:16 +00:00
|
|
|
|
2020-07-25 16:45:03 +00:00
|
|
|
using namespace world;
|
|
|
|
|
2020-07-31 23:17:09 +00:00
|
|
|
constexpr auto DENSITY = 0.f;
|
|
|
|
constexpr auto GRANULARITY = 30.f;
|
2020-07-10 17:49:16 +00:00
|
|
|
|
|
|
|
Chunk::Chunk(const chunk_pos& pos, Generator& rnd) {
|
|
|
|
const auto [densitySet, materialSet] = rnd.getChunk(pos, CHUNK_LENGTH);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < CHUNK_SIZE; i++) {
|
2020-08-02 09:47:25 +00:00
|
|
|
const auto density = std::clamp((densitySet[i] + DENSITY) * GRANULARITY, 0.f, 1.f) * Voxel::DENSITY_MAX;
|
|
|
|
const auto material = density > 0 ? 1 + std::clamp(static_cast<int>(std::lrint((materialSet[i] + 1) / 2 * (materials::count - 2))),
|
2020-07-25 14:29:05 +00:00
|
|
|
0, materials::count - 2) : 0; //NOTE: map (approx -1, 1) to (1, mat_max)
|
2020-08-02 09:47:25 +00:00
|
|
|
voxels[i] = Voxel(material, density);
|
2020-07-10 17:49:16 +00:00
|
|
|
}
|
2020-08-01 21:31:01 +00:00
|
|
|
rnd.free(densitySet);
|
|
|
|
rnd.free(materialSet);
|
2020-07-10 17:49:16 +00:00
|
|
|
}
|
2020-08-02 20:15:53 +00:00
|
|
|
#include <iostream>
|
2020-08-02 09:47:25 +00:00
|
|
|
Chunk::Chunk(std::istream& str, bool rle) {
|
|
|
|
if(rle) {
|
|
|
|
ushort i = 0;
|
|
|
|
while(!str.eof()) {
|
|
|
|
ushort count;
|
|
|
|
Voxel voxel;
|
|
|
|
str.read(reinterpret_cast<char *>(&count), sizeof(count));
|
|
|
|
str.read(reinterpret_cast<char *>(&voxel), sizeof(voxel));
|
|
|
|
str.peek();
|
|
|
|
for (; count > 0; count--) {
|
|
|
|
voxels[i] = voxel;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2020-08-02 20:15:53 +00:00
|
|
|
assert(i == CHUNK_SIZE && "Mismatch data length");
|
2020-08-02 09:47:25 +00:00
|
|
|
} else {
|
|
|
|
for(auto& voxel: voxels) {
|
|
|
|
str.read(reinterpret_cast<char *>(&voxel), sizeof(voxel));
|
2020-07-26 20:53:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-10 17:49:16 +00:00
|
|
|
Chunk::~Chunk() { }
|
|
|
|
|
2020-08-02 09:47:25 +00:00
|
|
|
void Chunk::write(std::ostream& str, bool rle) const {
|
|
|
|
if (rle) {
|
|
|
|
const auto *it = voxels.begin();
|
|
|
|
ushort counter = 1;
|
|
|
|
Voxel current = *it;
|
|
|
|
while(true) {
|
2020-08-02 20:15:53 +00:00
|
|
|
++it;
|
2020-08-02 09:47:25 +00:00
|
|
|
const auto end = (it == voxels.end());
|
|
|
|
if(end || current.value != it->value) {
|
|
|
|
str.write(reinterpret_cast<char *>(&counter), sizeof(counter));
|
|
|
|
str.write(reinterpret_cast<char *>(¤t), sizeof(current));
|
|
|
|
if(end)
|
|
|
|
break;
|
2020-07-26 20:53:14 +00:00
|
|
|
|
2020-08-02 09:47:25 +00:00
|
|
|
current = *it;
|
|
|
|
counter = 1;
|
|
|
|
} else {
|
|
|
|
counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for(auto current: voxels) {
|
|
|
|
str.write(reinterpret_cast<char *>(¤t), sizeof(current));
|
2020-07-26 20:53:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-25 14:29:05 +00:00
|
|
|
std::optional<Faces> Chunk::update() {
|
2020-07-10 17:49:16 +00:00
|
|
|
if(upToDate) {
|
2020-07-25 14:29:05 +00:00
|
|
|
return {};
|
2020-07-10 17:49:16 +00:00
|
|
|
} else {
|
|
|
|
upToDate = true;
|
2020-07-25 14:29:05 +00:00
|
|
|
return {toUpdate};
|
2020-07-10 17:49:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-25 16:45:03 +00:00
|
|
|
void Chunk::set(ushort idx, const Voxel& val) {
|
|
|
|
voxels[idx] = val;
|
|
|
|
invalidate(
|
|
|
|
((!getNeighborIdx(idx, Face::Up).has_value()) & Faces::Up) |
|
|
|
|
((!getNeighborIdx(idx, Face::Down).has_value()) & Faces::Down) |
|
|
|
|
((!getNeighborIdx(idx, Face::Left).has_value()) & Faces::Left) |
|
|
|
|
((!getNeighborIdx(idx, Face::Right).has_value()) & Faces::Right) |
|
|
|
|
((!getNeighborIdx(idx, Face::Forward).has_value()) & Faces::Forward) |
|
|
|
|
((!getNeighborIdx(idx, Face::Backward).has_value()) & Faces::Backward));
|
|
|
|
}
|
|
|
|
|
2020-08-02 20:15:53 +00:00
|
|
|
std::optional<chunk_voxel_idx> Chunk::getNeighborIdx(chunk_voxel_idx idx, Face dir) {
|
2020-07-31 23:17:09 +00:00
|
|
|
switch (dir) {
|
2020-07-10 17:49:16 +00:00
|
|
|
case Face::Forward:
|
2020-08-02 20:15:53 +00:00
|
|
|
if (idx % glm::IDX_LENGTH >= glm::IDX_LENGTH - 1)
|
2020-07-10 17:49:16 +00:00
|
|
|
return {};
|
|
|
|
return idx + 1;
|
|
|
|
|
|
|
|
case Face::Backward:
|
2020-08-02 20:15:53 +00:00
|
|
|
if (idx % glm::IDX_LENGTH <= 0)
|
2020-07-10 17:49:16 +00:00
|
|
|
return {};
|
|
|
|
return idx - 1;
|
|
|
|
|
|
|
|
case Face::Up:
|
2020-08-02 20:15:53 +00:00
|
|
|
if ((idx / glm::IDX_LENGTH) % glm::IDX_LENGTH >= glm::IDX_LENGTH - 1)
|
2020-07-10 17:49:16 +00:00
|
|
|
return {};
|
2020-08-02 20:15:53 +00:00
|
|
|
return idx + glm::IDX_LENGTH;
|
2020-07-10 17:49:16 +00:00
|
|
|
|
|
|
|
case Face::Down:
|
2020-08-02 20:15:53 +00:00
|
|
|
if ((idx / glm::IDX_LENGTH) % glm::IDX_LENGTH <= 0)
|
2020-07-10 17:49:16 +00:00
|
|
|
return {};
|
2020-08-02 20:15:53 +00:00
|
|
|
return idx - glm::IDX_LENGTH;
|
2020-07-10 17:49:16 +00:00
|
|
|
|
|
|
|
case Face::Right:
|
2020-08-02 20:15:53 +00:00
|
|
|
if (idx / glm::IDX_LENGTH2 >= glm::IDX_LENGTH - 1)
|
2020-07-10 17:49:16 +00:00
|
|
|
return {};
|
2020-08-02 20:15:53 +00:00
|
|
|
return idx + glm::IDX_LENGTH2;
|
2020-07-10 17:49:16 +00:00
|
|
|
|
|
|
|
case Face::Left:
|
2020-08-02 20:15:53 +00:00
|
|
|
if (idx / glm::IDX_LENGTH2 <= 0)
|
2020-07-10 17:49:16 +00:00
|
|
|
return {};
|
2020-08-02 20:15:53 +00:00
|
|
|
return idx - glm::IDX_LENGTH2;
|
2020-07-10 17:49:16 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|