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
intervalmaps-array-y
EmaMaker 2022-11-20 20:22:56 +01:00 committed by emamaker
parent b724640384
commit 8116791dcf
6 changed files with 46 additions and 52 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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).

View File

@ -51,7 +51,7 @@ int main()
glfwSetCursorPosCallback(window, mouse_callback);
glEnable(GL_DEPTH_TEST);
// SpaceFilling::initLUT();
SpaceFilling::initLUT();
chunkmanager::init();
while (!glfwWindowShouldClose(window))

View File

@ -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;