Removed default values from VoxelDataMap
parent
b0e71e58ab
commit
d2b20f676e
|
@ -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() {
|
VoxelBufferInternal::VoxelBufferInternal() {
|
||||||
// Minecraft uses way more than 255 block types and there is room for eventual metadata such as rotation
|
// 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;
|
_channels[CHANNEL_TYPE].depth = DEFAULT_TYPE_CHANNEL_DEPTH;
|
||||||
|
|
|
@ -125,6 +125,8 @@ public:
|
||||||
|
|
||||||
void set_default_values(FixedArray<uint64_t, VoxelBufferInternal::MAX_CHANNELS> values);
|
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;
|
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);
|
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.
|
// 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.
|
// 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?)
|
// 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;
|
RWLock _rw_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,8 @@
|
||||||
namespace zylann::voxel {
|
namespace zylann::voxel {
|
||||||
|
|
||||||
VoxelDataMap::VoxelDataMap() {
|
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);
|
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() {
|
VoxelDataMap::~VoxelDataMap() {
|
||||||
|
@ -55,7 +48,7 @@ int VoxelDataMap::get_voxel(Vector3i pos, unsigned int c) const {
|
||||||
Vector3i bpos = voxel_to_block(pos);
|
Vector3i bpos = voxel_to_block(pos);
|
||||||
const VoxelDataBlock *block = get_block(bpos);
|
const VoxelDataBlock *block = get_block(bpos);
|
||||||
if (block == nullptr || !block->has_voxels()) {
|
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());
|
RWLockRead lock(block->get_voxels_const().get_lock());
|
||||||
return block->get_voxels_const().get_voxel(to_local(pos), c);
|
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) {
|
VoxelDataBlock *VoxelDataMap::create_default_block(Vector3i bpos) {
|
||||||
std::shared_ptr<VoxelBufferInternal> buffer = make_shared_instance<VoxelBufferInternal>();
|
std::shared_ptr<VoxelBufferInternal> buffer = make_shared_instance<VoxelBufferInternal>();
|
||||||
buffer->create(_block_size, _block_size, _block_size);
|
buffer->create(_block_size, _block_size, _block_size);
|
||||||
buffer->set_default_values(_default_voxel);
|
//buffer->set_default_values(_default_voxel);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
ZN_ASSERT_RETURN_V(!has_block(bpos), nullptr);
|
ZN_ASSERT_RETURN_V(!has_block(bpos), nullptr);
|
||||||
#endif
|
#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
|
// TODO The generator needs to be invoked if the block has no voxels
|
||||||
if (block == nullptr || !block->has_voxels()) {
|
if (block == nullptr || !block->has_voxels()) {
|
||||||
// TODO Not valid for a float return value
|
// TODO Not valid for a float return value
|
||||||
return _default_voxel[c];
|
return VoxelBufferInternal::get_default_value_static(c);
|
||||||
}
|
}
|
||||||
Vector3i lpos = to_local(pos);
|
Vector3i lpos = to_local(pos);
|
||||||
RWLockRead lock(block->get_voxels_const().get_lock());
|
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);
|
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) {
|
VoxelDataBlock *VoxelDataMap::get_block(Vector3i bpos) {
|
||||||
auto it = _blocks_map.find(bpos);
|
auto it = _blocks_map.find(bpos);
|
||||||
if (it != _blocks_map.end()) {
|
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];
|
const uint8_t channel = channels[ci];
|
||||||
// For now, inexistent blocks default to hardcoded defaults, corresponding to "empty space".
|
// 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.
|
// 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,
|
dst_buffer.fill_area(VoxelBufferInternal::get_default_value_static(channel),
|
||||||
src_block_origin - min_pos + block_size_v, channel);
|
src_block_origin - min_pos, src_block_origin - min_pos + block_size_v, channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,9 +68,6 @@ public:
|
||||||
float get_voxel_f(Vector3i pos, unsigned int c = VoxelBufferInternal::CHANNEL_SDF) const;
|
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_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 {
|
inline void copy(Vector3i min_pos, VoxelBufferInternal &dst_buffer, unsigned int channels_mask) const {
|
||||||
copy(min_pos, dst_buffer, channels_mask, nullptr, nullptr);
|
copy(min_pos, dst_buffer, channels_mask, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -186,9 +183,6 @@ private:
|
||||||
void set_block_size_pow2(unsigned int p);
|
void set_block_size_pow2(unsigned int p);
|
||||||
|
|
||||||
private:
|
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.
|
// Blocks stored with a spatial hash in all 3D directions.
|
||||||
// This is dual storage: map and vector, for fast lookup and also fast iteration.
|
// 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
|
// Before I used Godot's HashMap with RELATIONSHIP = 2 because that delivers better performance compared to
|
||||||
|
|
Loading…
Reference in New Issue