179 lines
5.8 KiB
C++
179 lines
5.8 KiB
C++
#ifndef VOXEL_BUFFER_GD_H
|
|
#define VOXEL_BUFFER_GD_H
|
|
|
|
#include "voxel_buffer_internal.h"
|
|
#include <core/object/ref_counted.h>
|
|
#include <memory>
|
|
|
|
class Image;
|
|
|
|
namespace zylann::voxel {
|
|
|
|
class VoxelTool;
|
|
|
|
namespace gd {
|
|
|
|
// Scripts-facing wrapper around VoxelBufferInternal.
|
|
// It is separate because being a Godot object requires to carry more baggage, and because this data type can
|
|
// be instanced many times while being rarely accessed directly from scripts, it is a bit better to take this part out
|
|
class VoxelBuffer : public RefCounted {
|
|
GDCLASS(VoxelBuffer, RefCounted)
|
|
|
|
public:
|
|
enum ChannelId {
|
|
CHANNEL_TYPE = VoxelBufferInternal::CHANNEL_TYPE,
|
|
CHANNEL_SDF = VoxelBufferInternal::CHANNEL_SDF,
|
|
CHANNEL_COLOR = VoxelBufferInternal::CHANNEL_COLOR,
|
|
CHANNEL_INDICES = VoxelBufferInternal::CHANNEL_INDICES,
|
|
CHANNEL_WEIGHTS = VoxelBufferInternal::CHANNEL_WEIGHTS,
|
|
CHANNEL_DATA5 = VoxelBufferInternal::CHANNEL_DATA5,
|
|
CHANNEL_DATA6 = VoxelBufferInternal::CHANNEL_DATA6,
|
|
CHANNEL_DATA7 = VoxelBufferInternal::CHANNEL_DATA7,
|
|
MAX_CHANNELS = VoxelBufferInternal::MAX_CHANNELS,
|
|
};
|
|
|
|
// TODO use C++17 inline to initialize right here...
|
|
static const char *CHANNEL_ID_HINT_STRING;
|
|
|
|
enum Compression {
|
|
COMPRESSION_NONE = VoxelBufferInternal::COMPRESSION_NONE,
|
|
COMPRESSION_UNIFORM = VoxelBufferInternal::COMPRESSION_UNIFORM,
|
|
//COMPRESSION_RLE,
|
|
COMPRESSION_COUNT = VoxelBufferInternal::COMPRESSION_COUNT
|
|
};
|
|
|
|
enum Depth {
|
|
DEPTH_8_BIT = VoxelBufferInternal::DEPTH_8_BIT,
|
|
DEPTH_16_BIT = VoxelBufferInternal::DEPTH_16_BIT,
|
|
DEPTH_32_BIT = VoxelBufferInternal::DEPTH_32_BIT,
|
|
DEPTH_64_BIT = VoxelBufferInternal::DEPTH_64_BIT,
|
|
DEPTH_COUNT = VoxelBufferInternal::DEPTH_COUNT
|
|
};
|
|
|
|
// Limit was made explicit for serialization reasons, and also because there must be a reasonable one
|
|
static const uint32_t MAX_SIZE = 65535;
|
|
|
|
// Constructs a new buffer
|
|
VoxelBuffer();
|
|
// Reference an existing buffer
|
|
VoxelBuffer(std::shared_ptr<VoxelBufferInternal> &other);
|
|
|
|
~VoxelBuffer();
|
|
|
|
// Workaround because the constructor with arguments cannot always be used due to Godot limitations
|
|
static Ref<VoxelBuffer> create_shared(std::shared_ptr<VoxelBufferInternal> &other);
|
|
|
|
inline const VoxelBufferInternal &get_buffer() const {
|
|
#ifdef DEBUG_ENABLED
|
|
CRASH_COND(_buffer == nullptr);
|
|
#endif
|
|
return *_buffer;
|
|
}
|
|
|
|
inline VoxelBufferInternal &get_buffer() {
|
|
#ifdef DEBUG_ENABLED
|
|
CRASH_COND(_buffer == nullptr);
|
|
#endif
|
|
return *_buffer;
|
|
}
|
|
|
|
inline std::shared_ptr<VoxelBufferInternal> get_buffer_shared() {
|
|
#ifdef DEBUG_ENABLED
|
|
CRASH_COND(_buffer == nullptr);
|
|
#endif
|
|
return _buffer;
|
|
}
|
|
|
|
//inline std::shared_ptr<VoxelBufferInternal> get_buffer_shared() { return _buffer; }
|
|
|
|
Vector3i get_size() const {
|
|
return _buffer->get_size();
|
|
}
|
|
|
|
void create(int x, int y, int z) {
|
|
_buffer->create(x, y, z);
|
|
}
|
|
void clear();
|
|
|
|
uint64_t get_voxel(int x, int y, int z, unsigned int channel) const {
|
|
return _buffer->get_voxel(x, y, z, channel);
|
|
}
|
|
void set_voxel(uint64_t value, int x, int y, int z, unsigned int channel) {
|
|
_buffer->set_voxel(value, x, y, z, channel);
|
|
}
|
|
real_t get_voxel_f(int x, int y, int z, unsigned int channel_index) const;
|
|
void set_voxel_f(real_t value, int x, int y, int z, unsigned int channel_index);
|
|
|
|
void set_voxel_v(uint64_t value, Vector3i pos, unsigned int channel_index) {
|
|
_buffer->set_voxel(value, pos.x, pos.y, pos.z, channel_index);
|
|
}
|
|
|
|
void copy_channel_from(Ref<VoxelBuffer> other, unsigned int channel);
|
|
void copy_channel_from_area(
|
|
Ref<VoxelBuffer> other, Vector3i src_min, Vector3i src_max, Vector3i dst_min, unsigned int channel);
|
|
|
|
void fill(uint64_t defval, unsigned int channel_index = 0);
|
|
void fill_f(real_t value, unsigned int channel = 0);
|
|
void fill_area(uint64_t defval, Vector3i min, Vector3i max, unsigned int channel_index) {
|
|
_buffer->fill_area(defval, min, max, channel_index);
|
|
}
|
|
|
|
bool is_uniform(unsigned int channel_index) const;
|
|
|
|
void compress_uniform_channels();
|
|
Compression get_channel_compression(unsigned int channel_index) const;
|
|
|
|
void downscale_to(Ref<VoxelBuffer> dst, Vector3i src_min, Vector3i src_max, Vector3i dst_min) const;
|
|
|
|
Ref<VoxelBuffer> duplicate(bool include_metadata) const;
|
|
|
|
Ref<VoxelTool> get_voxel_tool();
|
|
|
|
void set_channel_depth(unsigned int channel_index, Depth new_depth);
|
|
Depth get_channel_depth(unsigned int channel_index) const;
|
|
|
|
// When using lower than 32-bit resolution for terrain signed distance fields,
|
|
// it should be scaled to better fit the range of represented values since the storage is normalized to -1..1.
|
|
// This returns that scale for a given depth configuration.
|
|
static float get_sdf_quantization_scale(Depth d);
|
|
|
|
// Metadata
|
|
|
|
Variant get_block_metadata() const;
|
|
void set_block_metadata(Variant meta);
|
|
|
|
Variant get_voxel_metadata(Vector3i pos) const;
|
|
void set_voxel_metadata(Vector3i pos, Variant meta);
|
|
|
|
void for_each_voxel_metadata(const Callable &callback) const;
|
|
void for_each_voxel_metadata_in_area(const Callable &callback, Vector3i min_pos, Vector3i max_pos);
|
|
void copy_voxel_metadata_in_area(
|
|
Ref<VoxelBuffer> src_buffer, Vector3i src_min_pos, Vector3i src_max_pos, Vector3i dst_pos);
|
|
|
|
void clear_voxel_metadata();
|
|
void clear_voxel_metadata_in_area(Vector3i min_pos, Vector3i max_pos);
|
|
|
|
// Debugging
|
|
|
|
Ref<Image> debug_print_sdf_to_image_top_down();
|
|
static Ref<Image> debug_print_sdf_to_image_top_down(const VoxelBufferInternal &vb);
|
|
Array debug_print_sdf_y_slices(float scale) const;
|
|
Ref<Image> debug_print_sdf_y_slice(float scale, int y) const;
|
|
|
|
private:
|
|
void _b_deprecated_optimize();
|
|
|
|
static void _bind_methods();
|
|
|
|
std::shared_ptr<VoxelBufferInternal> _buffer;
|
|
};
|
|
|
|
} // namespace gd
|
|
} // namespace zylann::voxel
|
|
|
|
VARIANT_ENUM_CAST(zylann::voxel::gd::VoxelBuffer::ChannelId)
|
|
VARIANT_ENUM_CAST(zylann::voxel::gd::VoxelBuffer::Depth)
|
|
VARIANT_ENUM_CAST(zylann::voxel::gd::VoxelBuffer::Compression)
|
|
|
|
#endif // VOXEL_BUFFER_GD_H
|