From 06a399f932407b7083b2af9823fb8faa92ad7b51 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Thu, 5 Jan 2017 02:39:40 +0100 Subject: [PATCH] Fixed set_voxel() and block force_update_blocks() --- voxel_buffer.cpp | 20 ++++++++++++++------ voxel_buffer.h | 4 +++- voxel_map.cpp | 29 ++++++++++++++++++----------- voxel_map.h | 2 +- voxel_terrain.cpp | 47 +++++++++++++++++++++++++---------------------- voxel_terrain.h | 1 + 6 files changed, 62 insertions(+), 41 deletions(-) diff --git a/voxel_buffer.cpp b/voxel_buffer.cpp index 7f9fe3e..6f93289 100644 --- a/voxel_buffer.cpp +++ b/voxel_buffer.cpp @@ -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; } diff --git a/voxel_buffer.h b/voxel_buffer.h index 125d450..7481c4b 100644 --- a/voxel_buffer.h +++ b/voxel_buffer.h @@ -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(); diff --git a/voxel_map.cpp b/voxel_map.cpp index a3c97d9..5feef21 100644 --- a/voxel_map.cpp +++ b/voxel_map.cpp @@ -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 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(buffer); + + block->voxels = buffer; //block->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 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; } diff --git a/voxel_map.h b/voxel_map.h index ba2b67c..cb78f94 100644 --- a/voxel_map.h +++ b/voxel_map.h @@ -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 buffer); MeshInstance * get_mesh_instance(const Node & root); diff --git a/voxel_terrain.cpp b/voxel_terrain.cpp index e6c26c3..cfc8f7d 100644 --- a/voxel_terrain.cpp +++ b/voxel_terrain.cpp @@ -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 buffer_ref = Ref(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 buffer_ref = Ref(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); diff --git a/voxel_terrain.h b/voxel_terrain.h index 469e329..5becc20 100644 --- a/voxel_terrain.h +++ b/voxel_terrain.h @@ -20,6 +20,7 @@ public: int get_block_update_count(); Ref get_mesher() { return _mesher; } + Ref get_map() { return _map; } protected: void _notification(int p_what);