add AreaMap2D
This commit is contained in:
parent
f70ac5c190
commit
c3569b5dd4
@ -84,7 +84,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
return L"frustum-culling: "+std::wstring(culling ? L"on" : L"off");
|
return L"frustum-culling: "+std::wstring(culling ? L"on" : L"off");
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([=]() {
|
panel->add(create_label([=]() {
|
||||||
return L"chunks: "+std::to_wstring(level->chunks->chunksCount)+
|
return L"chunks: "+std::to_wstring(level->chunks->getChunksCount())+
|
||||||
L" visible: "+std::to_wstring(level->chunks->visible);
|
L" visible: "+std::to_wstring(level->chunks->visible);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([=]() {
|
panel->add(create_label([=]() {
|
||||||
|
|||||||
@ -79,7 +79,7 @@ WorldRenderer::~WorldRenderer() = default;
|
|||||||
bool WorldRenderer::drawChunk(
|
bool WorldRenderer::drawChunk(
|
||||||
size_t index, Camera* camera, Shader* shader, bool culling
|
size_t index, Camera* camera, Shader* shader, bool culling
|
||||||
) {
|
) {
|
||||||
auto chunk = level->chunks->chunks[index];
|
auto chunk = level->chunks->getChunks()[index];
|
||||||
if (!chunk->flags.lighted) {
|
if (!chunk->flags.lighted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -122,15 +122,16 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
|||||||
// [warning] this whole method is not thread-safe for chunks
|
// [warning] this whole method is not thread-safe for chunks
|
||||||
|
|
||||||
std::vector<size_t> indices;
|
std::vector<size_t> indices;
|
||||||
for (size_t i = 0; i < chunks->volume; i++) {
|
for (size_t i = 0; i < chunks->getVolume(); i++) {
|
||||||
if (chunks->chunks[i] == nullptr) continue;
|
if (chunks->getChunks()[i] == nullptr) continue;
|
||||||
indices.emplace_back(i);
|
indices.emplace_back(i);
|
||||||
}
|
}
|
||||||
float px = camera->position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
float px = camera->position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
||||||
float pz = camera->position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
float pz = camera->position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
||||||
std::sort(indices.begin(), indices.end(), [chunks, px, pz](auto i, auto j) {
|
std::sort(indices.begin(), indices.end(), [chunks, px, pz](auto i, auto j) {
|
||||||
const auto a = chunks->chunks[i].get();
|
const auto& chunksBuffer = chunks->getChunks();
|
||||||
const auto b = chunks->chunks[j].get();
|
const auto a = chunksBuffer[i].get();
|
||||||
|
const auto b = chunksBuffer[j].get();
|
||||||
auto adx = (a->x - px);
|
auto adx = (a->x - px);
|
||||||
auto adz = (a->z - pz);
|
auto adz = (a->z - pz);
|
||||||
auto bdx = (b->x - px);
|
auto bdx = (b->x - px);
|
||||||
|
|||||||
@ -23,8 +23,9 @@ Lighting::Lighting(const Content* content, Chunks* chunks)
|
|||||||
Lighting::~Lighting() = default;
|
Lighting::~Lighting() = default;
|
||||||
|
|
||||||
void Lighting::clear(){
|
void Lighting::clear(){
|
||||||
for (size_t index = 0; index < chunks->volume; index++){
|
const auto& chunks = this->chunks->getChunks();
|
||||||
auto chunk = chunks->chunks[index];
|
for (size_t index = 0; index < chunks.size(); index++){
|
||||||
|
auto chunk = chunks[index];
|
||||||
if (chunk == nullptr)
|
if (chunk == nullptr)
|
||||||
continue;
|
continue;
|
||||||
Lightmap& lightmap = chunk->lightmap;
|
Lightmap& lightmap = chunk->lightmap;
|
||||||
|
|||||||
@ -124,17 +124,16 @@ void BlocksController::randomTick(
|
|||||||
|
|
||||||
void BlocksController::randomTick(int tickid, int parts) {
|
void BlocksController::randomTick(int tickid, int parts) {
|
||||||
auto indices = level->content->getIndices();
|
auto indices = level->content->getIndices();
|
||||||
const int w = chunks->w;
|
const auto& size = chunks->getSize();
|
||||||
const int d = chunks->d;
|
|
||||||
int segments = 4;
|
int segments = 4;
|
||||||
|
|
||||||
for (uint z = padding; z < d - padding; z++) {
|
for (uint z = padding; z < size.y - padding; z++) {
|
||||||
for (uint x = padding; x < w - padding; x++) {
|
for (uint x = padding; x < size.x - padding; x++) {
|
||||||
int index = z * w + x;
|
int index = z * size.x + x;
|
||||||
if ((index + tickid) % parts != 0) {
|
if ((index + tickid) % parts != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto& chunk = chunks->chunks[index];
|
auto& chunk = chunks->getChunks()[index];
|
||||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,16 +52,15 @@ void ChunksController::update(int64_t maxDuration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ChunksController::loadVisible() {
|
bool ChunksController::loadVisible() {
|
||||||
const int w = chunks->w;
|
const auto& size = chunks->getSize();
|
||||||
const int d = chunks->d;
|
|
||||||
|
|
||||||
int nearX = 0;
|
int nearX = 0;
|
||||||
int nearZ = 0;
|
int nearZ = 0;
|
||||||
int minDistance = ((w - padding * 2) / 2) * ((w - padding * 2) / 2);
|
int minDistance = ((size.x - padding * 2) / 2) * ((size.y - padding * 2) / 2);
|
||||||
for (uint z = padding; z < d - padding; z++) {
|
for (uint z = padding; z < size.y - padding; z++) {
|
||||||
for (uint x = padding; x < w - padding; x++) {
|
for (uint x = padding; x < size.x - padding; x++) {
|
||||||
int index = z * w + x;
|
int index = z * size.x + x;
|
||||||
auto& chunk = chunks->chunks[index];
|
auto& chunk = chunks->getChunks()[index];
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
||||||
if (buildLights(chunk)) {
|
if (buildLights(chunk)) {
|
||||||
@ -70,8 +69,8 @@ bool ChunksController::loadVisible() {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int lx = x - w / 2;
|
int lx = x - size.x / 2;
|
||||||
int lz = z - d / 2;
|
int lz = z - size.y / 2;
|
||||||
int distance = (lx * lx + lz * lz);
|
int distance = (lx * lx + lz * lz);
|
||||||
if (distance < minDistance) {
|
if (distance < minDistance) {
|
||||||
minDistance = distance;
|
minDistance = distance;
|
||||||
@ -81,14 +80,12 @@ bool ChunksController::loadVisible() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& chunk = chunks->chunks[nearZ * w + nearX];
|
const auto& chunk = chunks->getChunks()[nearZ * size.x + nearX];
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const auto& offset = chunks->getOffset();
|
||||||
const int ox = chunks->ox;
|
createChunk(nearX + offset.x, nearZ + offset.y);
|
||||||
const int oz = chunks->oz;
|
|
||||||
createChunk(nearX + ox, nearZ + oz);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
163
src/util/AreaMap2D.hpp
Normal file
163
src/util/AreaMap2D.hpp
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <functional>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
template<class T>
|
||||||
|
using OutCallback = std::function<void(const T&)>;
|
||||||
|
|
||||||
|
template<class T, typename TCoord=int>
|
||||||
|
class AreaMap2D {
|
||||||
|
glm::vec<2, TCoord> offset;
|
||||||
|
glm::vec<2, TCoord> size;
|
||||||
|
std::vector<T> firstBuffer;
|
||||||
|
std::vector<T> secondBuffer;
|
||||||
|
OutCallback<T> outCallback;
|
||||||
|
|
||||||
|
size_t valuesCount = 0;
|
||||||
|
|
||||||
|
void translate(const glm::vec<2, TCoord>& delta) {
|
||||||
|
if (delta.x == 0 && delta.y == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::fill(secondBuffer.begin(), secondBuffer.end(), T{});
|
||||||
|
for (TCoord y = 0; y < size.y; y++) {
|
||||||
|
for (TCoord x = 0; x < size.x; x++) {
|
||||||
|
auto& value = firstBuffer[y * size.x + x];
|
||||||
|
auto nx = x - delta.x;
|
||||||
|
auto ny = y - delta.y;
|
||||||
|
if (value == T{}) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nx < 0 || ny < 0 || nx >= size.x || ny >= size.y) {
|
||||||
|
if (outCallback) {
|
||||||
|
outCallback(value);
|
||||||
|
}
|
||||||
|
valuesCount--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
secondBuffer[ny * size.x + nx] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::swap(firstBuffer, secondBuffer);
|
||||||
|
offset += delta;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
AreaMap2D(glm::vec<2, TCoord> size)
|
||||||
|
: size(size),
|
||||||
|
firstBuffer(size.x * size.y), secondBuffer(size.x * size.y) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* getIf(const glm::vec<2, TCoord>& pos) const {
|
||||||
|
auto localPos = pos - offset;
|
||||||
|
if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x ||
|
||||||
|
localPos.y >= size.y) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &firstBuffer[localPos.y * size.x + localPos.x];
|
||||||
|
}
|
||||||
|
|
||||||
|
T get(const glm::vec<2, TCoord>& pos) {
|
||||||
|
auto localPos = pos - offset;
|
||||||
|
if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x ||
|
||||||
|
localPos.y >= size.y) {
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
return firstBuffer[localPos.y * size.x + localPos.x];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& require(const glm::vec<2, TCoord>& pos) const {
|
||||||
|
auto localPos = pos - offset;
|
||||||
|
if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x ||
|
||||||
|
localPos.y >= size.y) {
|
||||||
|
throw std::invalid_argument("position is out of window");
|
||||||
|
}
|
||||||
|
return firstBuffer[localPos.y * size.x + localPos.x];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool set(const glm::vec<2, TCoord>& pos, T value) {
|
||||||
|
auto localPos = pos - offset;
|
||||||
|
if (localPos.x < 0 || localPos.y < 0 || localPos.x >= size.x ||
|
||||||
|
localPos.y >= size.y) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto& element = firstBuffer[localPos.y * size.x + localPos.x];
|
||||||
|
if (!element) {
|
||||||
|
valuesCount++;
|
||||||
|
}
|
||||||
|
element = std::move(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOutCallback(const OutCallback<T>& callback) {
|
||||||
|
outCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(const glm::vec<2, TCoord>& newSize) {
|
||||||
|
if (newSize.x < size.x) {
|
||||||
|
TCoord delta = size.x - newSize.x;
|
||||||
|
translate({delta / 2, 0});
|
||||||
|
translate({-delta, 0});
|
||||||
|
translate({delta, 0});
|
||||||
|
}
|
||||||
|
if (newSize.y < size.y) {
|
||||||
|
TCoord delta = size.y - newSize.y;
|
||||||
|
translate({0, delta / 2});
|
||||||
|
translate({0, -delta});
|
||||||
|
translate({0, delta});
|
||||||
|
}
|
||||||
|
const TCoord newVolume = newSize.x * newSize.y;
|
||||||
|
std::vector<T> newFirstBuffer(newVolume);
|
||||||
|
std::vector<T> newSecondBuffer(newVolume);
|
||||||
|
for (TCoord y = 0; y < size.y && y < newSize.y; y++) {
|
||||||
|
for (TCoord x = 0; x < size.x && x < newSize.x; x++) {
|
||||||
|
newFirstBuffer[y * newSize.x + x] = firstBuffer[y * size.x + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size = newSize;
|
||||||
|
firstBuffer = std::move(newFirstBuffer);
|
||||||
|
secondBuffer = std::move(newSecondBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCenter(const glm::vec<2, TCoord>& center) {
|
||||||
|
auto delta = center - (offset + size / 2);
|
||||||
|
if (delta.x | delta.y) {
|
||||||
|
translate({delta.x, delta.y});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
for (TCoord i = 0; i < size.x * size.y; i++) {
|
||||||
|
auto value = firstBuffer[i];
|
||||||
|
firstBuffer[i] = {};
|
||||||
|
if (outCallback) {
|
||||||
|
outCallback(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
valuesCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec<2, TCoord>& getOffset() const {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec<2, TCoord>& getSize() const {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<T>& getBuffer() const {
|
||||||
|
return firstBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count() const {
|
||||||
|
return valuesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCoord area() const {
|
||||||
|
return size.x * size.y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -32,34 +32,31 @@ Chunks::Chunks(
|
|||||||
)
|
)
|
||||||
: level(level),
|
: level(level),
|
||||||
indices(level->content->getIndices()),
|
indices(level->content->getIndices()),
|
||||||
chunks(w * d),
|
areaMap({w, d}),
|
||||||
chunksSecond(w * d),
|
|
||||||
w(w),
|
|
||||||
d(d),
|
|
||||||
ox(ox),
|
|
||||||
oz(oz),
|
|
||||||
worldFiles(wfile) {
|
worldFiles(wfile) {
|
||||||
volume = static_cast<size_t>(w) * static_cast<size_t>(d);
|
areaMap.setCenter({ox-w/2, oz-d/2});
|
||||||
chunksCount = 0;
|
areaMap.setOutCallback([this](const auto& chunk) {
|
||||||
|
save(chunk.get());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
||||||
x -= ox * CHUNK_W;
|
if (y < 0 || y >= CHUNK_H) {
|
||||||
z -= oz * CHUNK_D;
|
|
||||||
int cx = floordiv(x, CHUNK_W);
|
|
||||||
int cy = floordiv(y, CHUNK_H);
|
|
||||||
int cz = floordiv(z, CHUNK_D);
|
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= int(w) || cy >= 1 || cz >= int(d)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto& chunk = chunks[cz * w + cx]; // not thread safe
|
int cx = floordiv(x, CHUNK_W);
|
||||||
|
int cz = floordiv(z, CHUNK_D);
|
||||||
|
auto ptr = areaMap.getIf({cx, cz});
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Chunk* chunk = ptr->get(); // not thread safe
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
int ly = y - cy * CHUNK_H;
|
|
||||||
int lz = z - cz * CHUNK_D;
|
int lz = z - cz * CHUNK_D;
|
||||||
return &chunk->voxels[(ly * CHUNK_D + lz) * CHUNK_W + lx];
|
return &chunk->voxels[(y * CHUNK_D + lz) * CHUNK_W + lx];
|
||||||
}
|
}
|
||||||
|
|
||||||
const AABB* Chunks::isObstacleAt(float x, float y, float z) {
|
const AABB* Chunks::isObstacleAt(float x, float y, float z) {
|
||||||
@ -114,61 +111,62 @@ bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) {
|
ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) {
|
||||||
x -= ox * CHUNK_W;
|
if (y < 0 || y >= CHUNK_H) {
|
||||||
z -= oz * CHUNK_D;
|
|
||||||
int cx = floordiv(x, CHUNK_W);
|
|
||||||
int cy = floordiv(y, CHUNK_H);
|
|
||||||
int cz = floordiv(z, CHUNK_D);
|
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= int(w) || cy >= 1 || cz >= int(d)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const auto& chunk = chunks[(cy * d + cz) * w + cx];
|
int cx = floordiv(x, CHUNK_W);
|
||||||
|
int cz = floordiv(z, CHUNK_D);
|
||||||
|
|
||||||
|
auto ptr = areaMap.getIf({cx, cz});
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Chunk* chunk = ptr->get();
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
int ly = y - cy * CHUNK_H;
|
|
||||||
int lz = z - cz * CHUNK_D;
|
int lz = z - cz * CHUNK_D;
|
||||||
return chunk->lightmap.get(lx, ly, lz, channel);
|
return chunk->lightmap.get(lx, y, lz, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) {
|
light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) {
|
||||||
x -= ox * CHUNK_W;
|
if (y < 0 || y >= CHUNK_H) {
|
||||||
z -= oz * CHUNK_D;
|
|
||||||
int cx = floordiv(x, CHUNK_W);
|
|
||||||
int cy = floordiv(y, CHUNK_H);
|
|
||||||
int cz = floordiv(z, CHUNK_D);
|
|
||||||
if (cx < 0 || cy < 0 || cz < 0 || cx >= int(w) || cy >= 1 || cz >= int(d)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const auto& chunk = chunks[(cy * d + cz) * w + cx];
|
int cx = floordiv(x, CHUNK_W);
|
||||||
|
int cz = floordiv(z, CHUNK_D);
|
||||||
|
|
||||||
|
auto ptr = areaMap.getIf({cx, cz});
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Chunk* chunk = ptr->get();
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lx = x - cx * CHUNK_W;
|
int lx = x - cx * CHUNK_W;
|
||||||
int ly = y - cy * CHUNK_H;
|
|
||||||
int lz = z - cz * CHUNK_D;
|
int lz = z - cz * CHUNK_D;
|
||||||
return chunk->lightmap.get(lx, ly, lz);
|
return chunk->lightmap.get(lx, y, lz);
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z) {
|
Chunk* Chunks::getChunkByVoxel(int32_t x, int32_t y, int32_t z) {
|
||||||
if (y < 0 || y >= CHUNK_H) return nullptr;
|
if (y < 0 || y >= CHUNK_H) {
|
||||||
x -= ox * CHUNK_W;
|
return nullptr;
|
||||||
z -= oz * CHUNK_D;
|
}
|
||||||
int cx = floordiv(x, CHUNK_W);
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cz = floordiv(z, CHUNK_D);
|
int cz = floordiv(z, CHUNK_D);
|
||||||
if (cx < 0 || cz < 0 || cx >= int(w) || cz >= int(d)) return nullptr;
|
if (auto ptr = areaMap.getIf({cx, cz})) {
|
||||||
return chunks[cz * w + cx].get();
|
return ptr->get();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk* Chunks::getChunk(int x, int z) {
|
Chunk* Chunks::getChunk(int x, int z) {
|
||||||
x -= ox;
|
if (auto ptr = areaMap.getIf({x, z})) {
|
||||||
z -= oz;
|
return ptr->get();
|
||||||
if (x < 0 || z < 0 || x >= static_cast<int>(w) ||
|
|
||||||
z >= static_cast<int>(d)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
return chunks[z * w + x].get();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::ivec3 Chunks::seekOrigin(
|
glm::ivec3 Chunks::seekOrigin(
|
||||||
@ -355,15 +353,13 @@ void Chunks::set(
|
|||||||
}
|
}
|
||||||
int32_t gx = x;
|
int32_t gx = x;
|
||||||
int32_t gz = z;
|
int32_t gz = z;
|
||||||
x -= ox * CHUNK_W;
|
|
||||||
z -= oz * CHUNK_D;
|
|
||||||
int cx = floordiv(x, CHUNK_W);
|
int cx = floordiv(x, CHUNK_W);
|
||||||
int cz = floordiv(z, CHUNK_D);
|
int cz = floordiv(z, CHUNK_D);
|
||||||
if (cx < 0 || cz < 0 || cx >= static_cast<int>(w) ||
|
auto ptr = areaMap.getIf({cx, cz});
|
||||||
cz >= static_cast<int>(d)) {
|
if (ptr == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Chunk* chunk = chunks[cz * w + cx].get();
|
Chunk* chunk = ptr->get();
|
||||||
if (chunk == nullptr) {
|
if (chunk == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -396,15 +392,18 @@ void Chunks::set(
|
|||||||
else if (id == 0)
|
else if (id == 0)
|
||||||
chunk->updateHeights();
|
chunk->updateHeights();
|
||||||
|
|
||||||
if (lx == 0 && (chunk = getChunk(cx + ox - 1, cz + oz)))
|
if (lx == 0 && (chunk = getChunk(cx - 1, cz))) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
if (lz == 0 && (chunk = getChunk(cx + ox, cz + oz - 1)))
|
}
|
||||||
|
if (lz == 0 && (chunk = getChunk(cx, cz - 1))) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
|
}
|
||||||
if (lx == CHUNK_W - 1 && (chunk = getChunk(cx + ox + 1, cz + oz)))
|
if (lx == CHUNK_W - 1 && (chunk = getChunk(cx, cz))) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
if (lz == CHUNK_D - 1 && (chunk = getChunk(cx + ox, cz + oz + 1)))
|
}
|
||||||
|
if (lz == CHUNK_D - 1 && (chunk = getChunk(cx, cz + 1))) {
|
||||||
chunk->flags.modified = true;
|
chunk->flags.modified = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
voxel* Chunks::rayCast(
|
voxel* Chunks::rayCast(
|
||||||
@ -643,97 +642,19 @@ glm::vec3 Chunks::rayCastToObstacle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::setCenter(int32_t x, int32_t z) {
|
void Chunks::setCenter(int32_t x, int32_t z) {
|
||||||
int cx = floordiv(x, CHUNK_W);
|
areaMap.setCenter({floordiv(x, CHUNK_W), floordiv(z, CHUNK_D)});
|
||||||
int cz = floordiv(z, CHUNK_D);
|
|
||||||
cx -= ox + w / 2;
|
|
||||||
cz -= oz + d / 2;
|
|
||||||
if (cx | cz) {
|
|
||||||
translate(cx, cz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunks::translate(int32_t dx, int32_t dz) {
|
|
||||||
for (uint i = 0; i < volume; i++) {
|
|
||||||
chunksSecond[i] = nullptr;
|
|
||||||
}
|
|
||||||
for (uint32_t z = 0; z < d; z++) {
|
|
||||||
for (uint32_t x = 0; x < w; x++) {
|
|
||||||
auto& chunk = chunks[z * w + x];
|
|
||||||
int nx = x - dx;
|
|
||||||
int nz = z - dz;
|
|
||||||
if (chunk == nullptr) continue;
|
|
||||||
if (nx < 0 || nz < 0 || nx >= static_cast<int>(w) ||
|
|
||||||
nz >= static_cast<int>(d)) {
|
|
||||||
level->events->trigger(EVT_CHUNK_HIDDEN, chunk.get());
|
|
||||||
save(chunk.get());
|
|
||||||
chunksCount--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
chunksSecond[nz * w + nx] = chunk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::swap(chunks, chunksSecond);
|
|
||||||
|
|
||||||
ox += dx;
|
|
||||||
oz += dz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::resize(uint32_t newW, uint32_t newD) {
|
void Chunks::resize(uint32_t newW, uint32_t newD) {
|
||||||
if (newW < w) {
|
areaMap.resize({newW, newD});
|
||||||
int delta = w - newW;
|
|
||||||
translate(delta / 2, 0);
|
|
||||||
translate(-delta, 0);
|
|
||||||
translate(delta, 0);
|
|
||||||
}
|
|
||||||
if (newD < d) {
|
|
||||||
int delta = d - newD;
|
|
||||||
translate(0, delta / 2);
|
|
||||||
translate(0, -delta);
|
|
||||||
translate(0, delta);
|
|
||||||
}
|
|
||||||
const int newVolume = newW * newD;
|
|
||||||
std::vector<std::shared_ptr<Chunk>> newChunks(newVolume);
|
|
||||||
std::vector<std::shared_ptr<Chunk>> newChunksSecond(newVolume);
|
|
||||||
for (int z = 0; z < static_cast<int>(d) && z < static_cast<int>(newD);
|
|
||||||
z++) {
|
|
||||||
for (int x = 0; x < static_cast<int>(w) && x < static_cast<int>(newW);
|
|
||||||
x++) {
|
|
||||||
newChunks[z * newW + x] = chunks[z * w + x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w = newW;
|
|
||||||
d = newD;
|
|
||||||
volume = newVolume;
|
|
||||||
chunks = std::move(newChunks);
|
|
||||||
chunksSecond = std::move(newChunksSecond);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunks::_setOffset(int32_t x, int32_t z) {
|
|
||||||
ox = x;
|
|
||||||
oz = z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Chunks::putChunk(const std::shared_ptr<Chunk>& chunk) {
|
bool Chunks::putChunk(const std::shared_ptr<Chunk>& chunk) {
|
||||||
int x = chunk->x;
|
return areaMap.set({chunk->x, chunk->z}, chunk);
|
||||||
int z = chunk->z;
|
|
||||||
x -= ox;
|
|
||||||
z -= oz;
|
|
||||||
if (x < 0 || z < 0 || x >= static_cast<int>(w) ||
|
|
||||||
z >= static_cast<int>(d)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
chunks[z * w + x] = chunk;
|
|
||||||
chunksCount++;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::saveAndClear() {
|
void Chunks::saveAndClear() {
|
||||||
for (size_t i = 0; i < volume; i++) {
|
areaMap.clear();
|
||||||
auto chunk = chunks[i].get();
|
|
||||||
chunks[i] = nullptr;
|
|
||||||
save(chunk);
|
|
||||||
}
|
|
||||||
chunksCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::save(Chunk* chunk) {
|
void Chunks::save(Chunk* chunk) {
|
||||||
@ -760,7 +681,8 @@ void Chunks::save(Chunk* chunk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunks::saveAll() {
|
void Chunks::saveAll() {
|
||||||
for (size_t i = 0; i < volume; i++) {
|
const auto& chunks = areaMap.getBuffer();
|
||||||
|
for (size_t i = 0; i < areaMap.area(); i++) {
|
||||||
if (auto& chunk = chunks[i]) {
|
if (auto& chunk = chunks[i]) {
|
||||||
save(chunk.get());
|
save(chunk.get());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "voxel.hpp"
|
#include "voxel.hpp"
|
||||||
|
#include "util/AreaMap2D.hpp"
|
||||||
|
|
||||||
class VoxelRenderer;
|
class VoxelRenderer;
|
||||||
|
|
||||||
@ -33,14 +34,10 @@ class Chunks {
|
|||||||
void setRotationExtended(
|
void setRotationExtended(
|
||||||
const Block& def, blockstate state, glm::ivec3 origin, uint8_t rotation
|
const Block& def, blockstate state, glm::ivec3 origin, uint8_t rotation
|
||||||
);
|
);
|
||||||
|
|
||||||
|
util::AreaMap2D<std::shared_ptr<Chunk>> areaMap;
|
||||||
public:
|
public:
|
||||||
std::vector<std::shared_ptr<Chunk>> chunks;
|
|
||||||
std::vector<std::shared_ptr<Chunk>> chunksSecond;
|
|
||||||
size_t volume;
|
|
||||||
size_t chunksCount;
|
|
||||||
size_t visible = 0;
|
size_t visible = 0;
|
||||||
uint32_t w, d;
|
|
||||||
int32_t ox, oz;
|
|
||||||
WorldFiles* worldFiles;
|
WorldFiles* worldFiles;
|
||||||
|
|
||||||
Chunks(
|
Chunks(
|
||||||
@ -105,14 +102,30 @@ public:
|
|||||||
bool isReplaceableBlock(int32_t x, int32_t y, int32_t z);
|
bool isReplaceableBlock(int32_t x, int32_t y, int32_t z);
|
||||||
bool isObstacleBlock(int32_t x, int32_t y, int32_t z);
|
bool isObstacleBlock(int32_t x, int32_t y, int32_t z);
|
||||||
|
|
||||||
// does not move chunks inside
|
|
||||||
void _setOffset(int32_t x, int32_t z);
|
|
||||||
|
|
||||||
void setCenter(int32_t x, int32_t z);
|
void setCenter(int32_t x, int32_t z);
|
||||||
void translate(int32_t x, int32_t z);
|
|
||||||
void resize(uint32_t newW, uint32_t newD);
|
void resize(uint32_t newW, uint32_t newD);
|
||||||
|
|
||||||
void saveAndClear();
|
void saveAndClear();
|
||||||
void save(Chunk* chunk);
|
void save(Chunk* chunk);
|
||||||
void saveAll();
|
void saveAll();
|
||||||
|
|
||||||
|
const std::vector<std::shared_ptr<Chunk>>& getChunks() const {
|
||||||
|
return areaMap.getBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::ivec2& getSize() const {
|
||||||
|
return areaMap.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::ivec2& getOffset() const {
|
||||||
|
return areaMap.getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getChunksCount() const {
|
||||||
|
return areaMap.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getVolume() const {
|
||||||
|
return areaMap.area();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -86,7 +86,7 @@ void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) {
|
|||||||
(settings.chunks.loadDistance.get() + settings.chunks.padding.get()) *
|
(settings.chunks.loadDistance.get() + settings.chunks.padding.get()) *
|
||||||
2LL
|
2LL
|
||||||
);
|
);
|
||||||
if (chunks->w != diameter) {
|
if (chunks->getSize().x != diameter) {
|
||||||
chunks->resize(diameter, diameter);
|
chunks->resize(diameter, diameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,7 @@ void WorldGenerator::generateHeightmap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
||||||
timeutil::ScopeLogTimer log(555);
|
//timeutil::ScopeLogTimer log(555);
|
||||||
|
|
||||||
auto prototype = generatePrototype(chunkX, chunkZ);
|
auto prototype = generatePrototype(chunkX, chunkZ);
|
||||||
generateHeightmap(prototype.get(), chunkX, chunkZ);
|
generateHeightmap(prototype.get(), chunkX, chunkZ);
|
||||||
|
|||||||
7
test/util/AreaMap2D.cpp
Normal file
7
test/util/AreaMap2D.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "util/AreaMap2D.hpp"
|
||||||
|
|
||||||
|
TEST(AreaMap2D, BaseTest) {
|
||||||
|
util::AreaMap2D<int> window({6, 6});
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user