Added mesh block size setter to VoxelTerrain

This commit is contained in:
Marc Gilleron 2021-04-15 20:00:41 +01:00
parent 1449560f29
commit f7d0039811
2 changed files with 67 additions and 0 deletions

View File

@ -155,6 +155,44 @@ unsigned int VoxelTerrain::get_mesh_block_size_pow2() const {
return _mesh_map.get_block_size_pow2();
}
void VoxelTerrain::set_mesh_block_size(unsigned int mesh_block_size) {
mesh_block_size = clamp(mesh_block_size, get_data_block_size(), VoxelConstants::MAX_BLOCK_SIZE);
unsigned int po2;
switch (mesh_block_size) {
case 16:
po2 = 4;
break;
case 32:
po2 = 5;
break;
default:
mesh_block_size = 16;
po2 = 4;
break;
}
if (mesh_block_size == get_mesh_block_size()) {
return;
}
// Unload all mesh blocks regardless of refcount
_mesh_map.create(po2, 0);
// Make paired viewers re-view the new meshable area
for (unsigned int i = 0; i < _paired_viewers.size(); ++i) {
PairedViewer &viewer = _paired_viewers[i];
// Resetting both because it's a re-initialization.
// We could also be doing that before or after their are shifted.
viewer.state.mesh_box = Rect3i();
viewer.prev_state.mesh_box = Rect3i();
}
VoxelServer::get_singleton()->set_volume_render_block_size(_volume_id, mesh_block_size);
// No update on bounds because we can support a mismatch, as long as it is a multiple of data block size
//set_bounds(_bounds_in_voxels);
}
void VoxelTerrain::restart_stream() {
_on_stream_params_changed();
}
@ -353,6 +391,11 @@ void VoxelTerrain::view_mesh_block(Vector3i bpos, bool mesh_flag, bool collision
block->viewers.add(false, mesh_flag, collision_flag);
// This is needed in case a viewer wants to view meshes in places data blocks are already present.
// Before that, meshes were updated only when a data block was loaded or modified,
// so changing block size or viewer flags did not make meshes appear.
try_schedule_mesh_update(block);
/*if (mesh_flag) {
viewers.add(VoxelViewerRefCount::TYPE_MESH);
if (viewers.get(VoxelViewerRefCount::TYPE_MESH) == 1) {
@ -1046,6 +1089,21 @@ void VoxelTerrain::_process() {
}
};
/*if (_reset_mesh_views_scheduled) {
// Pretend mesh view was empty last frame so meshes will get reloaded.
// It should work since the logic that sets this flag also clears all mesh blocks,
// but let's reset the map to be sure since there is room for something to happen in between.
if (_mesh_map.get_block_count() > 0) {
WARN_PRINT("Mesh map not empty after having scheduled a mesh view reset");
_mesh_map.clear();
}
_reset_mesh_views_scheduled = false;
for (auto it = _paired_viewers.begin(); it != _paired_viewers.end(); ++it) {
PairedViewer &p = *it;
p.prev_state.mesh_box = Rect3i();
}
}*/
// New viewers and updates
UpdatePairedViewer u{ *this, bounds_in_blocks, world_to_local_transform, view_distance_scale };
VoxelServer::get_singleton()->for_each_viewer(u);
@ -1071,6 +1129,8 @@ void VoxelTerrain::_process() {
const Rect3i &prev_data_box = viewer.prev_state.data_box;
if (prev_data_box != new_data_box) {
VOXEL_PROFILE_SCOPE();
// Unview blocks that just fell out of range
prev_data_box.difference(new_data_box, [this, &viewer](Rect3i out_of_range_box) {
out_of_range_box.for_each_cell([this, &viewer](Vector3i bpos) {
@ -1093,6 +1153,8 @@ void VoxelTerrain::_process() {
const Rect3i &prev_mesh_box = viewer.prev_state.mesh_box;
if (prev_mesh_box != new_mesh_box) {
VOXEL_PROFILE_SCOPE();
// Unview blocks that just fell out of range
prev_mesh_box.difference(new_mesh_box, [this, &viewer](Rect3i out_of_range_box) {
out_of_range_box.for_each_cell([this, &viewer](Vector3i bpos) {
@ -1620,6 +1682,9 @@ void VoxelTerrain::_bind_methods() {
ClassDB::bind_method(D_METHOD("voxel_to_data_block", "voxel_pos"), &VoxelTerrain::_b_voxel_to_data_block);
ClassDB::bind_method(D_METHOD("data_block_to_voxel", "block_pos"), &VoxelTerrain::_b_data_block_to_voxel);
ClassDB::bind_method(D_METHOD("get_mesh_block_size"), &VoxelTerrain::get_mesh_block_size);
ClassDB::bind_method(D_METHOD("set_mesh_block_size", "size"), &VoxelTerrain::set_mesh_block_size);
ClassDB::bind_method(D_METHOD("get_statistics"), &VoxelTerrain::_b_get_statistics);
ClassDB::bind_method(D_METHOD("get_voxel_tool"), &VoxelTerrain::get_voxel_tool);
@ -1650,6 +1715,7 @@ void VoxelTerrain::_bind_methods() {
// TODO Should probably be in the parent class?
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "run_stream_in_editor"),
"set_run_stream_in_editor", "is_stream_running_in_editor");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mesh_block_size"), "set_mesh_block_size", "get_mesh_block_size");
// TODO Add back access to block, but with an API securing multithreaded access
ADD_SIGNAL(MethodInfo(VoxelStringNames::get_singleton()->block_loaded,

View File

@ -36,6 +36,7 @@ public:
unsigned int get_mesh_block_size_pow2() const;
inline unsigned int get_mesh_block_size() const { return 1 << get_mesh_block_size_pow2(); }
void set_mesh_block_size(unsigned int p_block_size);
void post_edit_voxel(Vector3i pos);
void post_edit_area(Rect3i box_in_voxels);