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]; Channel & channel = _channels[i];
if (channel.data) { if (channel.data) {
// TODO Optimize with realloc // TODO Optimize with realloc
delete_channel(i, _size); delete_channel(i);
create_channel(i, new_size); create_channel(i, new_size);
} }
} }
@ -35,19 +35,26 @@ void VoxelBuffer::clear() {
for (unsigned int i = 0; i < MAX_CHANNELS; ++i) { for (unsigned int i = 0; i < MAX_CHANNELS; ++i) {
Channel & channel = _channels[i]; Channel & channel = _channels[i];
if (channel.data) { if (channel.data) {
delete_channel(i, _size); delete_channel(i);
} }
} }
} }
void VoxelBuffer::clear_channel(unsigned int channel_index, int clear_value) { void VoxelBuffer::clear_channel(unsigned int channel_index, int clear_value) {
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS); 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; _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 { 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]; 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)); memcpy(channel.data, other_channel.data, get_volume() * sizeof(uint8_t));
} }
else if(channel.data) { else if(channel.data) {
delete_channel(channel_index, _size); delete_channel(channel_index);
} }
channel.defval = other_channel.defval; 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)); 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]; Channel & channel = _channels[i];
ERR_FAIL_COND(channel.data == NULL);
memfree(channel.data); memfree(channel.data);
channel.data = NULL; channel.data = NULL;
} }

View File

@ -25,6 +25,8 @@ public:
_FORCE_INLINE_ Vector3i get_size() const { return _size; } _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; 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(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); void set_voxel_v(int value, Vector3 pos, unsigned int channel_index = 0);
@ -62,7 +64,7 @@ public:
private: private:
void create_channel_noinit(int i, Vector3i size); void create_channel_noinit(int i, Vector3i size);
void create_channel(int i, Vector3i size, uint8_t defval=0); void create_channel(int i, Vector3i size, uint8_t defval=0);
void delete_channel(int i, Vector3i size); void delete_channel(int i);
protected: protected:
static void _bind_methods(); static void _bind_methods();

View File

@ -15,18 +15,15 @@ MeshInstance * VoxelBlock::get_mesh_instance(const Node & root) {
} }
// Helper // 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); VoxelBlock * block = memnew(VoxelBlock);
block->pos = bpos; block->pos = bpos;
if (buffer) {
const int bs = VoxelBlock::SIZE; block->voxels = buffer;
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->map = &map; //block->map = &map;
return block; 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) { void VoxelMap::set_voxel(int value, Vector3i pos, unsigned int c) {
Vector3i bpos = voxel_to_block(pos); Vector3i bpos = voxel_to_block(pos);
VoxelBlock * block = get_block(bpos); VoxelBlock * block = get_block(bpos);
if (block == NULL) { 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); set_block(bpos, block);
} }
block->voxels->set_voxel(value, pos - block_to_voxel(bpos), c); 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) { void VoxelMap::set_block(Vector3i bpos, VoxelBlock * block) {
ERR_FAIL_COND(block == NULL);
if (_last_accessed_block == NULL || _last_accessed_block->pos == bpos) { if (_last_accessed_block == NULL || _last_accessed_block->pos == bpos) {
_last_accessed_block = block; _last_accessed_block = block;
} }

View File

@ -17,7 +17,7 @@ public:
Vector3i pos; Vector3i pos;
NodePath mesh_instance_path; 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); MeshInstance * get_mesh_instance(const Node & root);

View File

@ -79,6 +79,7 @@ void VoxelTerrain::update_blocks() {
uint32_t max_time = 1000 / 60; uint32_t max_time = 1000 / 60;
while (!_block_update_queue.empty() && (os.get_ticks_msec() - time_before) < max_time) { 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 Move this to a thread
// TODO Have VoxelTerrainGenerator in C++ // TODO Have VoxelTerrainGenerator in C++
@ -88,37 +89,37 @@ void VoxelTerrain::update_blocks() {
Vector3i block_pos = _block_update_queue[_block_update_queue.size() - 1]; Vector3i block_pos = _block_update_queue[_block_update_queue.size() - 1];
if (!_map->has_block(block_pos)) { if (!_map->has_block(block_pos)) {
// Create buffer // 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()) { 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); _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 // Update meshes
ERR_FAIL_COND(buffer_ref->get_size() != block_size); Vector3i ndir;
for (ndir.z = -1; ndir.z < 2; ++ndir.z) {
// Store buffer for (ndir.x = -1; ndir.x < 2; ++ndir.x) {
_map->set_block_buffer(block_pos, buffer_ref); for (ndir.y = -1; ndir.y < 2; ++ndir.y) {
Vector3i npos = block_pos + ndir;
// Update meshes // TODO What if the map is really composed of empty blocks?
Vector3i ndir; if (_map->is_block_surrounded(npos)) {
for (ndir.z = -1; ndir.z < 2; ++ndir.z) { update_block_mesh(npos);
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_block_mesh(block_pos);
} }
//update_block_mesh(block_pos);
// Pop request // Pop request
_block_update_queue.resize(_block_update_queue.size() - 1); _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_block_update_count"), &VoxelTerrain::get_block_update_count);
ObjectTypeDB::bind_method(_MD("get_mesher:VoxelMesher"), &VoxelTerrain::get_mesher); 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? // 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("voxel_to_block", "voxel_pos"), &VoxelTerrain::_voxel_to_block_binding);
ObjectTypeDB::bind_method(_MD("block_to_voxel", "block_pos"), &VoxelTerrain::_block_to_voxel_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(); int get_block_update_count();
Ref<VoxelMesher> get_mesher() { return _mesher; } Ref<VoxelMesher> get_mesher() { return _mesher; }
Ref<VoxelMap> get_map() { return _map; }
protected: protected:
void _notification(int p_what); void _notification(int p_what);