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");
|
||||
}));
|
||||
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);
|
||||
}));
|
||||
panel->add(create_label([=]() {
|
||||
|
||||
@ -79,7 +79,7 @@ WorldRenderer::~WorldRenderer() = default;
|
||||
bool WorldRenderer::drawChunk(
|
||||
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) {
|
||||
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
|
||||
|
||||
std::vector<size_t> indices;
|
||||
for (size_t i = 0; i < chunks->volume; i++) {
|
||||
if (chunks->chunks[i] == nullptr) continue;
|
||||
for (size_t i = 0; i < chunks->getVolume(); i++) {
|
||||
if (chunks->getChunks()[i] == nullptr) continue;
|
||||
indices.emplace_back(i);
|
||||
}
|
||||
float px = camera->position.x / static_cast<float>(CHUNK_W) - 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) {
|
||||
const auto a = chunks->chunks[i].get();
|
||||
const auto b = chunks->chunks[j].get();
|
||||
const auto& chunksBuffer = chunks->getChunks();
|
||||
const auto a = chunksBuffer[i].get();
|
||||
const auto b = chunksBuffer[j].get();
|
||||
auto adx = (a->x - px);
|
||||
auto adz = (a->z - pz);
|
||||
auto bdx = (b->x - px);
|
||||
|
||||
@ -23,8 +23,9 @@ Lighting::Lighting(const Content* content, Chunks* chunks)
|
||||
Lighting::~Lighting() = default;
|
||||
|
||||
void Lighting::clear(){
|
||||
for (size_t index = 0; index < chunks->volume; index++){
|
||||
auto chunk = chunks->chunks[index];
|
||||
const auto& chunks = this->chunks->getChunks();
|
||||
for (size_t index = 0; index < chunks.size(); index++){
|
||||
auto chunk = chunks[index];
|
||||
if (chunk == nullptr)
|
||||
continue;
|
||||
Lightmap& lightmap = chunk->lightmap;
|
||||
|
||||
@ -124,17 +124,16 @@ void BlocksController::randomTick(
|
||||
|
||||
void BlocksController::randomTick(int tickid, int parts) {
|
||||
auto indices = level->content->getIndices();
|
||||
const int w = chunks->w;
|
||||
const int d = chunks->d;
|
||||
const auto& size = chunks->getSize();
|
||||
int segments = 4;
|
||||
|
||||
for (uint z = padding; z < d - padding; z++) {
|
||||
for (uint x = padding; x < w - padding; x++) {
|
||||
int index = z * w + x;
|
||||
for (uint z = padding; z < size.y - padding; z++) {
|
||||
for (uint x = padding; x < size.x - padding; x++) {
|
||||
int index = z * size.x + x;
|
||||
if ((index + tickid) % parts != 0) {
|
||||
continue;
|
||||
}
|
||||
auto& chunk = chunks->chunks[index];
|
||||
auto& chunk = chunks->getChunks()[index];
|
||||
if (chunk == nullptr || !chunk->flags.lighted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -52,16 +52,15 @@ void ChunksController::update(int64_t maxDuration) {
|
||||
}
|
||||
|
||||
bool ChunksController::loadVisible() {
|
||||
const int w = chunks->w;
|
||||
const int d = chunks->d;
|
||||
const auto& size = chunks->getSize();
|
||||
|
||||
int nearX = 0;
|
||||
int nearZ = 0;
|
||||
int minDistance = ((w - padding * 2) / 2) * ((w - padding * 2) / 2);
|
||||
for (uint z = padding; z < d - padding; z++) {
|
||||
for (uint x = padding; x < w - padding; x++) {
|
||||
int index = z * w + x;
|
||||
auto& chunk = chunks->chunks[index];
|
||||
int minDistance = ((size.x - padding * 2) / 2) * ((size.y - padding * 2) / 2);
|
||||
for (uint z = padding; z < size.y - padding; z++) {
|
||||
for (uint x = padding; x < size.x - padding; x++) {
|
||||
int index = z * size.x + x;
|
||||
auto& chunk = chunks->getChunks()[index];
|
||||
if (chunk != nullptr) {
|
||||
if (chunk->flags.loaded && !chunk->flags.lighted) {
|
||||
if (buildLights(chunk)) {
|
||||
@ -70,8 +69,8 @@ bool ChunksController::loadVisible() {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int lx = x - w / 2;
|
||||
int lz = z - d / 2;
|
||||
int lx = x - size.x / 2;
|
||||
int lz = z - size.y / 2;
|
||||
int distance = (lx * lx + lz * lz);
|
||||
if (distance < minDistance) {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int ox = chunks->ox;
|
||||
const int oz = chunks->oz;
|
||||
createChunk(nearX + ox, nearZ + oz);
|
||||
const auto& offset = chunks->getOffset();
|
||||
createChunk(nearX + offset.x, nearZ + offset.y);
|
||||
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),
|
||||
indices(level->content->getIndices()),
|
||||
chunks(w * d),
|
||||
chunksSecond(w * d),
|
||||
w(w),
|
||||
d(d),
|
||||
ox(ox),
|
||||
oz(oz),
|
||||
areaMap({w, d}),
|
||||
worldFiles(wfile) {
|
||||
volume = static_cast<size_t>(w) * static_cast<size_t>(d);
|
||||
chunksCount = 0;
|
||||
areaMap.setCenter({ox-w/2, oz-d/2});
|
||||
areaMap.setOutCallback([this](const auto& chunk) {
|
||||
save(chunk.get());
|
||||
});
|
||||
}
|
||||
|
||||
voxel* Chunks::get(int32_t x, int32_t y, int32_t z) const {
|
||||
x -= ox * CHUNK_W;
|
||||
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)) {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
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) {
|
||||
return nullptr;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int ly = y - cy * CHUNK_H;
|
||||
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) {
|
||||
@ -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) {
|
||||
x -= ox * CHUNK_W;
|
||||
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)) {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int ly = y - cy * CHUNK_H;
|
||||
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) {
|
||||
x -= ox * CHUNK_W;
|
||||
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)) {
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
int lx = x - cx * CHUNK_W;
|
||||
int ly = y - cy * CHUNK_H;
|
||||
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) {
|
||||
if (y < 0 || y >= CHUNK_H) return nullptr;
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
if (y < 0 || y >= CHUNK_H) {
|
||||
return nullptr;
|
||||
}
|
||||
int cx = floordiv(x, CHUNK_W);
|
||||
int cz = floordiv(z, CHUNK_D);
|
||||
if (cx < 0 || cz < 0 || cx >= int(w) || cz >= int(d)) return nullptr;
|
||||
return chunks[cz * w + cx].get();
|
||||
if (auto ptr = areaMap.getIf({cx, cz})) {
|
||||
return ptr->get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Chunk* Chunks::getChunk(int x, int z) {
|
||||
x -= ox;
|
||||
z -= oz;
|
||||
if (x < 0 || z < 0 || x >= static_cast<int>(w) ||
|
||||
z >= static_cast<int>(d)) {
|
||||
return nullptr;
|
||||
if (auto ptr = areaMap.getIf({x, z})) {
|
||||
return ptr->get();
|
||||
}
|
||||
return chunks[z * w + x].get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glm::ivec3 Chunks::seekOrigin(
|
||||
@ -355,15 +353,13 @@ void Chunks::set(
|
||||
}
|
||||
int32_t gx = x;
|
||||
int32_t gz = z;
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
int cx = floordiv(x, CHUNK_W);
|
||||
int cz = floordiv(z, CHUNK_D);
|
||||
if (cx < 0 || cz < 0 || cx >= static_cast<int>(w) ||
|
||||
cz >= static_cast<int>(d)) {
|
||||
auto ptr = areaMap.getIf({cx, cz});
|
||||
if (ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
Chunk* chunk = chunks[cz * w + cx].get();
|
||||
Chunk* chunk = ptr->get();
|
||||
if (chunk == nullptr) {
|
||||
return;
|
||||
}
|
||||
@ -396,15 +392,18 @@ void Chunks::set(
|
||||
else if (id == 0)
|
||||
chunk->updateHeights();
|
||||
|
||||
if (lx == 0 && (chunk = getChunk(cx + ox - 1, cz + oz)))
|
||||
if (lx == 0 && (chunk = getChunk(cx - 1, cz))) {
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
voxel* Chunks::rayCast(
|
||||
@ -643,97 +642,19 @@ glm::vec3 Chunks::rayCastToObstacle(
|
||||
}
|
||||
|
||||
void Chunks::setCenter(int32_t x, int32_t z) {
|
||||
int cx = floordiv(x, CHUNK_W);
|
||||
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;
|
||||
areaMap.setCenter({floordiv(x, CHUNK_W), floordiv(z, CHUNK_D)});
|
||||
}
|
||||
|
||||
void Chunks::resize(uint32_t newW, uint32_t newD) {
|
||||
if (newW < w) {
|
||||
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;
|
||||
areaMap.resize({newW, newD});
|
||||
}
|
||||
|
||||
bool Chunks::putChunk(const std::shared_ptr<Chunk>& chunk) {
|
||||
int x = chunk->x;
|
||||
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;
|
||||
return areaMap.set({chunk->x, chunk->z}, chunk);
|
||||
}
|
||||
|
||||
void Chunks::saveAndClear() {
|
||||
for (size_t i = 0; i < volume; i++) {
|
||||
auto chunk = chunks[i].get();
|
||||
chunks[i] = nullptr;
|
||||
save(chunk);
|
||||
}
|
||||
chunksCount = 0;
|
||||
areaMap.clear();
|
||||
}
|
||||
|
||||
void Chunks::save(Chunk* chunk) {
|
||||
@ -760,7 +681,8 @@ void Chunks::save(Chunk* chunk) {
|
||||
}
|
||||
|
||||
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]) {
|
||||
save(chunk.get());
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "voxel.hpp"
|
||||
#include "util/AreaMap2D.hpp"
|
||||
|
||||
class VoxelRenderer;
|
||||
|
||||
@ -33,14 +34,10 @@ class Chunks {
|
||||
void setRotationExtended(
|
||||
const Block& def, blockstate state, glm::ivec3 origin, uint8_t rotation
|
||||
);
|
||||
|
||||
util::AreaMap2D<std::shared_ptr<Chunk>> areaMap;
|
||||
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;
|
||||
uint32_t w, d;
|
||||
int32_t ox, oz;
|
||||
WorldFiles* worldFiles;
|
||||
|
||||
Chunks(
|
||||
@ -105,14 +102,30 @@ public:
|
||||
bool isReplaceableBlock(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 translate(int32_t x, int32_t z);
|
||||
void resize(uint32_t newW, uint32_t newD);
|
||||
|
||||
void saveAndClear();
|
||||
void save(Chunk* chunk);
|
||||
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()) *
|
||||
2LL
|
||||
);
|
||||
if (chunks->w != diameter) {
|
||||
if (chunks->getSize().x != diameter) {
|
||||
chunks->resize(diameter, diameter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ void WorldGenerator::generateHeightmap(
|
||||
}
|
||||
|
||||
void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
||||
timeutil::ScopeLogTimer log(555);
|
||||
//timeutil::ScopeLogTimer log(555);
|
||||
|
||||
auto prototype = generatePrototype(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