103 lines
2.7 KiB
C++
103 lines
2.7 KiB
C++
#ifndef VOXEL_MESH_SDF_GD_H
|
|
#define VOXEL_MESH_SDF_GD_H
|
|
|
|
#include "../storage/voxel_buffer_gd.h"
|
|
#include "../util/math/vector3f.h"
|
|
|
|
#include <core/io/resource.h>
|
|
|
|
class Mesh;
|
|
class SceneTree;
|
|
|
|
namespace zylann::voxel {
|
|
|
|
// Contains the baked signed distance field of a mesh, which can be used to sculpt terrain.
|
|
// TODO Make it a resource so we can pre-build, save and load the baked data more easily
|
|
class VoxelMeshSDF : public Resource {
|
|
GDCLASS(VoxelMeshSDF, Resource)
|
|
public:
|
|
enum BakeMode { //
|
|
BAKE_MODE_ACCURATE_NAIVE,
|
|
BAKE_MODE_ACCURATE_PARTITIONED,
|
|
BAKE_MODE_APPROX_INTERP,
|
|
BAKE_MODE_APPROX_FLOODFILL,
|
|
BAKE_MODE_COUNT
|
|
};
|
|
|
|
static const int MIN_CELL_COUNT = 2;
|
|
static const int MAX_CELL_COUNT = 256;
|
|
|
|
static constexpr float MIN_MARGIN_RATIO = 0.f;
|
|
static constexpr float MAX_MARGIN_RATIO = 1.f;
|
|
|
|
static const int MIN_PARTITION_SUBDIV = 2;
|
|
static const int MAX_PARTITION_SUBDIV = 255;
|
|
|
|
// The data cannot be used until baked
|
|
bool is_baked() const;
|
|
bool is_baking() const;
|
|
|
|
int get_cell_count() const;
|
|
void set_cell_count(int cc);
|
|
|
|
float get_margin_ratio() const;
|
|
void set_margin_ratio(float mr);
|
|
|
|
BakeMode get_bake_mode() const;
|
|
void set_bake_mode(BakeMode mode);
|
|
|
|
int get_partition_subdiv() const;
|
|
void set_partition_subdiv(int subdiv);
|
|
|
|
void set_boundary_sign_fix_enabled(bool enable);
|
|
bool is_boundary_sign_fix_enabled() const;
|
|
|
|
void set_mesh(Ref<Mesh> mesh);
|
|
Ref<Mesh> get_mesh() const;
|
|
|
|
void bake();
|
|
|
|
// Bakes the SDF asynchronously using threads of the job system.
|
|
// TODO A reference to the SceneTree should not be necessary!
|
|
// It is currently needed to ensure `VoxelServerUpdater` gets created so it can tick the task system...
|
|
void bake_async(SceneTree *scene_tree);
|
|
|
|
Ref<gd::VoxelBuffer> get_voxel_buffer() const;
|
|
AABB get_aabb() const;
|
|
|
|
Array debug_check_sdf(Ref<Mesh> mesh);
|
|
|
|
private:
|
|
void _on_bake_async_completed(Ref<gd::VoxelBuffer> buffer, Vector3 min_pos, Vector3 max_pos);
|
|
|
|
Dictionary _b_get_data() const;
|
|
void _b_set_data(Dictionary d);
|
|
|
|
static void _bind_methods();
|
|
|
|
// Data
|
|
Ref<gd::VoxelBuffer> _voxel_buffer;
|
|
Vector3f _min_pos;
|
|
Vector3f _max_pos;
|
|
|
|
// States
|
|
bool _is_baking = false;
|
|
|
|
// Baking options
|
|
int _cell_count = 64;
|
|
float _margin_ratio = 0.25;
|
|
BakeMode _bake_mode = BAKE_MODE_ACCURATE_PARTITIONED;
|
|
uint8_t _partition_subdiv = 32;
|
|
bool _boundary_sign_fix = true;
|
|
// Note, the mesh is referenced here only for convenience. Setting it to null will not clear the SDF.
|
|
// An SDF should be usable without loading the original mesh onto the graphics card.
|
|
// The mesh is only used for baking.
|
|
Ref<Mesh> _mesh;
|
|
};
|
|
|
|
} // namespace zylann::voxel
|
|
|
|
VARIANT_ENUM_CAST(zylann::voxel::VoxelMeshSDF::BakeMode);
|
|
|
|
#endif // VOXEL_MESH_SDF_GD_H
|