From d2b20f676ef861eb41694dde09936057f10c05c2 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Sun, 28 Aug 2022 23:07:36 +0100 Subject: [PATCH] Removed default values from VoxelDataMap --- storage/voxel_buffer_internal.cpp | 15 +++++++++++++++ storage/voxel_buffer_internal.h | 3 +++ storage/voxel_data_map.cpp | 29 ++++++----------------------- storage/voxel_data_map.h | 6 ------ 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/storage/voxel_buffer_internal.cpp b/storage/voxel_buffer_internal.cpp index f6cab3d3..732b6a4e 100644 --- a/storage/voxel_buffer_internal.cpp +++ b/storage/voxel_buffer_internal.cpp @@ -106,6 +106,21 @@ inline real_t raw_voxel_to_real(uint64_t value, VoxelBufferInternal::Depth depth } } +namespace { +uint64_t g_default_values[VoxelBufferInternal::MAX_CHANNELS] = { + 0, // TYPE + snorm_to_s16(1.f), // SDF + encode_indices_to_packed_u16(0, 1, 2, 3), // INDICES + encode_weights_to_packed_u16(15, 0, 0, 0), // WEIGHTS + 0, 0, 0, 0 // +}; +} + +uint64_t VoxelBufferInternal::get_default_value_static(unsigned int channel_index) { + ZN_ASSERT(channel_index < MAX_CHANNELS); + return g_default_values[channel_index]; +} + VoxelBufferInternal::VoxelBufferInternal() { // Minecraft uses way more than 255 block types and there is room for eventual metadata such as rotation _channels[CHANNEL_TYPE].depth = DEFAULT_TYPE_CHANNEL_DEPTH; diff --git a/storage/voxel_buffer_internal.h b/storage/voxel_buffer_internal.h index 59e208e8..3e791d7d 100644 --- a/storage/voxel_buffer_internal.h +++ b/storage/voxel_buffer_internal.h @@ -125,6 +125,8 @@ public: void set_default_values(FixedArray values); + static uint64_t get_default_value_static(unsigned int channel_index); + uint64_t get_voxel(int x, int y, int z, unsigned int channel_index) const; void set_voxel(uint64_t value, int x, int y, int z, unsigned int channel_index); @@ -505,6 +507,7 @@ private: // TODO It may be preferable to actually move away from storing an RWLock in every buffer in the future. // We should be able to find a solution because very few of these locks are actually used at a given time. // It worked so far on PC but other platforms like the PS5 might have a pretty low limit (8K?) + // Also it's a heavy data structure, on Windows sizeof(RWLock) is 244. RWLock _rw_lock; }; diff --git a/storage/voxel_data_map.cpp b/storage/voxel_data_map.cpp index b60a956a..748000b2 100644 --- a/storage/voxel_data_map.cpp +++ b/storage/voxel_data_map.cpp @@ -10,15 +10,8 @@ namespace zylann::voxel { VoxelDataMap::VoxelDataMap() { - // TODO Make it configurable in editor (with all necessary notifications and updatings!) + // This is not planned to change at runtime at the moment. set_block_size_pow2(constants::DEFAULT_BLOCK_SIZE_PO2); - - // Pick same defaults as VoxelBuffer - VoxelBufferInternal b; - b.create(1, 1, 1); - for (unsigned int channel_index = 0; channel_index < VoxelBufferInternal::MAX_CHANNELS; ++channel_index) { - _default_voxel[channel_index] = b.get_voxel(0, 0, 0, channel_index); - } } VoxelDataMap::~VoxelDataMap() { @@ -55,7 +48,7 @@ int VoxelDataMap::get_voxel(Vector3i pos, unsigned int c) const { Vector3i bpos = voxel_to_block(pos); const VoxelDataBlock *block = get_block(bpos); if (block == nullptr || !block->has_voxels()) { - return _default_voxel[c]; + return VoxelBufferInternal::get_default_value_static(c); } RWLockRead lock(block->get_voxels_const().get_lock()); return block->get_voxels_const().get_voxel(to_local(pos), c); @@ -64,7 +57,7 @@ int VoxelDataMap::get_voxel(Vector3i pos, unsigned int c) const { VoxelDataBlock *VoxelDataMap::create_default_block(Vector3i bpos) { std::shared_ptr buffer = make_shared_instance(); buffer->create(_block_size, _block_size, _block_size); - buffer->set_default_values(_default_voxel); + //buffer->set_default_values(_default_voxel); #ifdef DEBUG_ENABLED ZN_ASSERT_RETURN_V(!has_block(bpos), nullptr); #endif @@ -99,7 +92,7 @@ float VoxelDataMap::get_voxel_f(Vector3i pos, unsigned int c) const { // TODO The generator needs to be invoked if the block has no voxels if (block == nullptr || !block->has_voxels()) { // TODO Not valid for a float return value - return _default_voxel[c]; + return VoxelBufferInternal::get_default_value_static(c); } Vector3i lpos = to_local(pos); RWLockRead lock(block->get_voxels_const().get_lock()); @@ -116,16 +109,6 @@ void VoxelDataMap::set_voxel_f(real_t value, Vector3i pos, unsigned int c) { voxels.set_voxel_f(value, lpos.x, lpos.y, lpos.z, c); } -void VoxelDataMap::set_default_voxel(int value, unsigned int channel) { - ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBufferInternal::MAX_CHANNELS); - _default_voxel[channel] = value; -} - -int VoxelDataMap::get_default_voxel(unsigned int channel) { - ZN_ASSERT_RETURN_V(channel >= 0 && channel < VoxelBufferInternal::MAX_CHANNELS, 0); - return _default_voxel[channel]; -} - VoxelDataBlock *VoxelDataMap::get_block(Vector3i bpos) { auto it = _blocks_map.find(bpos); if (it != _blocks_map.end()) { @@ -251,8 +234,8 @@ void VoxelDataMap::copy(Vector3i min_pos, VoxelBufferInternal &dst_buffer, unsig const uint8_t channel = channels[ci]; // For now, inexistent blocks default to hardcoded defaults, corresponding to "empty space". // If we want to change this, we may have to add an API for that. - dst_buffer.fill_area(_default_voxel[channel], src_block_origin - min_pos, - src_block_origin - min_pos + block_size_v, channel); + dst_buffer.fill_area(VoxelBufferInternal::get_default_value_static(channel), + src_block_origin - min_pos, src_block_origin - min_pos + block_size_v, channel); } } } diff --git a/storage/voxel_data_map.h b/storage/voxel_data_map.h index 84fbc19c..ec20fb70 100644 --- a/storage/voxel_data_map.h +++ b/storage/voxel_data_map.h @@ -68,9 +68,6 @@ public: float get_voxel_f(Vector3i pos, unsigned int c = VoxelBufferInternal::CHANNEL_SDF) const; void set_voxel_f(real_t value, Vector3i pos, unsigned int c = VoxelBufferInternal::CHANNEL_SDF); - void set_default_voxel(int value, unsigned int channel = 0); - int get_default_voxel(unsigned int channel = 0); - inline void copy(Vector3i min_pos, VoxelBufferInternal &dst_buffer, unsigned int channels_mask) const { copy(min_pos, dst_buffer, channels_mask, nullptr, nullptr); } @@ -186,9 +183,6 @@ private: void set_block_size_pow2(unsigned int p); private: - // Voxel values that will be returned if access is out of map bounds - FixedArray _default_voxel; - // Blocks stored with a spatial hash in all 3D directions. // This is dual storage: map and vector, for fast lookup and also fast iteration. // Before I used Godot's HashMap with RELATIONSHIP = 2 because that delivers better performance compared to