Fix VoxelInstancer not refreshing when an item is modified (picked from 2d7d09534a72dc749bcb62fce6c49314fb499688)

This commit is contained in:
Marc Gilleron 2022-01-08 00:16:15 +00:00
parent f50148cacd
commit c69e820eb6
2 changed files with 14 additions and 10 deletions

View File

@ -62,6 +62,8 @@ public:
Array surface_arrays,
const Transform &block_local_transform,
UpMode up_mode,
// When generating a 2x2x2 data block area, bits in `octant_mask` tell which octant should be generated.
// Bits set to zero will cause all instances in the corresponding octant to not be generated.
uint8_t octant_mask,
float block_size);

View File

@ -365,7 +365,7 @@ void VoxelInstancer::regenerate_layer(uint16_t layer_id, bool regenerate_blocks)
// Can be treated like a bool too.
static inline uint8_t has_edited_block(const Lod &lod, Vector3i pos) {
return lod.modified_blocks.has(pos) ||
lod.loaded_instances_data.find(pos) != lod.loaded_instances_data.end();
lod.loaded_instances_data.find(pos) != lod.loaded_instances_data.end();
}
static inline void extract_octant_transforms(
@ -398,6 +398,7 @@ void VoxelInstancer::regenerate_layer(uint16_t layer_id, bool regenerate_blocks)
const int lod_index = block->lod_index;
const Lod &lod = _lods[lod_index];
// Each bit means "should this octant be generated". If 0, it means it was edited and should not change
uint8_t octant_mask = 0xff;
if (render_to_data_factor == 1) {
if (L::has_edited_block(lod, block->grid_position)) {
@ -406,16 +407,17 @@ void VoxelInstancer::regenerate_layer(uint16_t layer_id, bool regenerate_blocks)
}
} else if (render_to_data_factor == 2) {
// The rendering block corresponds to 8 smaller data blocks
octant_mask = 0;
uint8_t edited_mask = 0;
const Vector3i data_pos0 = block->grid_position * render_to_data_factor;
octant_mask |= L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y, data_pos0.z));
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y, data_pos0.z)) << 1);
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y + 1, data_pos0.z)) << 2);
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y + 1, data_pos0.z)) << 3);
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y, data_pos0.z + 1)) << 4);
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y, data_pos0.z + 1)) << 5);
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y + 1, data_pos0.z + 1)) << 6);
octant_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y + 1, data_pos0.z + 1)) << 7);
edited_mask |= L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y, data_pos0.z));
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y, data_pos0.z)) << 1);
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y + 1, data_pos0.z)) << 2);
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y + 1, data_pos0.z)) << 3);
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y, data_pos0.z + 1)) << 4);
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y, data_pos0.z + 1)) << 5);
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x, data_pos0.y + 1, data_pos0.z + 1)) << 6);
edited_mask |= (L::has_edited_block(lod, Vector3i(data_pos0.x + 1, data_pos0.y + 1, data_pos0.z + 1)) << 7);
octant_mask = ~edited_mask;
if (octant_mask == 0) {
// All data blocks were edited, no regen on the whole render block
continue;