Better fix for VoxelLodTerrain task drop
parent
54eb228444
commit
2dfcc76600
|
@ -140,9 +140,10 @@ int VoxelServer::get_priority(const PriorityDependency &dep, uint8_t lod, float
|
|||
return priority;
|
||||
}
|
||||
|
||||
uint32_t VoxelServer::add_volume(ReceptionBuffers *buffers) {
|
||||
uint32_t VoxelServer::add_volume(ReceptionBuffers *buffers, VolumeType type) {
|
||||
CRASH_COND(buffers == nullptr);
|
||||
Volume volume;
|
||||
volume.type = type;
|
||||
volume.reception_buffers = buffers;
|
||||
volume.meshing_dependency = gd_make_shared<MeshingDependency>();
|
||||
return _world.volumes.create(volume);
|
||||
|
@ -184,9 +185,9 @@ void VoxelServer::set_volume_voxel_library(uint32_t volume_id, Ref<VoxelLibrary>
|
|||
volume.meshing_dependency->library = volume.voxel_library;
|
||||
}
|
||||
|
||||
void VoxelServer::set_volume_cancellable_requests(uint32_t volume_id, bool cancellable) {
|
||||
void VoxelServer::set_volume_octree_split_scale(uint32_t volume_id, float split_scale) {
|
||||
Volume &volume = _world.volumes.get(volume_id);
|
||||
volume.cancellable_requests = cancellable;
|
||||
volume.octree_split_scale = split_scale;
|
||||
}
|
||||
|
||||
void VoxelServer::invalidate_volume_mesh_requests(uint32_t volume_id) {
|
||||
|
@ -207,7 +208,27 @@ void VoxelServer::init_priority_dependency(
|
|||
const float block_radius = (volume.block_size << lod) / 2;
|
||||
dep.shared = _world.shared_priority_dependency;
|
||||
dep.world_position = volume.transform.xform(voxel_pos.to_vec3());
|
||||
dep.radius = volume.transform.basis.xform(Vector3(block_radius, block_radius, block_radius)).length();
|
||||
const float transformed_block_radius =
|
||||
volume.transform.basis.xform(Vector3(block_radius, block_radius, block_radius)).length();
|
||||
|
||||
switch (volume.type) {
|
||||
case VOLUME_SPARSE_GRID:
|
||||
// Distance beyond which no field of view can overlap the block
|
||||
dep.drop_distance_squared =
|
||||
squared(_world.shared_priority_dependency->highest_view_distance + transformed_block_radius);
|
||||
break;
|
||||
|
||||
case VOLUME_SPARSE_OCTREE:
|
||||
// Distance beyond which it is safe to drop a block without risking to block LOD subdivision.
|
||||
// This does not depend on viewer's view distance, but on LOD precision instead.
|
||||
dep.drop_distance_squared = squared(2.f * transformed_block_radius *
|
||||
get_octree_lod_block_region_extent(volume.octree_split_scale));
|
||||
break;
|
||||
|
||||
default:
|
||||
CRASH_NOW_MSG("Unexpected type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelServer::request_block_mesh(uint32_t volume_id, BlockMeshInput &input) {
|
||||
|
@ -221,7 +242,6 @@ void VoxelServer::request_block_mesh(uint32_t volume_id, BlockMeshInput &input)
|
|||
r->blocks = input.blocks;
|
||||
r->position = input.position;
|
||||
r->lod = input.lod;
|
||||
r->cancellable = volume.cancellable_requests;
|
||||
|
||||
r->smooth_enabled = volume.stream->get_used_channels_mask() & (1 << VoxelBuffer::CHANNEL_SDF);
|
||||
r->blocky_enabled = volume.voxel_library.is_valid() &&
|
||||
|
@ -246,7 +266,6 @@ void VoxelServer::request_block_load(uint32_t volume_id, Vector3i block_pos, int
|
|||
r.lod = lod;
|
||||
r.type = BlockDataRequest::TYPE_LOAD;
|
||||
r.block_size = volume.block_size;
|
||||
r.cancellable = volume.cancellable_requests;
|
||||
|
||||
r.stream_dependency = volume.stream_dependency;
|
||||
|
||||
|
@ -564,10 +583,7 @@ int VoxelServer::BlockDataRequest::get_priority() {
|
|||
}
|
||||
float closest_viewer_distance_sq;
|
||||
const int p = VoxelServer::get_priority(priority_dependency, lod, &closest_viewer_distance_sq);
|
||||
if (cancellable) {
|
||||
const float closest_viewer_distance = Math::sqrt(closest_viewer_distance_sq);
|
||||
too_far = closest_viewer_distance > priority_dependency.radius + priority_dependency.shared->highest_view_distance;
|
||||
}
|
||||
too_far = closest_viewer_distance_sq > priority_dependency.drop_distance_squared;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -662,10 +678,7 @@ void VoxelServer::BlockMeshRequest::run(VoxelTaskContext ctx) {
|
|||
int VoxelServer::BlockMeshRequest::get_priority() {
|
||||
float closest_viewer_distance_sq;
|
||||
const int p = VoxelServer::get_priority(priority_dependency, lod, &closest_viewer_distance_sq);
|
||||
if (cancellable) {
|
||||
const float closest_viewer_distance = Math::sqrt(closest_viewer_distance_sq);
|
||||
too_far = closest_viewer_distance > priority_dependency.radius + priority_dependency.shared->highest_view_distance;
|
||||
}
|
||||
too_far = closest_viewer_distance_sq > priority_dependency.drop_distance_squared;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,11 @@ public:
|
|||
bool is_default = false;
|
||||
};
|
||||
|
||||
enum VolumeType {
|
||||
VOLUME_SPARSE_GRID,
|
||||
VOLUME_SPARSE_OCTREE
|
||||
};
|
||||
|
||||
static VoxelServer *get_singleton();
|
||||
static void create_singleton();
|
||||
static void destroy_singleton();
|
||||
|
@ -73,18 +78,20 @@ public:
|
|||
VoxelServer();
|
||||
~VoxelServer();
|
||||
|
||||
uint32_t add_volume(ReceptionBuffers *buffers);
|
||||
// TODO Rename functions to C convention
|
||||
uint32_t add_volume(ReceptionBuffers *buffers, VolumeType type);
|
||||
void set_volume_transform(uint32_t volume_id, Transform t);
|
||||
void set_volume_block_size(uint32_t volume_id, uint32_t block_size);
|
||||
void set_volume_stream(uint32_t volume_id, Ref<VoxelStream> stream);
|
||||
void set_volume_voxel_library(uint32_t volume_id, Ref<VoxelLibrary> library);
|
||||
void set_volume_cancellable_requests(uint32_t volume_id, bool cancellable);
|
||||
void set_volume_octree_split_scale(uint32_t volume_id, float split_scale);
|
||||
void invalidate_volume_mesh_requests(uint32_t volume_id);
|
||||
void request_block_mesh(uint32_t volume_id, BlockMeshInput &input);
|
||||
void request_block_load(uint32_t volume_id, Vector3i block_pos, int lod);
|
||||
void request_block_save(uint32_t volume_id, Ref<VoxelBuffer> voxels, Vector3i block_pos, int lod);
|
||||
void remove_volume(uint32_t volume_id);
|
||||
|
||||
// TODO Rename functions to C convention
|
||||
uint32_t add_viewer();
|
||||
void remove_viewer(uint32_t viewer_id);
|
||||
void set_viewer_position(uint32_t viewer_id, Vector3 position);
|
||||
|
@ -109,6 +116,13 @@ public:
|
|||
void process();
|
||||
void wait_and_clear_all_tasks(bool warn);
|
||||
|
||||
static inline int get_octree_lod_block_region_extent(float split_scale) {
|
||||
// This is a bounding radius of blocks around a viewer within which we may load them.
|
||||
// It depends on the LOD split scale, which tells how close to a block we need to be for it to subdivide.
|
||||
// Each LOD is fractal so that value is the same for each of them, multiplied by 2^lod.
|
||||
return static_cast<int>(split_scale) * 2 + 2;
|
||||
}
|
||||
|
||||
private:
|
||||
Dictionary _b_get_stats();
|
||||
|
||||
|
@ -139,15 +153,15 @@ private:
|
|||
};
|
||||
|
||||
struct Volume {
|
||||
VolumeType type;
|
||||
ReceptionBuffers *reception_buffers = nullptr;
|
||||
Transform transform;
|
||||
Ref<VoxelStream> stream;
|
||||
Ref<VoxelLibrary> voxel_library;
|
||||
uint32_t block_size = 16;
|
||||
float octree_split_scale = 0;
|
||||
std::shared_ptr<StreamingDependency> stream_dependency;
|
||||
std::shared_ptr<MeshingDependency> meshing_dependency;
|
||||
// TODO Workaround for VoxelLodTerrain, which doesnt support this well atm
|
||||
bool cancellable_requests = true;
|
||||
};
|
||||
|
||||
struct PriorityDependencyShared {
|
||||
|
@ -170,7 +184,8 @@ private:
|
|||
struct PriorityDependency {
|
||||
std::shared_ptr<PriorityDependencyShared> shared;
|
||||
Vector3 world_position; // TODO Won't update while in queue. Can it be bad?
|
||||
float radius;
|
||||
// If the closest viewer is further away than this distance, the request can be cancelled as not worth it
|
||||
float drop_distance_squared;
|
||||
};
|
||||
|
||||
void init_priority_dependency(PriorityDependency &dep, Vector3i block_position, uint8_t lod, const Volume &volume);
|
||||
|
@ -195,7 +210,6 @@ private:
|
|||
uint8_t type;
|
||||
bool has_run = false;
|
||||
bool too_far = false;
|
||||
bool cancellable = true;
|
||||
PriorityDependency priority_dependency;
|
||||
std::shared_ptr<StreamingDependency> stream_dependency;
|
||||
// TODO Find a way to separate save, it doesnt need sorting
|
||||
|
@ -215,7 +229,6 @@ private:
|
|||
bool blocky_enabled;
|
||||
bool has_run = false;
|
||||
bool too_far = false;
|
||||
bool cancellable = true;
|
||||
PriorityDependency priority_dependency;
|
||||
std::shared_ptr<MeshingDependency> meshing_dependency;
|
||||
VoxelMesher::Output blocky_surfaces_output;
|
||||
|
|
|
@ -56,8 +56,8 @@ VoxelLodTerrain::VoxelLodTerrain() {
|
|||
|
||||
PRINT_VERBOSE("Construct VoxelLodTerrain");
|
||||
|
||||
_volume_id = VoxelServer::get_singleton()->add_volume(&_reception_buffers);
|
||||
VoxelServer::get_singleton()->set_volume_cancellable_requests(_volume_id, false);
|
||||
_volume_id = VoxelServer::get_singleton()->add_volume(&_reception_buffers, VoxelServer::VOLUME_SPARSE_OCTREE);
|
||||
VoxelServer::get_singleton()->set_volume_octree_split_scale(_volume_id, get_lod_split_scale());
|
||||
|
||||
_lods[0].map.instance();
|
||||
|
||||
|
@ -310,6 +310,8 @@ void VoxelLodTerrain::set_lod_split_scale(float p_lod_split_scale) {
|
|||
// Because `set_split_scale` may clamp it...
|
||||
_lod_split_scale = item.octree.get_split_scale();
|
||||
}
|
||||
|
||||
VoxelServer::get_singleton()->set_volume_octree_split_scale(_volume_id, get_lod_split_scale());
|
||||
}
|
||||
|
||||
float VoxelLodTerrain::get_lod_split_scale() const {
|
||||
|
@ -398,10 +400,7 @@ NodePath VoxelLodTerrain::get_viewer_path() const {
|
|||
}
|
||||
|
||||
int VoxelLodTerrain::get_block_region_extent() const {
|
||||
// This is the radius of blocks around the viewer in which we may load them.
|
||||
// It depends on the LOD split scale, which tells how close to a block we need to be for it to subdivide.
|
||||
// Each LOD is fractal so that value is the same for each of them.
|
||||
return static_cast<int>(_lod_split_scale) * 2 + 2;
|
||||
return VoxelServer::get_octree_lod_block_region_extent(_lod_split_scale);
|
||||
}
|
||||
|
||||
Vector3 VoxelLodTerrain::voxel_to_block_position(Vector3 vpos, int lod_index) const {
|
||||
|
|
|
@ -24,7 +24,7 @@ VoxelTerrain::VoxelTerrain() {
|
|||
// Infinite by default
|
||||
_bounds_in_voxels = Rect3i::from_center_extents(Vector3i(0), Vector3i(MAX_EXTENT));
|
||||
|
||||
_volume_id = VoxelServer::get_singleton()->add_volume(&_reception_buffers);
|
||||
_volume_id = VoxelServer::get_singleton()->add_volume(&_reception_buffers, VoxelServer::VOLUME_SPARSE_GRID);
|
||||
|
||||
_map.instance();
|
||||
|
||||
|
|
Loading…
Reference in New Issue