stabilize delays of chunks meshes building

This commit is contained in:
MihailRis 2025-12-29 20:41:47 +03:00
parent f47ccd5f30
commit 88544183d0
13 changed files with 335 additions and 191 deletions

View file

@ -335,26 +335,106 @@ bool Chunks::putChunk(const std::shared_ptr<Chunk>& chunk) {
return false;
}
// reduce nesting on next modification
// 25.06.2024: not now
// 11.11.2024: not now
// 12.12.2025: not now
void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const {
voxel* voxels = volume.getVoxels();
light_t* lights = volume.getLights();
int x = volume.getX();
int y = volume.getY();
int z = volume.getZ();
static void fill_with_void(
voxel* voxels,
light_t* lights,
const glm::ivec3& pos,
const glm::ivec3& size,
int cx,
int cz
) {
for (int ly = pos.y; ly < pos.y + size.y; ly++) {
for (int lz = std::max(pos.z, cz * CHUNK_D);
lz < std::min(pos.z + size.z, (cz + 1) * CHUNK_D);
lz++) {
for (int lx = std::max(pos.x, cx * CHUNK_W);
lx < std::min(pos.x + size.x, (cx + 1) * CHUNK_W);
lx++) {
uint idx = vox_index(
lx - pos.x, ly - pos.y, lz - pos.z, size.x, size.z
);
voxels[idx].id = BLOCK_VOID;
lights[idx] = 0;
}
}
}
}
int w = volume.getW();
int h = std::min<int>(volume.getH(), top);
int d = volume.getD();
static inline light_t apply_backlight(light_t light) {
return Lightmap::combine(
std::min(15, Lightmap::extract(light, 0) + 1),
std::min(15, Lightmap::extract(light, 1) + 1),
std::min(15, Lightmap::extract(light, 2) + 1),
std::min(15, static_cast<int>(Lightmap::extract(light, 3)))
);
}
int scx = floordiv<CHUNK_W>(x);
int scz = floordiv<CHUNK_D>(z);
#include "util/timeutil.hpp"
int ecx = floordiv<CHUNK_W>(x + w);
int ecz = floordiv<CHUNK_D>(z + d);
// ugly
static inline void sample_chunk(
const decltype(ContentIndices::blocks)& defs,
const Chunk& chunk,
voxel* voxels,
light_t* lights,
const glm::ivec3& pos,
const glm::ivec3& size,
int cx,
int cz,
bool backlight
) {
const auto cvoxels = chunk.voxels;
const auto clights = chunk.lightmap ? chunk.lightmap->getLights() : nullptr;
for (int ly = pos.y; ly < pos.y + size.y; ly++) {
for (int lz = std::max(pos.z, cz * CHUNK_D);
lz < std::min(pos.z + size.z, (cz + 1) * CHUNK_D);
lz++) {
for (int lx = std::max(pos.x, cx * CHUNK_W);
lx < std::min(pos.x + size.x, (cx + 1) * CHUNK_W);
lx++) {
uint vidx = vox_index(
lx - pos.x, ly - pos.y, lz - pos.z, size.x, size.z
);
uint cidx = vox_index(
lx - cx * CHUNK_W,
ly,
lz - cz * CHUNK_D,
CHUNK_W,
CHUNK_D
);
auto& vox = voxels[vidx];
vox = cvoxels[cidx];
light_t light = clights ? clights[cidx]
: Lightmap::SUN_LIGHT_ONLY;
// todo: move to the BlocksRenderer
if (backlight) {
const auto block = defs.get(vox.id);
if (block && block->lightPassing) {
light = apply_backlight(light);
}
}
lights[vidx] = light;
}
}
}
}
void Chunks::getVoxels(
voxel* voxels,
light_t* lights,
const glm::ivec3& pos,
const glm::ivec3& size,
bool backlight,
int top
) const {
timeutil::ScopeLogTimer log(111);
int h = std::min<int>(size.y, top);
int scx = floordiv<CHUNK_W>(pos.x);
int scz = floordiv<CHUNK_D>(pos.z);
int ecx = floordiv<CHUNK_W>(pos.x + size.x);
int ecz = floordiv<CHUNK_D>(pos.z + size.z);
int cw = ecx - scx + 1;
int cd = ecz - scz + 1;
@ -364,67 +444,37 @@ void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const {
for (int cx = scx; cx < scx + cw; cx++) {
const auto chunk = getChunk(cx, cz);
if (chunk == nullptr) {
// no chunk loaded -> filling with BLOCK_VOID
for (int ly = y; ly < y + h; ly++) {
for (int lz = std::max(z, cz * CHUNK_D);
lz < std::min(z + d, (cz + 1) * CHUNK_D);
lz++) {
for (int lx = std::max(x, cx * CHUNK_W);
lx < std::min(x + w, (cx + 1) * CHUNK_W);
lx++) {
uint idx = vox_index(lx - x, ly - y, lz - z, w, d);
voxels[idx].id = BLOCK_VOID;
lights[idx] = 0;
}
}
}
} else {
const voxel* cvoxels = chunk->voxels;
const light_t* clights =
chunk->lightmap ? chunk->lightmap->getLights() : nullptr;
for (int ly = y; ly < y + h; ly++) {
for (int lz = std::max(z, cz * CHUNK_D);
lz < std::min(z + d, (cz + 1) * CHUNK_D);
lz++) {
for (int lx = std::max(x, cx * CHUNK_W);
lx < std::min(x + w, (cx + 1) * CHUNK_W);
lx++) {
uint vidx = vox_index(lx - x, ly - y, lz - z, w, d);
uint cidx = vox_index(
lx - cx * CHUNK_W,
ly,
lz - cz * CHUNK_D,
CHUNK_W,
CHUNK_D
);
voxels[vidx] = cvoxels[cidx];
light_t light = clights ? clights[cidx]
: Lightmap::SUN_LIGHT_ONLY;
if (backlight) {
const auto block =
indices.blocks.get(voxels[vidx].id);
if (block && block->lightPassing) {
light = Lightmap::combine(
std::min(15,
Lightmap::extract(light, 0) + 1),
std::min(15,
Lightmap::extract(light, 1) + 1),
std::min(15,
Lightmap::extract(light, 2) + 1),
std::min(15,
static_cast<int>(Lightmap::extract(light, 3)))
);
}
}
lights[vidx] = light;
}
}
}
fill_with_void(
voxels, lights, pos, {size.x, h, size.z}, cx, cz
);
continue;
}
sample_chunk(
indices.blocks,
*chunk,
voxels,
lights,
pos,
{size.x, h, size.z},
cx,
cz,
backlight
);
}
}
}
void Chunks::getVoxels(VoxelsVolume& volume, bool backlight, int top) const {
getVoxels(
volume.getVoxels(),
volume.getLights(),
{volume.getX(), volume.getY(), volume.getZ()},
{volume.getW(), volume.getH(), volume.getD()},
backlight,
top
);
}
void Chunks::saveAndClear() {
areaMap.clear();
}

View file

@ -23,6 +23,8 @@ class LevelEvents;
class Block;
class VoxelsVolume;
template <int w, int h, int d> class StaticVoxelsVolume;
/// Player-centred chunks matrix
class Chunks {
LevelEvents* events;
@ -128,7 +130,34 @@ public:
bool isReplaceableBlock(int32_t x, int32_t y, int32_t z);
bool isObstacleBlock(int32_t x, int32_t y, int32_t z);
void getVoxels(VoxelsVolume& volume, bool backlight = false, int top = CHUNK_H) const;
void getVoxels(
VoxelsVolume& volume, bool backlight = false, int top = CHUNK_H
) const;
template <int w, int h, int d>
void getVoxels(
StaticVoxelsVolume<w, h, d>& volume,
bool backlight = false,
int top = CHUNK_H
) const {
getVoxels(
volume.getVoxels(),
volume.getLights(),
{volume.getX(), volume.getY(), volume.getZ()},
{w, h, d},
backlight,
top
);
}
void getVoxels(
voxel* voxels,
light_t* lights,
const glm::ivec3& pos,
const glm::ivec3& size,
bool backlight,
int top
) const;
void setCenter(int32_t x, int32_t z);
void resize(uint32_t newW, uint32_t newD);

View file

@ -1,28 +0,0 @@
#include "VoxelsVolume.hpp"
VoxelsVolume::VoxelsVolume(int x, int y, int z, int w, int h, int d)
: x(x),
y(y),
z(z),
w(w),
h(h),
d(d),
voxels(std::make_unique<voxel[]>(w * h * d)),
lights(std::make_unique<light_t[]>(w * h * d)) {
for (int i = 0; i < w * h * d; i++) {
voxels[i].id = BLOCK_VOID;
}
}
VoxelsVolume::VoxelsVolume(int w, int h, int d)
: VoxelsVolume(0, 0, 0, w, h, d) {
}
VoxelsVolume::~VoxelsVolume() {
}
void VoxelsVolume::setPosition(int x, int y, int z) {
this->x = x;
this->y = y;
this->z = z;
}

View file

@ -4,17 +4,25 @@
#include "typedefs.hpp"
#include "voxel.hpp"
class VoxelsVolume {
int x, y, z;
int w, h, d;
std::unique_ptr<voxel[]> voxels;
std::unique_ptr<light_t[]> lights;
public:
VoxelsVolume(int w, int h, int d);
VoxelsVolume(int x, int y, int z, int w, int h, int d);
virtual ~VoxelsVolume();
#include <cstring>
void setPosition(int x, int y, int z);
class VoxelsVolume {
public:
static inline constexpr size_t MAX_VOXELS = CHUNK_VOL * 2;
VoxelsVolume(int w, int h, int d)
: VoxelsVolume(0, 0, 0, w, h, d) {}
VoxelsVolume(int x, int y, int z, int w, int h, int d)
: x(x), y(y), z(z), w(w), h(h), d(d) {
std::memset(voxels.get(), 0xFF, sizeof(voxel) * w * h * d);
}
void setPosition(int x, int y, int z) {
this->x = x;
this->y = y;
this->z = z;
}
int getX() const {
return x;
@ -40,11 +48,11 @@ public:
return d;
}
voxel* getVoxels() const {
voxel* getVoxels() {
return voxels.get();
}
light_t* getLights() const {
light_t* getLights() {
return lights.get();
}
@ -72,4 +80,83 @@ public:
}
return lights[vox_index(bx - x, by - y, bz - z, w, d)];
}
private:
int x, y, z;
int w, h, d;
std::unique_ptr<voxel[]> voxels;
std::unique_ptr<light_t[]> lights;
};
template <int w, int h, int d>
class StaticVoxelsVolume {
public:
static inline constexpr size_t size = w * h * d;
static inline constexpr int width = w;
static inline constexpr int height = h;
static inline constexpr int depth = d;
StaticVoxelsVolume()
: StaticVoxelsVolume(0, 0, 0) {}
StaticVoxelsVolume(int x, int y, int z)
: x(x), y(y), z(z) {
std::memset(voxels, 0xFF, sizeof(voxel) * size);
}
void setPosition(int x, int y, int z) {
this->x = x;
this->y = y;
this->z = z;
}
int getX() const {
return x;
}
int getY() const {
return y;
}
int getZ() const {
return z;
}
voxel* getVoxels() {
return voxels;
}
light_t* getLights() {
return lights;
}
inline blockid_t pickBlockId(int bx, int by, int bz) const {
if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h ||
bz >= z + d) {
return BLOCK_VOID;
}
return voxels[vox_index(bx - x, by - y, bz - z, w, d)].id;
}
inline voxel pickBlock(int bx, int by, int bz) const {
if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h ||
bz >= z + d) {
return {BLOCK_VOID, {}};
}
return voxels[vox_index(bx - x, by - y, bz - z, w, d)];
}
inline light_t pickLight(int bx, int by, int bz) const {
if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h ||
bz >= z + d) {
return 0;
}
return lights[vox_index(bx - x, by - y, bz - z, w, d)];
}
private:
int x, y, z;
voxel voxels[size];
light_t lights[size];
};