From 8116791dcf50955c2c9b1e4bca6108ee6cb175c3 Mon Sep 17 00:00:00 2001 From: EmaMaker Date: Sun, 20 Nov 2022 20:22:56 +0100 Subject: [PATCH] use hilbert curve instead of flatten array Using valgrind heap memory tracker, this does not seem to bring any advantage on heap memory usage. To be tested more in depth --- include/globals.hpp | 7 +++-- src/chunk.cpp | 6 ++-- src/chunkgenerator.cpp | 70 +++++++++++++++++++----------------------- src/chunkmesh.cpp | 6 ++-- src/main.cpp | 2 +- src/spacefilling.cpp | 7 +++-- 6 files changed, 46 insertions(+), 52 deletions(-) diff --git a/include/globals.hpp b/include/globals.hpp index ca63c67..d51d568 100644 --- a/include/globals.hpp +++ b/include/globals.hpp @@ -2,6 +2,7 @@ #define GLOBALS_H #include "camera.hpp" +#include "chunk.hpp" #ifdef GLOBALS_DEFINER #define extr @@ -9,13 +10,13 @@ #define extr extern #endif -#define RENDER_DISTANCE 4 +#define RENDER_DISTANCE 8 extr Camera theCamera; extr uint32_t MORTON_XYZ_ENCODE[CHUNK_SIZE][CHUNK_SIZE][CHUNK_SIZE]; -extr uint32_t MORTON_XYZ_DECODE[CHUNK_SIZE][3]; +extr uint32_t MORTON_XYZ_DECODE[CHUNK_VOLUME][3]; extr uint32_t HILBERT_XYZ_ENCODE[CHUNK_SIZE][CHUNK_SIZE][CHUNK_SIZE]; -extr uint32_t HILBERT_XYZ_DECODE[CHUNK_SIZE][3]; +extr uint32_t HILBERT_XYZ_DECODE[CHUNK_VOLUME][3]; #endif \ No newline at end of file diff --git a/src/chunk.cpp b/src/chunk.cpp index 859b002..73a3047 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -27,14 +27,12 @@ namespace Chunk Block Chunk::getBlock(int x, int y, int z) { - return blocks.at(coord3DTo1D(x, y, z)); - // return blocks.at(HILBERT_XYZ_ENCODE[x][y][z]); + return blocks.at(HILBERT_XYZ_ENCODE[x][y][z]); } void Chunk::setBlock(Block b, int x, int y, int z) { - // return blocks.insert(HILBERT_XYZ_ENCODE[x][y][z], HILBERT_XYZ_ENCODE[x][y][z]+1, b); - int coord = coord3DTo1D(x, y, z); + int coord = HILBERT_XYZ_ENCODE[x][y][z]; blocks.insert(coord <= 0 ? 0 : coord, coord+1 >= CHUNK_VOLUME ? CHUNK_VOLUME : coord+1, b); } diff --git a/src/chunkgenerator.cpp b/src/chunkgenerator.cpp index 59223e1..e114354 100644 --- a/src/chunkgenerator.cpp +++ b/src/chunkgenerator.cpp @@ -4,6 +4,7 @@ #include "block.hpp" #include "chunkgenerator.hpp" +#include "globals.hpp" #include "OpenSimplexNoise.h" #include "utils.hpp" @@ -43,47 +44,40 @@ void generateNoise(Chunk::Chunk *chunk) Block block_prev{Block::AIR}; int block_prev_start{0}; - // The order of iteration MUST RESPECT the order in which the array is transformed from 3d to 1d - for (int k = 0; k < CHUNK_SIZE; k++) + // A space filling curve is continuous, so there is no particular order + for (int s = 0; s < CHUNK_VOLUME; s++) { - for (int j = 0; j < CHUNK_SIZE; j++) + + int x = HILBERT_XYZ_DECODE[s][0] + CHUNK_SIZE * chunk->getPosition().x; + int y = HILBERT_XYZ_DECODE[s][1] + CHUNK_SIZE * chunk->getPosition().y; + int z = HILBERT_XYZ_DECODE[s][2] + CHUNK_SIZE * chunk->getPosition().z; + int d2 = HILBERT_XYZ_DECODE[s][0] * CHUNK_SIZE + HILBERT_XYZ_DECODE[s][2]; + + if (grassNoiseLUT[d2] == -1) + grassNoiseLUT[d2] = GRASS_OFFSET + (int)((0.5 + noiseGen1.eval(x * NOISE_GRASS_X_MULT, z * NOISE_GRASS_Z_MULT) * NOISE_GRASS_MULT)); + if (dirtNoiseLUT[d2] == -1) + dirtNoiseLUT[d2] = NOISE_DIRT_MIN + (int)((0.5 + noiseGen2.eval(x * NOISE_DIRT_X_MULT, z * NOISE_DIRT_Z_MULT) * NOISE_DIRT_MULT)); + + int grassNoise = grassNoiseLUT[d2]; + int dirtNoise = dirtNoiseLUT[d2]; + int stoneLevel = grassNoise - dirtNoise; + + if (y < stoneLevel) + block = Block::STONE; + else if (y >= stoneLevel && y < grassNoise) + block = Block::DIRT; + else if (y == grassNoise) + block = Block::GRASS; + else + block = Block::AIR; + + if (block != block_prev) { - for (int i = 0; i < CHUNK_SIZE; i++) - { - int x = i + CHUNK_SIZE * chunk->getPosition().x; - int y = j + CHUNK_SIZE * chunk->getPosition().y; - int z = k + CHUNK_SIZE * chunk->getPosition().z; - int d2 = k * CHUNK_SIZE + i; - - if (grassNoiseLUT[d2] == -1) - grassNoiseLUT[d2] = GRASS_OFFSET + (int)((0.5 + noiseGen1.eval(x * NOISE_GRASS_X_MULT, z * NOISE_GRASS_Z_MULT) * NOISE_GRASS_MULT)); - if (dirtNoiseLUT[d2] == -1) - dirtNoiseLUT[d2] = NOISE_DIRT_MIN + (int)((0.5 + noiseGen2.eval(x * NOISE_DIRT_X_MULT, z * NOISE_DIRT_Z_MULT) * NOISE_DIRT_MULT)); - - int grassNoise = grassNoiseLUT[d2]; - int dirtNoise = dirtNoiseLUT[d2]; - int stoneLevel = grassNoise - dirtNoise; - - if (y < stoneLevel) - block = Block::STONE; - else if (y >= stoneLevel && y < grassNoise) - block = Block::DIRT; - else if (y == grassNoise) - block = Block::GRASS; - else - block = Block::AIR; - - int index = Chunk::coord3DTo1D(i, j, k); - int min = index > block_prev_start ? block_prev_start : index, max = index > block_prev_start ? index : block_prev_start; - if (block != block_prev) - { - chunk->setBlocks(block_prev_start, index, block_prev); - block_prev_start = index; - } - - block_prev = block; - } + chunk->setBlocks(block_prev_start, s, block_prev); + block_prev_start = s; } + + block_prev = block; } chunk->setBlocks(block_prev_start, CHUNK_VOLUME, block_prev); diff --git a/src/chunkmesh.cpp b/src/chunkmesh.cpp index d765f85..8fd9618 100755 --- a/src/chunkmesh.cpp +++ b/src/chunkmesh.cpp @@ -99,10 +99,10 @@ void ChunkMesh::mesh() { for (x[u] = 0; x[u] < CHUNK_SIZE; x[u]++) { - Block b1 = (x[dim] >= 0) ? blocks[Chunk::coord3DTo1D(x[0], x[1], x[2])] : Block::NULLBLK; /*blocks[SpaceFilling::HILBERT_XYZ_ENCODE[x[0]][x[1]][x[2]]]*/ + Block b1 = (x[dim] >= 0) ? blocks[HILBERT_XYZ_ENCODE[x[0]][x[1]][x[2]]]: Block::NULLBLK; Block b2 = (x[dim] < CHUNK_SIZE - 1) - ? blocks[Chunk::coord3DTo1D(x[0] + q[0], x[1] + q[1], x[2] + q[2])] - : Block::NULLBLK; /*blocks[SpaceFilling::HILBERT_XYZ_ENCODE[x[0] + q[0]][x[1] + q[1]][x[2] + q[2]]]*/ + ? blocks[HILBERT_XYZ_ENCODE[x[0] + q[0]][x[1] + q[1]][x[2] + q[2]]] + : Block::NULLBLK; // This is the original line taken from rob's code, readapted (replace voxelFace // with b1 and b2). diff --git a/src/main.cpp b/src/main.cpp index d922197..8bb9220 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,7 +51,7 @@ int main() glfwSetCursorPosCallback(window, mouse_callback); glEnable(GL_DEPTH_TEST); - // SpaceFilling::initLUT(); + SpaceFilling::initLUT(); chunkmanager::init(); while (!glfwWindowShouldClose(window)) diff --git a/src/spacefilling.cpp b/src/spacefilling.cpp index 9753e7d..1f0bc4c 100644 --- a/src/spacefilling.cpp +++ b/src/spacefilling.cpp @@ -188,15 +188,16 @@ namespace SpaceFilling void initLUT() { - uint32_t morton, hilbert; + uint32_t morton, hilbert,j; for (uint32_t i = 0; i < CHUNK_SIZE; i++) { - for (uint32_t j = 0; j < CHUNK_SIZE; j++) + for (uint32_t y = 0; y < CHUNK_SIZE; y++) { for (uint32_t k = 0; k < CHUNK_SIZE; k++) { + j = CHUNK_SIZE - 1 - y; morton = Morton_3D_Encode_10bit(i, j, k); - hilbert = MortonToHilbert3D(morton, 4); // 4 hilbert bits + hilbert = MortonToHilbert3D(morton, 2); // 4 hilbert bits MORTON_XYZ_ENCODE[i][j][k] = morton; MORTON_XYZ_DECODE[morton][0] = i;