VoxelEngine/src/voxels/Chunk.cpp

129 lines
2.9 KiB
C++

#include "Chunk.h"
#include <memory>
#include "voxel.h"
#include "../content/ContentLUT.h"
#include "../lighting/Lightmap.h"
Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
bottom = 0;
top = CHUNK_H;
voxels = new voxel[CHUNK_VOL];
for (size_t i = 0; i < CHUNK_VOL; i++) {
voxels[i].id = 2;
voxels[i].states = 0;
}
lightmap = new Lightmap();
renderData.vertices = nullptr;
}
Chunk::~Chunk(){
delete lightmap;
delete[] voxels;
}
bool Chunk::isEmpty(){
int id = -1;
for (size_t i = 0; i < CHUNK_VOL; i++){
if (voxels[i].id != id){
if (id != -1)
return false;
else
id = voxels[i].id;
}
}
return true;
}
void Chunk::updateHeights() {
for (size_t i = 0; i < CHUNK_VOL; i++) {
if (voxels[i].id != 0) {
bottom = i / (CHUNK_D * CHUNK_W);
break;
}
}
for (int i = CHUNK_VOL - 1; i >= 0; i--) {
if (voxels[i].id != 0) {
top = i / (CHUNK_D * CHUNK_W) + 1;
break;
}
}
}
Chunk* Chunk::clone() const {
Chunk* other = new Chunk(x,z);
for (size_t i = 0; i < CHUNK_VOL; i++)
other->voxels[i] = voxels[i];
other->lightmap->set(lightmap);
return other;
}
/**
Current chunk format:
- byte-order: big-endian
- [don't panic!] first and second bytes are separated for RLE efficiency
```cpp
uint8_t voxel_id_first_byte[CHUNK_VOL];
uint8_t voxel_id_second_byte[CHUNK_VOL];
uint8_t voxel_states_first_byte[CHUNK_VOL];
uint8_t voxel_states_second_byte[CHUNK_VOL];
```
Total size: (CHUNK_VOL * 4) bytes
*/
ubyte* Chunk::encode() const {
ubyte* buffer = new ubyte[CHUNK_DATA_LEN];
for (size_t i = 0; i < CHUNK_VOL; i++) {
buffer[i] = voxels[i].id >> 8;
buffer[CHUNK_VOL+i] = voxels[i].id & 0xFF;
buffer[CHUNK_VOL*2 + i] = voxels[i].states >> 8;
buffer[CHUNK_VOL*3 + i] = voxels[i].states & 0xFF;
}
return buffer;
}
/**
* @return true if all is fine
**/
bool Chunk::decode(ubyte* data) {
for (size_t i = 0; i < CHUNK_VOL; i++) {
voxel& vox = voxels[i];
ubyte bid1 = data[i];
ubyte bid2 = data[CHUNK_VOL + i];
ubyte bst1 = data[CHUNK_VOL*2 + i];
ubyte bst2 = data[CHUNK_VOL*3 + i];
vox.id = (blockid_t(bid1) << 8) | (blockid_t(bid2));
vox.states = (blockstate_t(bst1) << 8) | (blockstate_t(bst2));
}
return true;
}
/*
* Convert chunk voxels data from 16 bit to 32 bit
*/
void Chunk::fromOld(ubyte* data) {
for (size_t i = 0; i < CHUNK_VOL; i++) {
data[i + CHUNK_VOL*3] = data[i + CHUNK_VOL];
data[i + CHUNK_VOL] = data[i];
data[i + CHUNK_VOL*2] = 0;
data[i] = 0;
}
}
void Chunk::convert(ubyte* data, const ContentLUT* lut) {
for (size_t i = 0; i < CHUNK_VOL; i++) {
// see encode method to understand what the hell is going on here
blockid_t id = ((blockid_t(data[i]) << 8) |
blockid_t(data[CHUNK_VOL+i]));
blockid_t replacement = lut->getBlockId(id);
data[i] = replacement >> 8;
data[CHUNK_VOL+i] = replacement & 0xFF;
}
}