godot_voxel/voxel_terrain.h

133 lines
3.6 KiB
C
Raw Normal View History

#ifndef VOXEL_TERRAIN_H
#define VOXEL_TERRAIN_H
#include "vector3i.h"
#include "zprofiling.h"
#include "voxel_provider.h"
#include "voxel_provider_thread.h"
#include "voxel_mesh_updater.h"
#include "rect3i.h"
#include <scene/3d/spatial.h>
class VoxelMap;
class VoxelLibrary;
2017-03-26 18:09:37 +02:00
// Infinite static terrain made of voxels.
// It is loaded around VoxelTerrainStreamers.
class VoxelTerrain : public Spatial /*, public IVoxelMapObserver*/ {
GDCLASS(VoxelTerrain, Spatial)
public:
2017-01-01 04:40:16 +01:00
VoxelTerrain();
~VoxelTerrain();
void set_provider(Ref<VoxelProvider> provider);
Ref<VoxelProvider> get_provider() const;
void set_voxel_library(Ref<VoxelLibrary> library);
Ref<VoxelLibrary> get_voxel_library() const;
void make_block_dirty(Vector3i bpos);
//void make_blocks_dirty(Vector3i min, Vector3i size);
void make_voxel_dirty(Vector3i pos);
bool is_block_dirty(Vector3i bpos) const;
2017-03-26 18:09:37 +02:00
void set_generate_collisions(bool enabled);
bool get_generate_collisions() const { return _generate_collisions; }
int get_view_distance() const;
void set_view_distance(int distance_in_voxels);
2017-03-26 18:09:37 +02:00
void set_viewer_path(NodePath path);
NodePath get_viewer_path() const;
void set_material(int id, Ref<Material> material);
Ref<Material> get_material(int id) const;
Ref<VoxelMap> get_map() { return _map; }
struct Stats {
VoxelMeshUpdater::Stats updater;
VoxelProviderThread::Stats provider;
uint32_t mesh_alloc_time;
uint32_t updated_blocks;
Stats(): mesh_alloc_time(0), updated_blocks(0)
{ }
};
protected:
2017-01-01 04:40:16 +01:00
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;
2017-01-01 04:40:16 +01:00
void _process();
void make_all_view_dirty_deferred();
enum BlockDirtyState {
BLOCK_LOAD,
BLOCK_UPDATE
};
Spatial *get_viewer(NodePath path) const;
void immerge_block(Vector3i bpos);
Dictionary get_statistics() const;
2017-01-01 04:40:16 +01:00
static void _bind_methods();
2017-01-01 04:40:16 +01:00
// Convenience
2017-08-20 15:17:54 +02:00
Vector3 _voxel_to_block_binding(Vector3 pos);
Vector3 _block_to_voxel_binding(Vector3 pos);
//void _force_load_blocks_binding(Vector3 center, Vector3 extents) { force_load_blocks(center, extents); }
//void _make_block_dirty_binding(Vector3 bpos) { make_block_dirty(bpos); }
//void _make_blocks_dirty_binding(Vector3 min, Vector3 size) { make_blocks_dirty(min, size); }
void _make_voxel_dirty_binding(Vector3 pos) { make_voxel_dirty(pos); }
2017-03-26 20:07:01 +02:00
Variant _raycast_binding(Vector3 origin, Vector3 direction, real_t max_distance);
void set_voxel(Vector3 pos, int value, int c);
int get_voxel(Vector3 pos, int c);
void clear_block_update_state(Vector3i block_pos);
static void remove_positions_outside_box(Vector<Vector3i> &positions, Rect3i box, HashMap<Vector3i, BlockDirtyState, Vector3iHasher> &state_map);
2017-01-02 02:19:02 +01:00
private:
// Voxel storage
Ref<VoxelMap> _map;
// How many blocks to load around the viewer
int _view_distance_blocks;
// 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?
Vector<Vector3i> _blocks_pending_load;
Vector<Vector3i> _blocks_pending_update;
HashMap<Vector3i, BlockDirtyState, Vector3iHasher> _dirty_blocks; // only the key is relevant
2017-01-02 02:19:02 +01:00
Ref<VoxelProvider> _provider;
VoxelProviderThread *_provider_thread;
Ref<VoxelLibrary> _library;
VoxelMeshUpdater *_block_updater;
2017-01-02 02:19:02 +01:00
NodePath _viewer_path;
Vector3i _last_viewer_block_pos;
int _last_view_distance_blocks;
2017-03-26 18:09:37 +02:00
bool _generate_collisions;
Ref<Material> _materials[VoxelMesher::MAX_MATERIALS];
Stats _stats;
};
#endif // VOXEL_TERRAIN_H