#ifndef VOXEL_LOD_TERRAIN_HPP #define VOXEL_LOD_TERRAIN_HPP #include "../streams/voxel_stream.h" #include "lod_octree.h" #include "voxel_data_loader.h" #include "voxel_map.h" #include "voxel_mesh_updater.h" #include #include class VoxelMap; // Paged terrain made of voxel blocks of variable level of detail. // Designed for highest view distances, preferably using smooth voxels. // Voxels are polygonized around the viewer by distance in a very large sphere, usually extending beyond far clip. // Data is streamed using a VoxelStream, which must support LOD. class VoxelLodTerrain : public Spatial { GDCLASS(VoxelLodTerrain, Spatial) public: static const int MAX_LOD = 32; VoxelLodTerrain(); ~VoxelLodTerrain(); Ref get_material() const; void set_material(Ref p_material); Ref get_stream() const; void set_stream(Ref p_stream); int get_view_distance() const; void set_view_distance(unsigned int p_distance_in_voxels); void set_lod_split_scale(float p_lod_split_scale); float get_lod_split_scale() const; void set_lod_count(int p_lod_count); int get_lod_count() const; void set_generate_collisions(bool enabled); bool get_generate_collisions() const { return _generate_collisions; } // Sets up to which amount of LODs collision will generate. -1 means all of them. void set_collision_lod_count(int lod_count); int get_collision_lod_count() const; void set_viewer_path(NodePath path); NodePath get_viewer_path() const; int get_block_region_extent() const; Dictionary get_block_info(Vector3 fbpos, int lod_index) const; Vector3 voxel_to_block_position(Vector3 vpos, int lod_index) const; unsigned int get_block_size_pow2() const; void set_block_size_po2(unsigned int p_block_size_po2); struct Stats { VoxelMeshUpdater::Stats updater; VoxelDataLoader::Stats stream; int blocked_lods = 0; int updated_blocks = 0; int dropped_block_loads = 0; int dropped_block_meshs = 0; uint64_t time_detect_required_blocks = 0; uint64_t time_request_blocks_to_load = 0; uint64_t time_process_load_responses = 0; uint64_t time_request_blocks_to_update = 0; uint64_t time_process_update_responses = 0; }; Dictionary get_statistics() const; protected: static void _bind_methods(); void _notification(int p_what); void _process(); private: unsigned int get_block_size() const; void make_all_view_dirty_deferred(); Spatial *get_viewer() const; void immerge_block(Vector3i block_pos, int lod_index); void start_updater(); void stop_updater(); void start_streamer(); void stop_streamer(); void reset_maps(); Vector3 get_viewer_pos(Vector3 &out_direction) const; void try_schedule_loading_with_neighbors(const Vector3i &p_bpos, int lod_index); bool check_block_loaded_and_updated(const Vector3i &p_bpos, int lod_index); void _set_lod_count(int p_lod_count); void _set_block_size_po2(int p_block_size_po2); void _on_stream_params_changed(); template void for_all_blocks(A &action) { for (int lod_index = 0; lod_index < MAX_LOD; ++lod_index) { if (_lods[lod_index].map.is_valid()) { _lods[lod_index].map->for_all_blocks(action); } } } struct OctreeItem { LodOctree octree; #ifdef TOOLS_ENABLED Spatial *debug_box = nullptr; #endif }; #ifdef TOOLS_ENABLED void create_octree_debug_box(OctreeItem &item, Vector3i pos); void destroy_octree_debug_box(OctreeItem &item, Vector3i pos); #endif // This terrain type is a sparse grid of octrees. // Indexed by a grid coordinate whose step is the size of the highest-LOD block // This octree doesn't hold any data... hence bool. Map _lod_octrees; // In which octree the viewer was on last frame Vector3i _last_viewer_octree_position; unsigned int _last_octree_region_extent = 0; NodePath _viewer_path; Ref _stream; VoxelDataLoader *_stream_thread = nullptr; VoxelMeshUpdater *_block_updater = nullptr; std::vector _blocks_pending_main_thread_update; Ref _material; bool _generate_collisions = true; int _collision_lod_count = -1; // Each LOD works in a set of coordinates spanning 2x more voxels the higher their index is struct Lod { Ref map; Set loading_blocks; std::vector blocks_pending_update; // These are relative to this LOD, in block coordinates Vector3i last_viewer_block_pos; int last_view_distance_blocks = 0; // Members for memory caching std::vector blocks_to_load; #ifdef TOOLS_ENABLED // TODO Debug, may be removed in the future HashMap debug_unexpected_load_drop_time; #endif }; Lod _lods[MAX_LOD]; int _lod_count = 0; float _lod_split_scale = 0.f; unsigned int _view_distance_voxels = 512; Stats _stats; }; #endif // VOXEL_LOD_TERRAIN_HPP