Removed default values from VoxelDataMap

master
Marc Gilleron 2022-08-28 23:07:36 +01:00
parent b0e71e58ab
commit d2b20f676e
4 changed files with 24 additions and 29 deletions

View File

@ -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;

View File

@ -125,6 +125,8 @@ public:
void set_default_values(FixedArray<uint64_t, VoxelBufferInternal::MAX_CHANNELS> 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;
};

View File

@ -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<VoxelBufferInternal> buffer = make_shared_instance<VoxelBufferInternal>();
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);
}
}
}

View File

@ -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<uint64_t, VoxelBufferInternal::MAX_CHANNELS> _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