[ChunkMeshBuilder] Direct surrounding chunks are now handled.

This commit is contained in:
Quentin Bazin 2021-05-31 20:04:17 +02:00
parent 2496f2e9ee
commit c76f944132
2 changed files with 82 additions and 23 deletions

View File

@ -32,17 +32,24 @@
using namespace BlockGeometry;
void ChunkMeshBuilder::addMeshBuildingJob(const Chunk &chunk, const TextureAtlas &textureAtlas) {
// Creating the job (creates a copy of the chunk to send it to the thread)
ChunkMeshBuildingJob job;
job.textureAtlas = &textureAtlas;
job.chunkData.loadFromChunk(chunk);
job.chunkData.x = chunk.x();
job.chunkData.y = chunk.y();
job.chunkData.z = chunk.z();
std::memcpy(&job.chunkData.data, &chunk.data(), sizeof(Chunk::DataArray));
std::memcpy(&job.chunkData.lightData, &chunk.lightmap().data(), sizeof(ChunkLightmap::LightMapArray));
// Initialize chunk neighbours
for (u8f i = 0 ; i < 6 ; ++i)
if (const Chunk *neighbour = chunk.getSurroundingChunk(i) ; neighbour)
job.neighbourData[i].emplace().loadFromChunk(*neighbour);
// Send the job to the thread pool
auto future = m_threadPool.submit([](ChunkMeshBuildingJob job) {
// Tell the chunk where to find its neighbours
for (u8f i = 0 ; i < 6 ; ++i)
if (job.neighbourData[i].has_value())
job.chunkData.neighbours[i] = &job.neighbourData[i].value();
// For each block, generate its vertices and add them to the list
for (s8f z = 0 ; z < CHUNK_HEIGHT ; z++) {
for (s8f y = 0 ; y < CHUNK_DEPTH ; y++) {
for (s8f x = 0 ; x < CHUNK_WIDTH ; x++) {
@ -50,7 +57,7 @@ void ChunkMeshBuilder::addMeshBuildingJob(const Chunk &chunk, const TextureAtlas
if (!blockID) continue;
u16 blockParam = job.chunkData.getBlockParam(x, y, z);
const BlockState &blockState = job.chunkData.getBlockState(blockID, blockParam);
const BlockState &blockState = ChunkData::getBlockState(blockID, blockParam);
if (blockState.drawType() == BlockDrawType::XShape)
addCross(x, y, z, job, blockState);

View File

@ -38,29 +38,79 @@ struct ChunkData {
Chunk::DataArray data;
ChunkLightmap::LightMapArray lightData;
u16 getBlockID(s8f x, s8f y, s8f z) const { return data[z][y][x] & 0xffff; }
u16 getBlockParam(s8f x, s8f y, s8f z) const { return (data[z][y][x] >> 16) & 0xffff; }
ChunkData *neighbours[6]{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
u8 getTorchlight(s8f x, s8f y, s8f z) const { return lightData[z][y][x] & 0xf; }
u8 getSunlight(s8f x, s8f y, s8f z) const { return (lightData[z][y][x] >> 4) & 0xf; }
void loadFromChunk(const Chunk &chunk) {
x = chunk.x();
y = chunk.y();
z = chunk.z();
const BlockState &getBlockState(u16 blockID, u16 blockParam) const {
const Block &block = Registry::getInstance().getBlock(blockID);
return block.getState(block.param().hasParam(BlockParam::State) ?
block.param().getParam(BlockParam::State, blockParam) : 0);
std::memcpy(&data, &chunk.data(), sizeof(Chunk::DataArray));
std::memcpy(&lightData, &chunk.lightmap().data(), sizeof(ChunkLightmap::LightMapArray));
}
u16 getBlockID(s8f x, s8f y, s8f z) const {
if(x < 0) return neighbours[0] ? neighbours[0]->getBlockID(x + Chunk::width, y, z) : 0;
if(x >= Chunk::width) return neighbours[1] ? neighbours[1]->getBlockID(x - Chunk::width, y, z) : 0;
if(y < 0) return neighbours[2] ? neighbours[2]->getBlockID(x, y + Chunk::depth, z) : 0;
if(y >= Chunk::depth) return neighbours[3] ? neighbours[3]->getBlockID(x, y - Chunk::depth, z) : 0;
if(z < 0) return neighbours[4] ? neighbours[4]->getBlockID(x, y, z + Chunk::height) : 0;
if(z >= Chunk::height) return neighbours[5] ? neighbours[5]->getBlockID(x, y, z - Chunk::height) : 0;
return data[z][y][x] & 0xffff;
}
u16 getBlockParam(s8f x, s8f y, s8f z) const {
if(x < 0) return neighbours[0] ? neighbours[0]->getBlockParam(x + Chunk::width, y, z) : 0;
if(x >= Chunk::width) return neighbours[1] ? neighbours[1]->getBlockParam(x - Chunk::width, y, z) : 0;
if(y < 0) return neighbours[2] ? neighbours[2]->getBlockParam(x, y + Chunk::depth, z) : 0;
if(y >= Chunk::depth) return neighbours[3] ? neighbours[3]->getBlockParam(x, y - Chunk::depth, z) : 0;
if(z < 0) return neighbours[4] ? neighbours[4]->getBlockParam(x, y, z + Chunk::height) : 0;
if(z >= Chunk::height) return neighbours[5] ? neighbours[5]->getBlockParam(x, y, z - Chunk::height) : 0;
return (data[z][y][x] >> 16) & 0xffff;
}
u8 getTorchlight(s8f x, s8f y, s8f z) const {
if(x < 0) return neighbours[0] ? neighbours[0]->getTorchlight(x + Chunk::width, y, z) : 0;
if(x >= Chunk::width) return neighbours[1] ? neighbours[1]->getTorchlight(x - Chunk::width, y, z) : 0;
if(y < 0) return neighbours[2] ? neighbours[2]->getTorchlight(x, y + Chunk::depth, z) : 0;
if(y >= Chunk::depth) return neighbours[3] ? neighbours[3]->getTorchlight(x, y - Chunk::depth, z) : 0;
if(z < 0) return neighbours[4] ? neighbours[4]->getTorchlight(x, y, z + Chunk::height) : 0;
if(z >= Chunk::height) return neighbours[5] ? neighbours[5]->getTorchlight(x, y, z - Chunk::height) : 0;
return lightData[z][y][x] & 0xf;
}
u8 getSunlight(s8f x, s8f y, s8f z) const {
if(x < 0) return neighbours[0] ? neighbours[0]->getSunlight(x + Chunk::width, y, z) : 15;
if(x >= Chunk::width) return neighbours[1] ? neighbours[1]->getSunlight(x - Chunk::width, y, z) : 15;
if(y < 0) return neighbours[2] ? neighbours[2]->getSunlight(x, y + Chunk::depth, z) : 15;
if(y >= Chunk::depth) return neighbours[3] ? neighbours[3]->getSunlight(x, y - Chunk::depth, z) : 15;
if(z < 0) return neighbours[4] ? neighbours[4]->getSunlight(x, y, z + Chunk::height) : 15;
if(z >= Chunk::height) return neighbours[5] ? neighbours[5]->getSunlight(x, y, z - Chunk::height) : 15;
return (lightData[z][y][x] >> 4) & 0xf;
}
const BlockState *getBlockState(s8f x, s8f y, s8f z) const {
if (x >= 0 && x < CHUNK_WIDTH
&& y >= 0 && y < CHUNK_DEPTH
&& z >= 0 && z < CHUNK_HEIGHT) {
u16 blockID = getBlockID(x, y, z);
u16 blockParam = getBlockParam(x, y, z);
if(x < 0) return neighbours[0] ? neighbours[0]->getBlockState(x + Chunk::width, y, z) : nullptr;
if(x >= Chunk::width) return neighbours[1] ? neighbours[1]->getBlockState(x - Chunk::width, y, z) : nullptr;
if(y < 0) return neighbours[2] ? neighbours[2]->getBlockState(x, y + Chunk::depth, z) : nullptr;
if(y >= Chunk::depth) return neighbours[3] ? neighbours[3]->getBlockState(x, y - Chunk::depth, z) : nullptr;
if(z < 0) return neighbours[4] ? neighbours[4]->getBlockState(x, y, z + Chunk::height) : nullptr;
if(z >= Chunk::height) return neighbours[5] ? neighbours[5]->getBlockState(x, y, z - Chunk::height) : nullptr;
return &getBlockState(blockID, blockParam);
}
u16 blockID = getBlockID(x, y, z);
u16 blockParam = getBlockParam(x, y, z);
return nullptr;
return &getBlockState(blockID, blockParam);
}
static const BlockState &getBlockState(u16 blockID, u16 blockParam) {
const Block &block = Registry::getInstance().getBlock(blockID);
return block.getState(block.param().hasParam(BlockParam::State) ?
block.param().getParam(BlockParam::State, blockParam) : 0);
}
};
@ -69,6 +119,8 @@ struct ChunkMeshBuildingJob {
ChunkData chunkData;
std::array<std::optional<ChunkData>, 6> neighbourData;
VerticesArray vertices;
const TextureAtlas *textureAtlas;