-
-
Notifications
You must be signed in to change notification settings - Fork 253
/
voxel_terrain.h
208 lines (158 loc) · 6.18 KB
/
voxel_terrain.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#ifndef VOXEL_TERRAIN_H
#define VOXEL_TERRAIN_H
#include "../server/voxel_server.h"
#include "../storage/voxel_data_map.h"
#include "voxel_mesh_map.h"
#include "voxel_node.h"
#include <scene/3d/spatial.h>
class VoxelTool;
// Infinite paged terrain made of voxel blocks all with the same level of detail.
// Voxels are polygonized around the viewer by distance in a large cubic space.
// Data is streamed using a VoxelStream.
class VoxelTerrain : public VoxelNode {
GDCLASS(VoxelTerrain, VoxelNode)
public:
static const unsigned int MAX_VIEW_DISTANCE_FOR_LARGE_VOLUME = 512;
VoxelTerrain();
~VoxelTerrain();
void set_stream(Ref<VoxelStream> p_stream) override;
Ref<VoxelStream> get_stream() const override;
void set_generator(Ref<VoxelGenerator> p_generator) override;
Ref<VoxelGenerator> get_generator() const override;
void set_mesher(Ref<VoxelMesher> mesher) override;
Ref<VoxelMesher> get_mesher() const override;
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);
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(Box3i box_in_voxels);
void set_generate_collisions(bool enabled);
bool get_generate_collisions() const { return _generate_collisions; }
void set_collision_layer(int layer);
int get_collision_layer() const;
void set_collision_mask(int mask);
int get_collision_mask() const;
unsigned int get_max_view_distance() const;
void set_max_view_distance(unsigned int distance_in_voxels);
// TODO Make this obsolete with multi-viewers
void set_viewer_path(NodePath path);
NodePath get_viewer_path() const;
void set_material(unsigned int id, Ref<Material> material);
Ref<Material> get_material(unsigned int id) const;
VoxelDataMap &get_storage() { return _data_map; }
const VoxelDataMap &get_storage() const { return _data_map; }
Ref<VoxelTool> get_voxel_tool();
void set_run_stream_in_editor(bool enable);
bool is_stream_running_in_editor() const;
void set_bounds(Box3i box);
Box3i get_bounds() const;
void restart_stream() override;
void remesh_all_blocks() override;
// For convenience, this is actually stored in a particular type of mesher
Ref<VoxelLibrary> get_voxel_library() const;
struct Stats {
int updated_blocks = 0;
int dropped_block_loads = 0;
int dropped_block_meshs = 0;
int remaining_main_thread_blocks = 0;
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;
};
const Stats &get_stats() const;
struct BlockToSave {
Ref<VoxelBuffer> voxels;
Vector3i position;
};
protected:
void _notification(int p_what);
private:
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;
void _process();
void _on_stream_params_changed();
void _set_block_size_po2(int p_block_size_po2);
//void make_all_view_dirty();
void start_updater();
void stop_updater();
void start_streamer();
void stop_streamer();
void reset_map();
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);
void try_schedule_mesh_update_from_data(const Box3i &box_in_voxels);
void save_all_modified_blocks(bool with_copy);
void get_viewer_pos_and_direction(Vector3 &out_pos, Vector3 &out_direction) const;
void send_block_data_requests();
void emit_data_block_loaded(const VoxelDataBlock *block);
void emit_data_block_unloaded(const VoxelDataBlock *block);
bool try_get_paired_viewer_index(uint32_t id, size_t &out_i) const;
static void _bind_methods();
// Bindings
Vector3 _b_voxel_to_data_block(Vector3 pos) const;
Vector3 _b_data_block_to_voxel(Vector3 pos) const;
//void _force_load_blocks_binding(Vector3 center, Vector3 extents) { force_load_blocks(center, extents); }
void _b_save_modified_blocks();
void _b_save_block(Vector3 p_block_pos);
void _b_set_bounds(AABB aabb);
AABB _b_get_bounds() const;
Dictionary _b_get_statistics() const;
uint32_t _volume_id = 0;
VoxelServer::ReceptionBuffers _reception_buffers;
struct PairedViewer {
struct State {
Vector3i local_position_voxels;
Box3i data_box;
Box3i mesh_box;
int view_distance_voxels = 0;
bool requires_collisions = false;
bool requires_meshes = false;
};
uint32_t id;
State state;
State prev_state;
};
std::vector<PairedViewer> _paired_viewers;
// Voxel storage
VoxelDataMap _data_map;
// Mesh storage
VoxelMeshMap _mesh_map;
// 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.
Box3i _bounds_in_voxels;
Box3i _prev_bounds_in_voxels;
unsigned int _max_view_distance_voxels = 128;
// 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?
struct LoadingBlock {
VoxelRefCount viewers;
};
HashMap<Vector3i, LoadingBlock, Vector3iHasher> _loading_blocks;
std::vector<Vector3i> _blocks_pending_load;
std::vector<Vector3i> _blocks_pending_update;
std::vector<BlockToSave> _blocks_to_save;
Ref<VoxelStream> _stream;
Ref<VoxelMesher> _mesher;
Ref<VoxelGenerator> _generator;
bool _generate_collisions = true;
unsigned int _collision_layer = 1;
unsigned int _collision_mask = 1;
bool _run_stream_in_editor = true;
//bool _stream_enabled = false;
Ref<Material> _materials[VoxelMesherBlocky::MAX_MATERIALS];
Stats _stats;
};
#endif // VOXEL_TERRAIN_H