2016-05-10 01:59:54 +02:00
|
|
|
#ifndef VOXEL_TERRAIN_H
|
|
|
|
#define VOXEL_TERRAIN_H
|
|
|
|
|
2020-08-25 23:00:38 +01:00
|
|
|
#include "../server/voxel_server.h"
|
2021-05-31 16:27:08 +01:00
|
|
|
#include "../storage/voxel_data_map.h"
|
2021-04-13 23:48:35 +01:00
|
|
|
#include "voxel_mesh_map.h"
|
2020-12-18 22:58:41 +00:00
|
|
|
#include "voxel_node.h"
|
2018-09-25 00:54:07 +01:00
|
|
|
|
|
|
|
#include <scene/3d/spatial.h>
|
|
|
|
|
2019-09-08 19:42:25 +01:00
|
|
|
class VoxelTool;
|
2017-03-26 18:09:37 +02:00
|
|
|
|
2019-05-09 19:11:17 +01:00
|
|
|
// Infinite paged terrain made of voxel blocks all with the same level of detail.
|
2019-05-04 00:00:50 +01:00
|
|
|
// Voxels are polygonized around the viewer by distance in a large cubic space.
|
2019-05-25 16:07:38 +01:00
|
|
|
// Data is streamed using a VoxelStream.
|
2020-12-18 22:58:41 +00:00
|
|
|
class VoxelTerrain : public VoxelNode {
|
|
|
|
GDCLASS(VoxelTerrain, VoxelNode)
|
2016-05-10 01:59:54 +02:00
|
|
|
public:
|
2020-09-13 22:36:28 +01:00
|
|
|
static const unsigned int MAX_VIEW_DISTANCE_FOR_LARGE_VOLUME = 512;
|
|
|
|
|
2017-01-01 04:40:16 +01:00
|
|
|
VoxelTerrain();
|
2018-09-25 00:54:07 +01:00
|
|
|
~VoxelTerrain();
|
2016-05-10 01:59:54 +02:00
|
|
|
|
2020-12-18 22:58:41 +00:00
|
|
|
void set_stream(Ref<VoxelStream> p_stream) override;
|
|
|
|
Ref<VoxelStream> get_stream() const override;
|
2020-02-15 03:12:13 +08:00
|
|
|
|
2021-01-17 17:18:05 +00:00
|
|
|
void set_generator(Ref<VoxelGenerator> p_generator) override;
|
|
|
|
Ref<VoxelGenerator> get_generator() const override;
|
|
|
|
|
2020-12-18 22:58:41 +00:00
|
|
|
void set_mesher(Ref<VoxelMesher> mesher) override;
|
|
|
|
Ref<VoxelMesher> get_mesher() const override;
|
2017-08-15 02:24:52 +02:00
|
|
|
|
2021-04-13 23:48:35 +01:00
|
|
|
unsigned int get_data_block_size_pow2() const;
|
|
|
|
inline unsigned int get_data_block_size() const { return 1 << get_data_block_size_pow2(); }
|
|
|
|
void set_data_block_size_po2(unsigned int p_block_size_po2);
|
2019-08-24 01:44:27 +01:00
|
|
|
|
2021-04-13 23:48:35 +01:00
|
|
|
unsigned int get_mesh_block_size_pow2() const;
|
|
|
|
inline unsigned int get_mesh_block_size() const { return 1 << get_mesh_block_size_pow2(); }
|
2021-04-15 20:00:41 +01:00
|
|
|
void set_mesh_block_size(unsigned int p_block_size);
|
2021-04-13 23:48:35 +01:00
|
|
|
|
|
|
|
void post_edit_voxel(Vector3i pos);
|
2021-05-31 17:10:54 +01:00
|
|
|
void post_edit_area(Box3i box_in_voxels);
|
2016-05-10 01:59:54 +02:00
|
|
|
|
2017-03-26 18:09:37 +02:00
|
|
|
void set_generate_collisions(bool enabled);
|
2017-08-15 02:24:52 +02:00
|
|
|
bool get_generate_collisions() const { return _generate_collisions; }
|
|
|
|
|
2021-05-09 20:49:45 +01:00
|
|
|
void set_collision_layer(int layer);
|
|
|
|
int get_collision_layer() const;
|
|
|
|
|
|
|
|
void set_collision_mask(int mask);
|
|
|
|
int get_collision_mask() const;
|
|
|
|
|
2020-09-06 19:01:12 +01:00
|
|
|
unsigned int get_max_view_distance() const;
|
|
|
|
void set_max_view_distance(unsigned int distance_in_voxels);
|
2017-03-26 18:09:37 +02:00
|
|
|
|
2020-08-25 23:00:38 +01:00
|
|
|
// TODO Make this obsolete with multi-viewers
|
2017-03-28 00:56:01 +02:00
|
|
|
void set_viewer_path(NodePath path);
|
2017-08-15 02:24:52 +02:00
|
|
|
NodePath get_viewer_path() const;
|
|
|
|
|
2019-06-18 14:24:56 +09:00
|
|
|
void set_material(unsigned int id, Ref<Material> material);
|
|
|
|
Ref<Material> get_material(unsigned int id) const;
|
2017-03-28 00:56:01 +02:00
|
|
|
|
2021-04-13 23:48:35 +01:00
|
|
|
VoxelDataMap &get_storage() { return _data_map; }
|
|
|
|
const VoxelDataMap &get_storage() const { return _data_map; }
|
2020-11-21 18:28:06 +00:00
|
|
|
|
2019-09-08 19:42:25 +01:00
|
|
|
Ref<VoxelTool> get_voxel_tool();
|
2016-05-10 01:59:54 +02:00
|
|
|
|
2020-08-14 20:33:09 +01:00
|
|
|
void set_run_stream_in_editor(bool enable);
|
|
|
|
bool is_stream_running_in_editor() const;
|
|
|
|
|
2021-05-31 17:10:54 +01:00
|
|
|
void set_bounds(Box3i box);
|
|
|
|
Box3i get_bounds() const;
|
2020-09-13 22:36:28 +01:00
|
|
|
|
2020-12-18 22:58:41 +00:00
|
|
|
void restart_stream() override;
|
|
|
|
void remesh_all_blocks() override;
|
2020-12-18 21:01:50 +00:00
|
|
|
|
|
|
|
// For convenience, this is actually stored in a particular type of mesher
|
|
|
|
Ref<VoxelLibrary> get_voxel_library() const;
|
2020-08-14 20:33:09 +01:00
|
|
|
|
2018-09-25 00:54:07 +01:00
|
|
|
struct Stats {
|
2019-08-25 18:47:43 +01:00
|
|
|
int updated_blocks = 0;
|
|
|
|
int dropped_block_loads = 0;
|
|
|
|
int dropped_block_meshs = 0;
|
2021-01-16 13:05:50 +00:00
|
|
|
int remaining_main_thread_blocks = 0;
|
2021-02-18 19:50:47 +00:00
|
|
|
uint32_t time_detect_required_blocks = 0;
|
|
|
|
uint32_t time_request_blocks_to_load = 0;
|
|
|
|
uint32_t time_process_load_responses = 0;
|
|
|
|
uint32_t time_request_blocks_to_update = 0;
|
|
|
|
uint32_t time_process_update_responses = 0;
|
2018-09-25 00:54:07 +01:00
|
|
|
};
|
|
|
|
|
2020-12-25 17:08:40 +00:00
|
|
|
const Stats &get_stats() const;
|
|
|
|
|
2020-08-26 19:49:30 +01:00
|
|
|
struct BlockToSave {
|
|
|
|
Ref<VoxelBuffer> voxels;
|
|
|
|
Vector3i position;
|
|
|
|
};
|
|
|
|
|
2016-05-10 01:59:54 +02:00
|
|
|
protected:
|
2017-01-01 04:40:16 +01:00
|
|
|
void _notification(int p_what);
|
2017-03-28 00:56:01 +02:00
|
|
|
|
|
|
|
private:
|
2017-08-15 02:24:52 +02:00
|
|
|
bool _set(const StringName &p_name, const Variant &p_value);
|
|
|
|
bool _get(const StringName &p_name, Variant &r_ret) const;
|
|
|
|
void _get_property_list(List<PropertyInfo> *p_list) const;
|
|
|
|
|
2017-01-01 04:40:16 +01:00
|
|
|
void _process();
|
2016-05-10 01:59:54 +02:00
|
|
|
|
2019-08-24 01:44:27 +01:00
|
|
|
void _on_stream_params_changed();
|
|
|
|
void _set_block_size_po2(int p_block_size_po2);
|
2021-04-13 23:48:35 +01:00
|
|
|
//void make_all_view_dirty();
|
2019-08-24 01:44:27 +01:00
|
|
|
void start_updater();
|
|
|
|
void stop_updater();
|
|
|
|
void start_streamer();
|
|
|
|
void stop_streamer();
|
|
|
|
void reset_map();
|
2017-08-15 02:24:52 +02:00
|
|
|
|
2021-04-13 23:48:35 +01:00
|
|
|
void view_data_block(Vector3i bpos);
|
|
|
|
void view_mesh_block(Vector3i bpos, bool mesh_flag, bool collision_flag);
|
|
|
|
void unview_data_block(Vector3i bpos);
|
|
|
|
void unview_mesh_block(Vector3i bpos, bool mesh_flag, bool collision_flag);
|
|
|
|
void unload_data_block(Vector3i bpos);
|
|
|
|
void unload_mesh_block(Vector3i bpos);
|
|
|
|
//void make_data_block_dirty(Vector3i bpos);
|
|
|
|
void try_schedule_mesh_update(VoxelMeshBlock *block);
|
2021-05-31 17:10:54 +01:00
|
|
|
void try_schedule_mesh_update_from_data(const Box3i &box_in_voxels);
|
2020-09-06 19:01:12 +01:00
|
|
|
|
2019-05-28 00:40:09 +01:00
|
|
|
void save_all_modified_blocks(bool with_copy);
|
2019-09-07 21:19:12 +01:00
|
|
|
void get_viewer_pos_and_direction(Vector3 &out_pos, Vector3 &out_direction) const;
|
2019-06-02 01:59:39 +01:00
|
|
|
void send_block_data_requests();
|
2017-08-28 01:47:38 +02:00
|
|
|
|
2021-04-13 23:48:35 +01:00
|
|
|
void emit_data_block_loaded(const VoxelDataBlock *block);
|
|
|
|
void emit_data_block_unloaded(const VoxelDataBlock *block);
|
2020-08-10 20:57:03 +01:00
|
|
|
|
2020-09-06 19:01:12 +01:00
|
|
|
bool try_get_paired_viewer_index(uint32_t id, size_t &out_i) const;
|
|
|
|
|
2017-01-01 04:40:16 +01:00
|
|
|
static void _bind_methods();
|
2016-05-10 01:59:54 +02:00
|
|
|
|
2019-09-08 19:42:25 +01:00
|
|
|
// Bindings
|
2021-04-13 23:48:35 +01:00
|
|
|
Vector3 _b_voxel_to_data_block(Vector3 pos) const;
|
|
|
|
Vector3 _b_data_block_to_voxel(Vector3 pos) const;
|
2018-09-25 00:54:07 +01:00
|
|
|
//void _force_load_blocks_binding(Vector3 center, Vector3 extents) { force_load_blocks(center, extents); }
|
2020-07-25 16:29:16 +01:00
|
|
|
void _b_save_modified_blocks();
|
|
|
|
void _b_save_block(Vector3 p_block_pos);
|
2020-09-13 22:36:28 +01:00
|
|
|
void _b_set_bounds(AABB aabb);
|
|
|
|
AABB _b_get_bounds() const;
|
2020-12-25 17:08:40 +00:00
|
|
|
Dictionary _b_get_statistics() const;
|
2018-09-25 00:54:07 +01:00
|
|
|
|
2020-08-25 23:00:38 +01:00
|
|
|
uint32_t _volume_id = 0;
|
|
|
|
VoxelServer::ReceptionBuffers _reception_buffers;
|
|
|
|
|
2020-09-06 19:01:12 +01:00
|
|
|
struct PairedViewer {
|
|
|
|
struct State {
|
2021-04-13 23:48:35 +01:00
|
|
|
Vector3i local_position_voxels;
|
2021-05-31 17:10:54 +01:00
|
|
|
Box3i data_box;
|
|
|
|
Box3i mesh_box;
|
2021-04-13 23:48:35 +01:00
|
|
|
int view_distance_voxels = 0;
|
2020-09-09 18:58:58 +01:00
|
|
|
bool requires_collisions = false;
|
|
|
|
bool requires_meshes = false;
|
2020-09-06 19:01:12 +01:00
|
|
|
};
|
|
|
|
uint32_t id;
|
|
|
|
State state;
|
|
|
|
State prev_state;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<PairedViewer> _paired_viewers;
|
|
|
|
|
2017-01-02 02:19:02 +01:00
|
|
|
// Voxel storage
|
2021-04-13 23:48:35 +01:00
|
|
|
VoxelDataMap _data_map;
|
|
|
|
// Mesh storage
|
|
|
|
VoxelMeshMap _mesh_map;
|
2017-01-02 02:19:02 +01:00
|
|
|
|
2020-09-13 22:36:28 +01:00
|
|
|
// Area within which voxels can exist.
|
|
|
|
// Note, these bounds might not be exactly represented. This volume is chunk-based, so the result will be
|
|
|
|
// approximated to the closest chunk.
|
2021-05-31 17:10:54 +01:00
|
|
|
Box3i _bounds_in_voxels;
|
|
|
|
Box3i _prev_bounds_in_voxels;
|
2020-09-13 22:36:28 +01:00
|
|
|
|
2021-04-13 23:48:35 +01:00
|
|
|
unsigned int _max_view_distance_voxels = 128;
|
2017-08-15 02:24:52 +02:00
|
|
|
|
2017-03-28 00:56:01 +02:00
|
|
|
// TODO Terrains only need to handle the visible portion of voxels, which reduces the bounds blocks to handle.
|
|
|
|
// Therefore, could a simple grid be better to use than a hashmap?
|
|
|
|
|
2020-09-06 19:01:12 +01:00
|
|
|
struct LoadingBlock {
|
2021-04-15 20:16:27 +01:00
|
|
|
VoxelRefCount viewers;
|
2020-09-06 19:01:12 +01:00
|
|
|
};
|
2017-04-06 23:44:11 +02:00
|
|
|
|
2020-09-06 19:01:12 +01:00
|
|
|
HashMap<Vector3i, LoadingBlock, Vector3iHasher> _loading_blocks;
|
|
|
|
std::vector<Vector3i> _blocks_pending_load;
|
|
|
|
std::vector<Vector3i> _blocks_pending_update;
|
2020-08-26 19:49:30 +01:00
|
|
|
std::vector<BlockToSave> _blocks_to_save;
|
2019-05-28 00:40:09 +01:00
|
|
|
|
2019-05-25 16:07:38 +01:00
|
|
|
Ref<VoxelStream> _stream;
|
2020-12-18 21:01:50 +00:00
|
|
|
Ref<VoxelMesher> _mesher;
|
2021-01-17 17:18:05 +00:00
|
|
|
Ref<VoxelGenerator> _generator;
|
2017-01-02 02:19:02 +01:00
|
|
|
|
2019-08-25 13:04:49 +01:00
|
|
|
bool _generate_collisions = true;
|
2021-05-09 20:49:45 +01:00
|
|
|
unsigned int _collision_layer = 1;
|
|
|
|
unsigned int _collision_mask = 1;
|
2020-08-14 20:33:09 +01:00
|
|
|
bool _run_stream_in_editor = true;
|
2020-09-13 22:36:28 +01:00
|
|
|
//bool _stream_enabled = false;
|
2017-03-26 18:09:37 +02:00
|
|
|
|
2019-04-28 17:58:29 +01:00
|
|
|
Ref<Material> _materials[VoxelMesherBlocky::MAX_MATERIALS];
|
2018-09-25 00:54:07 +01:00
|
|
|
|
|
|
|
Stats _stats;
|
2016-05-10 01:59:54 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // VOXEL_TERRAIN_H
|