2022-09-25 23:05:56 +00:00
|
|
|
#include "chunk.hpp"
|
|
|
|
#include "xe_engine.hpp"
|
|
|
|
|
|
|
|
namespace app {
|
|
|
|
|
2022-09-26 15:03:27 +00:00
|
|
|
static std::map<std::pair<uint32_t, uint32_t>, Chunk*> chunks{};
|
2022-09-25 23:05:56 +00:00
|
|
|
|
|
|
|
Chunk::Chunk(uint32_t gridX, uint32_t gridZ, uint32_t world_seed)
|
|
|
|
: world_seed{world_seed},
|
|
|
|
chunk_seed{(world_seed * gridX) + (world_seed * gridZ) / 2},
|
|
|
|
gridX{gridX},
|
|
|
|
gridZ{gridZ} {
|
|
|
|
generate();
|
|
|
|
}
|
|
|
|
|
|
|
|
Chunk* Chunk::newChunk(uint32_t gridX, uint32_t gridZ, uint32_t world_seed) {
|
2022-09-26 15:03:27 +00:00
|
|
|
Chunk* chunk = new Chunk(gridX, gridZ, world_seed);
|
|
|
|
chunks[{gridX, gridZ}] = std::move(chunk);
|
|
|
|
return chunks[{gridX, gridZ}];
|
2022-09-25 23:05:56 +00:00
|
|
|
}
|
|
|
|
|
2022-09-26 15:03:27 +00:00
|
|
|
Chunk* Chunk::getChunk(uint32_t gridX, uint32_t gridZ) {
|
|
|
|
if(chunks.count({gridX, gridZ})) {
|
|
|
|
return chunks[{gridX, gridZ}];
|
|
|
|
} else {
|
|
|
|
return NULL;
|
2022-09-25 23:05:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t Chunk::getBlock(uint32_t x, uint32_t y, uint32_t z) {
|
2022-09-26 15:03:27 +00:00
|
|
|
if(y > 256) return AIR;
|
|
|
|
if(y < 0) return INVALID;
|
2022-09-25 23:05:56 +00:00
|
|
|
int chunkX = gridX;
|
|
|
|
int chunkZ = gridZ;
|
|
|
|
if(x < 0) {
|
|
|
|
chunkX--;
|
|
|
|
x = 15;
|
2022-09-26 15:03:27 +00:00
|
|
|
} else if(x > 15) {
|
|
|
|
chunkX++;
|
2022-09-25 23:05:56 +00:00
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
if(z < 0) {
|
|
|
|
chunkZ--;
|
|
|
|
z = 15;
|
2022-09-26 15:03:27 +00:00
|
|
|
} else if(z > 15) {
|
|
|
|
chunkZ++;
|
2022-09-25 23:05:56 +00:00
|
|
|
z = 0;
|
|
|
|
}
|
|
|
|
if(chunkX == gridX && chunkZ == gridZ) {
|
2022-09-26 15:03:27 +00:00
|
|
|
int index = x + (z * 16) + (y * 256);
|
2022-09-25 23:05:56 +00:00
|
|
|
return blocks[index];
|
|
|
|
} else {
|
|
|
|
Chunk* chunk = getChunk(chunkX, chunkZ);
|
|
|
|
if(chunk == nullptr) {
|
2022-09-26 15:03:27 +00:00
|
|
|
return INVALID;
|
2022-09-25 23:05:56 +00:00
|
|
|
} else {
|
2022-09-26 15:03:27 +00:00
|
|
|
int index = x + (z * 16) + (y * 256);
|
2022-09-25 23:05:56 +00:00
|
|
|
return chunk->blocks[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Chunk::setBlock(uint32_t x, uint32_t y, uint32_t z, uint8_t block) {
|
2022-09-26 15:03:27 +00:00
|
|
|
int index = x + (z * 16) + (y * 256);
|
2022-09-25 23:05:56 +00:00
|
|
|
blocks[index] = block;
|
|
|
|
}
|
|
|
|
|
2022-09-26 15:03:27 +00:00
|
|
|
void Chunk::reset() {
|
|
|
|
for(const auto &[key, chunk]: chunks) {
|
|
|
|
delete chunk;
|
|
|
|
}
|
|
|
|
chunks.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<xe::Model> Chunk::getMesh() {
|
|
|
|
if(reloadRequired) {
|
|
|
|
delete chunkMesh.get();
|
|
|
|
xe::Model::Builder builder{};
|
|
|
|
builder.vertexData = vertexData;
|
|
|
|
builder.vertexSize = 32;
|
|
|
|
chunkMesh = std::make_shared<xe::Model>(xe::Engine::getInstance()->getDevice(), builder);
|
|
|
|
}
|
|
|
|
return chunkMesh;
|
2022-09-25 23:05:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Chunk::createMeshAsync() {
|
|
|
|
if(working) return;
|
|
|
|
// worker = std::thread(createMesh);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Chunk::createMesh() {
|
|
|
|
working = true;
|
|
|
|
vertexData.clear();
|
|
|
|
for(int x=0;x<16;x++) {
|
|
|
|
for(int y=0; y<256; y++) {
|
|
|
|
for(int z=0; z<16; z++) {
|
|
|
|
uint8_t block = getBlock(x,y,z);
|
|
|
|
if(block == AIR) continue;
|
|
|
|
if(getBlock(x+1,y,z) == AIR) {
|
|
|
|
addVerticies(0, x, y, z);
|
|
|
|
}
|
|
|
|
if(getBlock(x-1,y,z) == AIR) {
|
|
|
|
addVerticies(1, x, y, z);
|
|
|
|
}
|
|
|
|
if(getBlock(x,y+1,z) == AIR) {
|
|
|
|
addVerticies(2, x, y, z);
|
|
|
|
}
|
|
|
|
if(getBlock(x,y-1,z) == AIR) {
|
|
|
|
addVerticies(3, x, y, z);
|
|
|
|
}
|
|
|
|
if(getBlock(x,y,z+1) == AIR) {
|
|
|
|
addVerticies(4, x, y, z);
|
|
|
|
}
|
|
|
|
if(getBlock(x,y,z-1) == AIR) {
|
|
|
|
addVerticies(5, x, y, z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
working = false;
|
|
|
|
reloadRequired = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Chunk::addVerticies(uint32_t side, uint32_t x, uint32_t y, uint32_t z) {
|
|
|
|
for(int i = 0; i < 6; i ++) {
|
|
|
|
vertexData.push_back(px[side * 6 + i][0] + x);
|
|
|
|
vertexData.push_back(px[side * 6 + i][1] + y);
|
|
|
|
vertexData.push_back(px[side * 6 + i][2] + z);
|
|
|
|
vertexData.push_back(nm[side][0]);
|
|
|
|
vertexData.push_back(nm[side][1]);
|
|
|
|
vertexData.push_back(nm[side][2]);
|
|
|
|
vertexData.push_back(uv[i][0]);
|
|
|
|
vertexData.push_back(uv[i][1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Chunk::generate() {
|
|
|
|
blocks.resize(16*16*256);
|
|
|
|
|
2022-09-26 15:03:27 +00:00
|
|
|
const PerlinNoise perlin{world_seed};
|
2022-09-25 23:05:56 +00:00
|
|
|
|
|
|
|
for(int x = 0; x < 16; x++) {
|
|
|
|
for(int z = 0; z < 16; z++) {
|
2022-09-26 15:03:27 +00:00
|
|
|
int height = perlin.octave2D_01((( x + gridX * 16) * 0.01), ((z + gridZ * 16) * 0.01), 4) * 10;
|
2022-09-25 23:05:56 +00:00
|
|
|
for(int y = 0; y < 256; y++) {
|
|
|
|
if(y <= height)
|
|
|
|
setBlock(x, y, z, DIRT);
|
|
|
|
else
|
|
|
|
setBlock(x, y, z, AIR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|