Fixed set_voxel() and block force_update_blocks()

This commit is contained in:
Marc Gilleron 2017-01-05 02:39:40 +01:00
parent d3ab015c67
commit 06a399f932
6 changed files with 62 additions and 41 deletions

View File

@ -23,7 +23,7 @@ void VoxelBuffer::create(int sx, int sy, int sz) {
Channel & channel = _channels[i];
if (channel.data) {
// TODO Optimize with realloc
delete_channel(i, _size);
delete_channel(i);
create_channel(i, new_size);
}
}
@ -35,19 +35,26 @@ void VoxelBuffer::clear() {
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
Channel & channel = _channels[i];
if (channel.data) {
delete_channel(i, _size);
delete_channel(i);
}
}
}
void VoxelBuffer::clear_channel(unsigned int channel_index, int clear_value) {
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
delete_channel(channel_index, _size);
if(_channels[channel_index].data)
delete_channel(channel_index);
_channels[channel_index].defval = clear_value;
}
void VoxelBuffer::set_default_values(uint8_t values[VoxelBuffer::MAX_CHANNELS]) {
for(unsigned int i = 0; i < MAX_CHANNELS; ++i) {
_channels[i].defval = values[i];
}
}
int VoxelBuffer::get_voxel(int x, int y, int z, unsigned int channel_index) const {
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, 0);
ERR_FAIL_INDEX_V(channel_index, MAX_CHANNELS, 0);
const Channel & channel = _channels[channel_index];
@ -156,7 +163,7 @@ void VoxelBuffer::copy_from(const VoxelBuffer & other, unsigned int channel_inde
memcpy(channel.data, other_channel.data, get_volume() * sizeof(uint8_t));
}
else if(channel.data) {
delete_channel(channel_index, _size);
delete_channel(channel_index);
}
channel.defval = other_channel.defval;
@ -223,8 +230,9 @@ void VoxelBuffer::create_channel_noinit(int i, Vector3i size) {
channel.data = (uint8_t*)memalloc(volume * sizeof(uint8_t));
}
void VoxelBuffer::delete_channel(int i, Vector3i size) {
void VoxelBuffer::delete_channel(int i) {
Channel & channel = _channels[i];
ERR_FAIL_COND(channel.data == NULL);
memfree(channel.data);
channel.data = NULL;
}

View File

@ -25,6 +25,8 @@ public:
_FORCE_INLINE_ Vector3i get_size() const { return _size; }
void set_default_values(uint8_t values[MAX_CHANNELS]);
int get_voxel(int x, int y, int z, unsigned int channel_index=0) const;
void set_voxel(int value, int x, int y, int z, unsigned int channel_index=0);
void set_voxel_v(int value, Vector3 pos, unsigned int channel_index = 0);
@ -62,7 +64,7 @@ public:
private:
void create_channel_noinit(int i, Vector3i size);
void create_channel(int i, Vector3i size, uint8_t defval=0);
void delete_channel(int i, Vector3i size);
void delete_channel(int i);
protected:
static void _bind_methods();

View File

@ -15,18 +15,15 @@ MeshInstance * VoxelBlock::get_mesh_instance(const Node & root) {
}
// Helper
VoxelBlock * VoxelBlock::create(Vector3i bpos, VoxelBuffer * buffer) {
VoxelBlock * VoxelBlock::create(Vector3i bpos, Ref<VoxelBuffer> buffer) {
const int bs = VoxelBlock::SIZE;
ERR_FAIL_COND_V(buffer.is_null(), NULL);
ERR_FAIL_COND_V(buffer->get_size() != Vector3i(bs, bs, bs), NULL);
VoxelBlock * block = memnew(VoxelBlock);
block->pos = bpos;
if (buffer) {
const int bs = VoxelBlock::SIZE;
ERR_FAIL_COND_V(buffer->get_size() != Vector3i(bs, bs, bs), NULL);
}
else {
buffer = memnew(VoxelBuffer);
}
ERR_FAIL_COND_V(buffer == NULL, NULL);
block->voxels = Ref<VoxelBuffer>(buffer);
block->voxels = buffer;
//block->map = &map;
return block;
}
@ -58,12 +55,21 @@ int VoxelMap::get_voxel(Vector3i pos, unsigned int c) {
}
void VoxelMap::set_voxel(int value, Vector3i pos, unsigned int c) {
Vector3i bpos = voxel_to_block(pos);
VoxelBlock * block = get_block(bpos);
if (block == NULL) {
block = VoxelBlock::create(bpos);
Ref<VoxelBuffer> buffer(memnew(VoxelBuffer));
buffer->create(VoxelBlock::SIZE, VoxelBlock::SIZE, VoxelBlock::SIZE);
buffer->set_default_values(_default_voxel);
block = VoxelBlock::create(bpos, buffer);
set_block(bpos, block);
}
block->voxels->set_voxel(value, pos - block_to_voxel(bpos), c);
}
@ -90,6 +96,7 @@ VoxelBlock * VoxelMap::get_block(Vector3i bpos) {
}
void VoxelMap::set_block(Vector3i bpos, VoxelBlock * block) {
ERR_FAIL_COND(block == NULL);
if (_last_accessed_block == NULL || _last_accessed_block->pos == bpos) {
_last_accessed_block = block;
}

View File

@ -17,7 +17,7 @@ public:
Vector3i pos;
NodePath mesh_instance_path;
static VoxelBlock * create(Vector3i bpos, VoxelBuffer * buffer = 0);
static VoxelBlock * create(Vector3i bpos, Ref<VoxelBuffer> buffer);
MeshInstance * get_mesh_instance(const Node & root);

View File

@ -79,6 +79,7 @@ void VoxelTerrain::update_blocks() {
uint32_t max_time = 1000 / 60;
while (!_block_update_queue.empty() && (os.get_ticks_msec() - time_before) < max_time) {
//printf("Remaining: %i\n", _block_update_queue.size());
// TODO Move this to a thread
// TODO Have VoxelTerrainGenerator in C++
@ -88,37 +89,37 @@ void VoxelTerrain::update_blocks() {
Vector3i block_pos = _block_update_queue[_block_update_queue.size() - 1];
if (!_map->has_block(block_pos)) {
// Create buffer
Ref<VoxelBuffer> buffer_ref = Ref<VoxelBuffer>(memnew(VoxelBuffer));
const Vector3i block_size(VoxelBlock::SIZE, VoxelBlock::SIZE, VoxelBlock::SIZE);
buffer_ref->create(block_size.x, block_size.y, block_size.z);
// Query voxel provider
if(!_provider.is_null()) {
Ref<VoxelBuffer> buffer_ref = Ref<VoxelBuffer>(memnew(VoxelBuffer));
const Vector3i block_size(VoxelBlock::SIZE, VoxelBlock::SIZE, VoxelBlock::SIZE);
buffer_ref->create(block_size.x, block_size.y, block_size.z);
// Query voxel provider
_provider->emerge_block(buffer_ref, block_pos);
// Check script return
ERR_FAIL_COND(buffer_ref->get_size() != block_size);
// Store buffer
_map->set_block_buffer(block_pos, buffer_ref);
}
}
// Check script return
ERR_FAIL_COND(buffer_ref->get_size() != block_size);
// Store buffer
_map->set_block_buffer(block_pos, buffer_ref);
// Update meshes
Vector3i ndir;
for (ndir.z = -1; ndir.z < 2; ++ndir.z) {
for (ndir.x = -1; ndir.x < 2; ++ndir.x) {
for (ndir.y = -1; ndir.y < 2; ++ndir.y) {
Vector3i npos = block_pos + ndir;
if (_map->is_block_surrounded(npos)) {
update_block_mesh(npos);
}
// Update meshes
Vector3i ndir;
for (ndir.z = -1; ndir.z < 2; ++ndir.z) {
for (ndir.x = -1; ndir.x < 2; ++ndir.x) {
for (ndir.y = -1; ndir.y < 2; ++ndir.y) {
Vector3i npos = block_pos + ndir;
// TODO What if the map is really composed of empty blocks?
if (_map->is_block_surrounded(npos)) {
update_block_mesh(npos);
}
}
}
//update_block_mesh(block_pos);
}
//update_block_mesh(block_pos);
// Pop request
_block_update_queue.resize(_block_update_queue.size() - 1);
@ -191,6 +192,8 @@ void VoxelTerrain::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_block_update_count"), &VoxelTerrain::get_block_update_count);
ObjectTypeDB::bind_method(_MD("get_mesher:VoxelMesher"), &VoxelTerrain::get_mesher);
ObjectTypeDB::bind_method(_MD("get_map:VoxelMap"), &VoxelTerrain::get_map);
// TODO Make those two static in VoxelMap?
ObjectTypeDB::bind_method(_MD("voxel_to_block", "voxel_pos"), &VoxelTerrain::_voxel_to_block_binding);
ObjectTypeDB::bind_method(_MD("block_to_voxel", "block_pos"), &VoxelTerrain::_block_to_voxel_binding);

View File

@ -20,6 +20,7 @@ public:
int get_block_update_count();
Ref<VoxelMesher> get_mesher() { return _mesher; }
Ref<VoxelMap> get_map() { return _map; }
protected:
void _notification(int p_what);