godot_voxel/storage/voxel_buffer.h
Marc Gilleron a226111818 Run edits after preloads without a sync point on the main thread
- Still room for improvement, more parallelism is possible
- Started moving the data into its own structure
- Added locks to secure access to the data map (not truly used yet)
- Tasks with a tracker can schedule next ones when they complete
- Data loading responses also come with a callback, no buffer anymore
- Use new data grid to cache map access
2021-10-13 20:28:20 +01:00

154 lines
5.5 KiB
C++

#ifndef VOXEL_BUFFER_H
#define VOXEL_BUFFER_H
#include "voxel_buffer_internal.h"
class VoxelTool;
class Image;
class FuncRef;
// TODO I wish I could call the original class `VoxelBuffer` and expose this other one with that name.
// Godot doesn't seem to allow doing that. So the original class had to be named `VoxelBufferInternal`...
// 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 Reference {
GDCLASS(VoxelBuffer, Reference)
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();
inline const VoxelBufferInternal &get_buffer() const { return *_buffer; }
inline VoxelBufferInternal &get_buffer() { return *_buffer; }
//inline std::shared_ptr<VoxelBufferInternal> get_buffer_shared() { return _buffer; }
Vector3 get_size() const {
return _buffer->get_size().to_vec3();
}
int get_size_x() const { return _buffer->get_size().x; }
int get_size_y() const { return _buffer->get_size().x; }
int get_size_z() const { return _buffer->get_size().x; }
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, Vector3 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, Vector3 src_min, Vector3 src_max, Vector3 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, Vector3 min, Vector3 max, unsigned int channel_index) {
_buffer->fill_area(defval, Vector3i(min), Vector3i(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, Vector3 src_min, Vector3 src_max, Vector3 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 { return _buffer->get_block_metadata(); }
void set_block_metadata(Variant meta);
Variant get_voxel_metadata(Vector3 pos) const {
return _buffer->get_voxel_metadata(Vector3i(pos));
}
void set_voxel_metadata(Vector3 pos, Variant meta) {
_buffer->set_voxel_metadata(Vector3i(pos), meta);
}
void for_each_voxel_metadata(Ref<FuncRef> callback) const;
void for_each_voxel_metadata_in_area(Ref<FuncRef> callback, Vector3 min_pos, Vector3 max_pos);
void copy_voxel_metadata_in_area(
Ref<VoxelBuffer> src_buffer, Vector3 src_min_pos, Vector3 src_max_pos, Vector3 dst_pos);
void clear_voxel_metadata();
void clear_voxel_metadata_in_area(Vector3 min_pos, Vector3 max_pos);
// Debugging
Ref<Image> debug_print_sdf_to_image_top_down();
private:
static void _bind_methods();
// Not sure yet if we'll really need shared_ptr or just no pointer
std::shared_ptr<VoxelBufferInternal> _buffer;
};
VARIANT_ENUM_CAST(VoxelBuffer::ChannelId)
VARIANT_ENUM_CAST(VoxelBuffer::Depth)
VARIANT_ENUM_CAST(VoxelBuffer::Compression)
#endif // VOXEL_BUFFER_H