Moved all generators under their own base class and folder

master
Marc Gilleron 2020-01-26 22:34:26 +00:00
parent 87a9766442
commit 8879d9b2e7
26 changed files with 348 additions and 239 deletions

1
SCsub
View File

@ -11,6 +11,7 @@ files = [
"meshers/mc/*.cpp",
"meshers/*.cpp",
"streams/*.cpp",
"generators/*.cpp",
"util/*.cpp",
"terrain/*.cpp",
"math/*.cpp",

View File

@ -0,0 +1,55 @@
#include "voxel_generator.h"
#include "../voxel_string_names.h"
VoxelGenerator::VoxelGenerator() {
}
void VoxelGenerator::generate_block(VoxelBlockRequest &input) {
ERR_FAIL_COND(input.voxel_buffer.is_null());
ScriptInstance *script = get_script_instance();
if (script) {
// Call script to generate buffer
Variant arg1 = input.voxel_buffer;
Variant arg2 = input.origin_in_voxels.to_vec3();
Variant arg3 = input.lod;
const Variant *args[3] = { &arg1, &arg2, &arg3 };
Variant::CallError err;
script->call(VoxelStringNames::get_singleton()->generate_block, args, 3, err);
ERR_FAIL_COND_MSG(err.error != Variant::CallError::CALL_OK,
"voxel_generator.cpp:emerge_block gave an error: " + String::num(err.error) +
", Argument: " + String::num(err.argument) +
", Expected type: " + Variant::get_type_name(err.expected));
// This had to be explicitely logged due to the usual GD debugger not working with threads
}
}
//bool VoxelGenerator::is_thread_safe() const {
// return false;
//}
//bool VoxelGenerator::is_cloneable() const {
// return false;
//}
void VoxelGenerator::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
VoxelBlockRequest r = { out_buffer, Vector3i(origin_in_voxels), lod };
generate_block(r);
}
void VoxelGenerator::_b_generate_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels, int lod) {
ERR_FAIL_COND(lod < 0);
VoxelBlockRequest r = { out_buffer, Vector3i(origin_in_voxels), lod };
generate_block(r);
}
void VoxelGenerator::_bind_methods() {
// Note: C++ inheriting classes don't need to re-bind these, because they are bindings that call the actual virtual methods
ClassDB::bind_method(D_METHOD("generate_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelGenerator::_b_generate_block);
}

View File

@ -0,0 +1,31 @@
#ifndef VOXEL_GENERATOR_H
#define VOXEL_GENERATOR_H
#include "../streams/voxel_stream.h"
// TODO I would like VoxelGenerator to not inherit VoxelStream
// because it gets members that make no sense with generators
// Provides access to read-only generated voxels.
// Must be implemented in a multi-thread-safe way.
class VoxelGenerator : public VoxelStream {
GDCLASS(VoxelGenerator, VoxelStream)
public:
VoxelGenerator();
virtual void generate_block(VoxelBlockRequest &input);
// TODO Single sample
// virtual bool is_thread_safe() const;
// virtual bool is_cloneable() const;
private:
void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) override;
protected:
static void _bind_methods();
void _b_generate_block(Ref<VoxelBuffer> out_buffer, Vector3 origin_in_voxels, int lod);
};
#endif // VOXEL_GENERATOR_H

View File

@ -0,0 +1,59 @@
#include "voxel_stream_heightmap.h"
#include "../util/array_slice.h"
#include "../util/fixed_array.h"
VoxelGeneratorHeightmap::VoxelGeneratorHeightmap() {
}
void VoxelGeneratorHeightmap::set_channel(VoxelBuffer::ChannelId channel) {
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
_channel = channel;
}
VoxelBuffer::ChannelId VoxelGeneratorHeightmap::get_channel() const {
return _channel;
}
void VoxelGeneratorHeightmap::set_height_start(float start) {
_range.start = start;
}
float VoxelGeneratorHeightmap::get_height_start() const {
return _range.start;
}
void VoxelGeneratorHeightmap::set_height_range(float range) {
_range.height = range;
}
float VoxelGeneratorHeightmap::get_height_range() const {
return _range.height;
}
void VoxelGeneratorHeightmap::set_iso_scale(float iso_scale) {
_iso_scale = iso_scale;
}
float VoxelGeneratorHeightmap::get_iso_scale() const {
return _iso_scale;
}
void VoxelGeneratorHeightmap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelGeneratorHeightmap::set_channel);
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelGeneratorHeightmap::get_channel);
ClassDB::bind_method(D_METHOD("set_height_start", "start"), &VoxelGeneratorHeightmap::set_height_start);
ClassDB::bind_method(D_METHOD("get_height_start"), &VoxelGeneratorHeightmap::get_height_start);
ClassDB::bind_method(D_METHOD("set_height_range", "range"), &VoxelGeneratorHeightmap::set_height_range);
ClassDB::bind_method(D_METHOD("get_height_range"), &VoxelGeneratorHeightmap::get_height_range);
ClassDB::bind_method(D_METHOD("set_iso_scale", "scale"), &VoxelGeneratorHeightmap::set_iso_scale);
ClassDB::bind_method(D_METHOD("get_iso_scale"), &VoxelGeneratorHeightmap::get_iso_scale);
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_start"), "set_height_start", "get_height_start");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_range"), "set_height_range", "get_height_range");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "iso_scale"), "set_iso_scale", "get_iso_scale");
}

View File

@ -1,13 +1,14 @@
#ifndef VOXEL_STREAM_HEIGHTMAP_H
#define VOXEL_STREAM_HEIGHTMAP_H
#include "voxel_stream.h"
#include "../voxel_buffer.h"
#include "voxel_generator.h"
#include <core/image.h>
class VoxelStreamHeightmap : public VoxelStream {
GDCLASS(VoxelStreamHeightmap, VoxelStream)
class VoxelGeneratorHeightmap : public VoxelGenerator {
GDCLASS(VoxelGeneratorHeightmap, VoxelGenerator)
public:
VoxelStreamHeightmap();
VoxelGeneratorHeightmap();
void set_channel(VoxelBuffer::ChannelId channel);
VoxelBuffer::ChannelId get_channel() const;

View File

@ -19,42 +19,42 @@ inline float get_height_blurred(Image &im, int x, int y) {
} // namespace
VoxelStreamImage::VoxelStreamImage() {
VoxelGeneratorImage::VoxelGeneratorImage() {
}
void VoxelStreamImage::set_image(Ref<Image> im) {
void VoxelGeneratorImage::set_image(Ref<Image> im) {
_image = im;
}
Ref<Image> VoxelStreamImage::get_image() const {
Ref<Image> VoxelGeneratorImage::get_image() const {
return _image;
}
void VoxelStreamImage::set_blur_enabled(bool enable) {
void VoxelGeneratorImage::set_blur_enabled(bool enable) {
_blur_enabled = enable;
}
bool VoxelStreamImage::is_blur_enabled() const {
bool VoxelGeneratorImage::is_blur_enabled() const {
return _blur_enabled;
}
void VoxelStreamImage::emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels, int lod) {
void VoxelGeneratorImage::generate_block(VoxelBlockRequest &input) {
ERR_FAIL_COND(_image.is_null());
VoxelBuffer &out_buffer = **p_out_buffer;
VoxelBuffer &out_buffer = **input.voxel_buffer;
Image &image = **_image;
image.lock();
if (_blur_enabled) {
VoxelStreamHeightmap::generate(out_buffer,
VoxelGeneratorHeightmap::generate(out_buffer,
[&image](int x, int z) { return get_height_blurred(image, x, z); },
origin_in_voxels, lod);
input.origin_in_voxels, input.lod);
} else {
VoxelStreamHeightmap::generate(out_buffer,
VoxelGeneratorHeightmap::generate(out_buffer,
[&image](int x, int z) { return get_height_repeat(image, x, z); },
origin_in_voxels, lod);
input.origin_in_voxels, input.lod);
}
image.unlock();
@ -62,10 +62,12 @@ void VoxelStreamImage::emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i orig
out_buffer.compress_uniform_channels();
}
void VoxelStreamImage::_bind_methods() {
void VoxelGeneratorImage::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_image", "image"), &VoxelStreamImage::set_image);
ClassDB::bind_method(D_METHOD("get_image"), &VoxelStreamImage::get_image);
ClassDB::bind_method(D_METHOD("set_image", "image"), &VoxelGeneratorImage::set_image);
ClassDB::bind_method(D_METHOD("get_image"), &VoxelGeneratorImage::get_image);
// TODO Expose blur option!
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_image", "get_image");
}

View File

@ -5,10 +5,10 @@
#include <core/image.h>
// Provides infinite tiling heightmap based on an image
class VoxelStreamImage : public VoxelStreamHeightmap {
GDCLASS(VoxelStreamImage, VoxelStreamHeightmap)
class VoxelGeneratorImage : public VoxelGeneratorHeightmap {
GDCLASS(VoxelGeneratorImage, VoxelGeneratorHeightmap)
public:
VoxelStreamImage();
VoxelGeneratorImage();
void set_image(Ref<Image> im);
Ref<Image> get_image() const;
@ -16,7 +16,7 @@ public:
void set_blur_enabled(bool enable);
bool is_blur_enabled() const;
void emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels, int lod);
void generate_block(VoxelBlockRequest &input) override;
private:
static void _bind_methods();

View File

@ -1,38 +1,38 @@
#include "voxel_stream_noise.h"
void VoxelStreamNoise::set_channel(VoxelBuffer::ChannelId channel) {
void VoxelGeneratorNoise::set_channel(VoxelBuffer::ChannelId channel) {
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
_channel = channel;
}
VoxelBuffer::ChannelId VoxelStreamNoise::get_channel() const {
VoxelBuffer::ChannelId VoxelGeneratorNoise::get_channel() const {
return _channel;
}
void VoxelStreamNoise::set_noise(Ref<OpenSimplexNoise> noise) {
void VoxelGeneratorNoise::set_noise(Ref<OpenSimplexNoise> noise) {
_noise = noise;
}
Ref<OpenSimplexNoise> VoxelStreamNoise::get_noise() const {
Ref<OpenSimplexNoise> VoxelGeneratorNoise::get_noise() const {
return _noise;
}
void VoxelStreamNoise::set_height_start(real_t y) {
void VoxelGeneratorNoise::set_height_start(real_t y) {
_height_start = y;
}
real_t VoxelStreamNoise::get_height_start() const {
real_t VoxelGeneratorNoise::get_height_start() const {
return _height_start;
}
void VoxelStreamNoise::set_height_range(real_t hrange) {
void VoxelGeneratorNoise::set_height_range(real_t hrange) {
if (hrange < 0.1f) {
hrange = 0.1f;
}
_height_range = hrange;
}
real_t VoxelStreamNoise::get_height_range() const {
real_t VoxelGeneratorNoise::get_height_range() const {
return _height_range;
}
@ -70,13 +70,15 @@ static inline float get_shaped_noise(OpenSimplexNoise &noise, float x, float y,
return sum / max;
}
void VoxelStreamNoise::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
void VoxelGeneratorNoise::generate_block(VoxelBlockRequest &input) {
ERR_FAIL_COND(out_buffer.is_null());
ERR_FAIL_COND(input.voxel_buffer.is_null());
ERR_FAIL_COND(_noise.is_null());
OpenSimplexNoise &noise = **_noise;
VoxelBuffer &buffer = **out_buffer;
VoxelBuffer &buffer = **input.voxel_buffer;
Vector3i origin_in_voxels = input.origin_in_voxels;
int lod = input.lod;
int isosurface_lower_bound = static_cast<int>(Math::floor(_height_start));
int isosurface_upper_bound = static_cast<int>(Math::ceil(_height_start + _height_range));
@ -157,19 +159,19 @@ void VoxelStreamNoise::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin
}
}
void VoxelStreamNoise::_bind_methods() {
void VoxelGeneratorNoise::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &VoxelStreamNoise::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &VoxelStreamNoise::get_noise);
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &VoxelGeneratorNoise::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &VoxelGeneratorNoise::get_noise);
ClassDB::bind_method(D_METHOD("set_height_start", "hstart"), &VoxelStreamNoise::set_height_start);
ClassDB::bind_method(D_METHOD("get_height_start"), &VoxelStreamNoise::get_height_start);
ClassDB::bind_method(D_METHOD("set_height_start", "hstart"), &VoxelGeneratorNoise::set_height_start);
ClassDB::bind_method(D_METHOD("get_height_start"), &VoxelGeneratorNoise::get_height_start);
ClassDB::bind_method(D_METHOD("set_height_range", "hrange"), &VoxelStreamNoise::set_height_range);
ClassDB::bind_method(D_METHOD("get_height_range"), &VoxelStreamNoise::get_height_range);
ClassDB::bind_method(D_METHOD("set_height_range", "hrange"), &VoxelGeneratorNoise::set_height_range);
ClassDB::bind_method(D_METHOD("get_height_range"), &VoxelGeneratorNoise::get_height_range);
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelStreamNoise::set_channel);
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelStreamNoise::get_channel);
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelGeneratorNoise::set_channel);
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelGeneratorNoise::get_channel);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_start"), "set_height_start", "get_height_start");

View File

@ -2,11 +2,11 @@
#define VOXEL_STREAM_NOISE_H
#include "../util/float_buffer_3d.h"
#include "voxel_stream.h"
#include "voxel_generator.h"
#include <modules/opensimplex/open_simplex_noise.h>
class VoxelStreamNoise : public VoxelStream {
GDCLASS(VoxelStreamNoise, VoxelStream)
class VoxelGeneratorNoise : public VoxelGenerator {
GDCLASS(VoxelGeneratorNoise, VoxelGenerator)
public:
void set_channel(VoxelBuffer::ChannelId channel);
@ -21,7 +21,7 @@ public:
void set_height_range(real_t hrange);
real_t get_height_range() const;
void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod);
void generate_block(VoxelBlockRequest &input) override;
protected:
static void _bind_methods();

View File

@ -0,0 +1,53 @@
#include "voxel_stream_noise_2d.h"
VoxelGeneratorNoise2D::VoxelGeneratorNoise2D() {
}
void VoxelGeneratorNoise2D::set_noise(Ref<OpenSimplexNoise> noise) {
_noise = noise;
}
Ref<OpenSimplexNoise> VoxelGeneratorNoise2D::get_noise() const {
return _noise;
}
void VoxelGeneratorNoise2D::set_curve(Ref<Curve> curve) {
_curve = curve;
}
Ref<Curve> VoxelGeneratorNoise2D::get_curve() const {
return _curve;
}
void VoxelGeneratorNoise2D::generate_block(VoxelBlockRequest &input) {
ERR_FAIL_COND(_noise.is_null());
VoxelBuffer &out_buffer = **input.voxel_buffer;
OpenSimplexNoise &noise = **_noise;
if (_curve.is_null()) {
VoxelGeneratorHeightmap::generate(out_buffer,
[&noise](int x, int z) { return 0.5 + 0.5 * noise.get_noise_2d(x, z); },
input.origin_in_voxels, input.lod);
} else {
Curve &curve = **_curve;
VoxelGeneratorHeightmap::generate(out_buffer,
[&noise, &curve](int x, int z) { return curve.interpolate_baked(0.5 + 0.5 * noise.get_noise_2d(x, z)); },
input.origin_in_voxels, input.lod);
}
out_buffer.compress_uniform_channels();
}
void VoxelGeneratorNoise2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &VoxelGeneratorNoise2D::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &VoxelGeneratorNoise2D::get_noise);
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &VoxelGeneratorNoise2D::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &VoxelGeneratorNoise2D::get_curve);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
}

View File

@ -4,10 +4,10 @@
#include "voxel_stream_heightmap.h"
#include <modules/opensimplex/open_simplex_noise.h>
class VoxelStreamNoise2D : public VoxelStreamHeightmap {
GDCLASS(VoxelStreamNoise2D, VoxelStreamHeightmap)
class VoxelGeneratorNoise2D : public VoxelGeneratorHeightmap {
GDCLASS(VoxelGeneratorNoise2D, VoxelGeneratorHeightmap)
public:
VoxelStreamNoise2D();
VoxelGeneratorNoise2D();
void set_noise(Ref<OpenSimplexNoise> noise);
Ref<OpenSimplexNoise> get_noise() const;
@ -15,7 +15,7 @@ public:
void set_curve(Ref<Curve> curve);
Ref<Curve> get_curve() const;
void emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels, int lod);
void generate_block(VoxelBlockRequest &input) override;
private:
static void _bind_methods();

View File

@ -1,38 +1,39 @@
#include "voxel_stream_test.h"
VARIANT_ENUM_CAST(VoxelStreamTest::Mode)
VARIANT_ENUM_CAST(VoxelGeneratorTest::Mode)
VoxelStreamTest::VoxelStreamTest() {
VoxelGeneratorTest::VoxelGeneratorTest() {
_mode = MODE_WAVES;
_voxel_type = 1;
_pattern_size = Vector3i(10, 10, 10);
}
void VoxelStreamTest::set_mode(Mode mode) {
void VoxelGeneratorTest::set_mode(Mode mode) {
ERR_FAIL_INDEX(mode, MODE_COUNT)
_mode = mode;
}
void VoxelStreamTest::set_voxel_type(int t) {
void VoxelGeneratorTest::set_voxel_type(int t) {
_voxel_type = t;
}
int VoxelStreamTest::get_voxel_type() const {
int VoxelGeneratorTest::get_voxel_type() const {
return _voxel_type;
}
void VoxelStreamTest::set_pattern_size(Vector3i size) {
void VoxelGeneratorTest::set_pattern_size(Vector3i size) {
ERR_FAIL_COND(size.x < 1 || size.y < 1 || size.z < 1);
_pattern_size = size;
}
void VoxelStreamTest::set_pattern_offset(Vector3i offset) {
void VoxelGeneratorTest::set_pattern_offset(Vector3i offset) {
_pattern_offset = offset;
}
void VoxelStreamTest::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin, int lod) {
ERR_FAIL_COND(out_buffer.is_null());
void VoxelGeneratorTest::generate_block(VoxelBlockRequest &input) {
ERR_FAIL_COND(input.voxel_buffer.is_null());
if (lod != 0) {
if (input.lod != 0) {
// TODO Handle higher lods
return;
}
@ -40,16 +41,16 @@ void VoxelStreamTest::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin,
switch (_mode) {
case MODE_FLAT:
generate_block_flat(**out_buffer, origin, lod);
generate_block_flat(**input.voxel_buffer, input.origin_in_voxels, input.lod);
break;
case MODE_WAVES:
generate_block_waves(**out_buffer, origin, lod);
generate_block_waves(**input.voxel_buffer, input.origin_in_voxels, input.lod);
break;
}
}
void VoxelStreamTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
void VoxelGeneratorTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
// TODO Don't expect a block pos, but a voxel pos!
Vector3i size = out_buffer.get_size();
@ -67,7 +68,7 @@ void VoxelStreamTest::generate_block_flat(VoxelBuffer &out_buffer, Vector3i orig
}
}
void VoxelStreamTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
void VoxelGeneratorTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i origin, int lod) {
// TODO Don't expect a block pos, but a voxel pos!
Vector3i size = out_buffer.get_size();
@ -108,19 +109,19 @@ void VoxelStreamTest::generate_block_waves(VoxelBuffer &out_buffer, Vector3i ori
}
}
void VoxelStreamTest::_bind_methods() {
void VoxelGeneratorTest::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VoxelStreamTest::set_mode);
ClassDB::bind_method(D_METHOD("get_mode"), &VoxelStreamTest::get_mode);
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VoxelGeneratorTest::set_mode);
ClassDB::bind_method(D_METHOD("get_mode"), &VoxelGeneratorTest::get_mode);
ClassDB::bind_method(D_METHOD("set_voxel_type", "id"), &VoxelStreamTest::set_voxel_type);
ClassDB::bind_method(D_METHOD("get_voxel_type"), &VoxelStreamTest::get_voxel_type);
ClassDB::bind_method(D_METHOD("set_voxel_type", "id"), &VoxelGeneratorTest::set_voxel_type);
ClassDB::bind_method(D_METHOD("get_voxel_type"), &VoxelGeneratorTest::get_voxel_type);
ClassDB::bind_method(D_METHOD("set_pattern_size", "size"), &VoxelStreamTest::_set_pattern_size);
ClassDB::bind_method(D_METHOD("get_pattern_size"), &VoxelStreamTest::_get_pattern_size);
ClassDB::bind_method(D_METHOD("set_pattern_size", "size"), &VoxelGeneratorTest::_set_pattern_size);
ClassDB::bind_method(D_METHOD("get_pattern_size"), &VoxelGeneratorTest::_get_pattern_size);
ClassDB::bind_method(D_METHOD("set_pattern_offset", "offset"), &VoxelStreamTest::_set_pattern_offset);
ClassDB::bind_method(D_METHOD("get_pattern_offset"), &VoxelStreamTest::_get_pattern_offset);
ClassDB::bind_method(D_METHOD("set_pattern_offset", "offset"), &VoxelGeneratorTest::_set_pattern_offset);
ClassDB::bind_method(D_METHOD("get_pattern_offset"), &VoxelGeneratorTest::_get_pattern_offset);
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Flat,Waves"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "voxel_type", PROPERTY_HINT_RANGE, "0,255,1"), "set_voxel_type", "get_voxel_type");

View File

@ -1,20 +1,21 @@
#ifndef VOXEL_STREAM_TEST_H
#define VOXEL_STREAM_TEST_H
#include "voxel_stream.h"
#include "voxel_generator.h"
class VoxelStreamTest : public VoxelStream {
GDCLASS(VoxelStreamTest, VoxelStream)
class VoxelGeneratorTest : public VoxelGenerator {
GDCLASS(VoxelGeneratorTest, VoxelGenerator)
public:
enum Mode {
MODE_FLAT,
MODE_WAVES
MODE_WAVES,
MODE_COUNT
};
VoxelStreamTest();
VoxelGeneratorTest();
virtual void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin, int lod);
void generate_block(VoxelBlockRequest &input) override;
void set_mode(Mode mode);
Mode get_mode() const { return _mode; }

View File

@ -1,16 +1,16 @@
#include "register_types.h"
#include "edition/voxel_tool.h"
#include "generators/voxel_stream_heightmap.h"
#include "generators/voxel_stream_image.h"
#include "generators/voxel_stream_noise.h"
#include "generators/voxel_stream_noise_2d.h"
#include "generators/voxel_stream_test.h"
#include "meshers/blocky/voxel_mesher_blocky.h"
#include "meshers/dmc/voxel_mesher_dmc.h"
#include "meshers/transvoxel/voxel_mesher_transvoxel.h"
#include "streams/voxel_stream_block_files.h"
#include "streams/voxel_stream_file.h"
#include "streams/voxel_stream_heightmap.h"
#include "streams/voxel_stream_image.h"
#include "streams/voxel_stream_noise.h"
#include "streams/voxel_stream_noise_2d.h"
#include "streams/voxel_stream_region_files.h"
#include "streams/voxel_stream_test.h"
#include "terrain/voxel_box_mover.h"
#include "terrain/voxel_lod_terrain.h"
#include "terrain/voxel_map.h"
@ -36,15 +36,18 @@ void register_voxel_types() {
// Streams
ClassDB::register_class<VoxelStream>();
ClassDB::register_class<VoxelStreamTest>();
ClassDB::register_class<VoxelStreamHeightmap>();
ClassDB::register_class<VoxelStreamImage>();
ClassDB::register_class<VoxelStreamNoise>();
ClassDB::register_class<VoxelStreamNoise2D>();
ClassDB::register_class<VoxelStreamFile>();
ClassDB::register_class<VoxelStreamBlockFiles>();
ClassDB::register_class<VoxelStreamRegionFiles>();
// Generators
ClassDB::register_class<VoxelGenerator>();
ClassDB::register_class<VoxelGeneratorTest>();
ClassDB::register_class<VoxelGeneratorHeightmap>();
ClassDB::register_class<VoxelGeneratorImage>();
ClassDB::register_class<VoxelGeneratorNoise2D>();
ClassDB::register_class<VoxelGeneratorNoise>();
// Helpers
ClassDB::register_class<VoxelBoxMover>();
ClassDB::register_class<VoxelRaycastResult>();

View File

@ -0,0 +1,15 @@
#ifndef VOXEL_BLOCK_REQUEST_H
#define VOXEL_BLOCK_REQUEST_H
#include "../math/vector3i.h"
#include "../voxel_buffer.h"
class VoxelBuffer;
struct VoxelBlockRequest {
Ref<VoxelBuffer> voxel_buffer;
Vector3i origin_in_voxels;
int lod;
};
#endif // VOXEL_BLOCK_REQUEST_H

View File

@ -43,17 +43,17 @@ void VoxelStream::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxe
}
}
void VoxelStream::emerge_blocks(Vector<VoxelStream::BlockRequest> &p_blocks) {
void VoxelStream::emerge_blocks(Vector<VoxelBlockRequest> &p_blocks) {
// Default implementation. May matter for some stream types to optimize loading.
for (int i = 0; i < p_blocks.size(); ++i) {
BlockRequest &r = p_blocks.write[i];
VoxelBlockRequest &r = p_blocks.write[i];
emerge_block(r.voxel_buffer, r.origin_in_voxels, r.lod);
}
}
void VoxelStream::immerge_blocks(Vector<VoxelStream::BlockRequest> &p_blocks) {
void VoxelStream::immerge_blocks(Vector<VoxelBlockRequest> &p_blocks) {
for (int i = 0; i < p_blocks.size(); ++i) {
BlockRequest &r = p_blocks.write[i];
VoxelBlockRequest &r = p_blocks.write[i];
immerge_block(r.voxel_buffer, r.origin_in_voxels, r.lod);
}
}

View File

@ -2,20 +2,15 @@
#define VOXEL_STREAM_H
#include "../util/zprofiling.h"
#include "../voxel_buffer.h"
#include "voxel_block_request.h"
#include <core/resource.h>
// Provides access to a source of paged voxel data.
// Provides access to a source of paged voxel data, which may load and save.
// Must be implemented in a multi-thread-safe way.
// If you are looking for a more specialized API to generate voxels, use VoxelGenerator.
class VoxelStream : public Resource {
GDCLASS(VoxelStream, Resource)
public:
struct BlockRequest {
Ref<VoxelBuffer> voxel_buffer;
Vector3i origin_in_voxels;
int lod;
};
struct Stats {
int file_openings = 0;
int time_spent_opening_files = 0;
@ -31,12 +26,12 @@ public:
virtual void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod);
// Note: vector is passed by ref for performance. Don't reorder it.
virtual void emerge_blocks(Vector<BlockRequest> &p_blocks);
virtual void emerge_blocks(Vector<VoxelBlockRequest> &p_blocks);
// Returns multiple blocks of voxels to the stream.
// Generators usually don't implement it.
// This function is recommended if you save to files, because you can batch their access.
virtual void immerge_blocks(Vector<BlockRequest> &p_blocks);
virtual void immerge_blocks(Vector<VoxelBlockRequest> &p_blocks);
virtual bool is_thread_safe() const;
virtual bool is_cloneable() const;

View File

@ -23,18 +23,18 @@ void VoxelStreamFile::emerge_block_fallback(Ref<VoxelBuffer> out_buffer, Vector3
// This function is just a helper around the true thing, really. I might remove it in the future.
BlockRequest r;
VoxelBlockRequest r;
r.voxel_buffer = out_buffer;
r.origin_in_voxels = origin_in_voxels;
r.lod = lod;
Vector<BlockRequest> requests;
Vector<VoxelBlockRequest> requests;
requests.push_back(r);
emerge_blocks_fallback(requests);
}
void VoxelStreamFile::emerge_blocks_fallback(Vector<VoxelStreamFile::BlockRequest> &requests) {
void VoxelStreamFile::emerge_blocks_fallback(Vector<VoxelBlockRequest> &requests) {
VOXEL_PROFILE_SCOPE(profile_scope);
if (_fallback_stream.is_valid()) {

View File

@ -28,7 +28,7 @@ protected:
static void _bind_methods();
void emerge_block_fallback(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod);
void emerge_blocks_fallback(Vector<BlockRequest> &requests);
void emerge_blocks_fallback(Vector<VoxelBlockRequest> &requests);
FileAccess *open_file(const String &fpath, int mode_flags, Error *err);

View File

@ -1,59 +0,0 @@
#include "voxel_stream_heightmap.h"
#include "../util/array_slice.h"
#include "../util/fixed_array.h"
VoxelStreamHeightmap::VoxelStreamHeightmap() {
}
void VoxelStreamHeightmap::set_channel(VoxelBuffer::ChannelId channel) {
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
_channel = channel;
}
VoxelBuffer::ChannelId VoxelStreamHeightmap::get_channel() const {
return _channel;
}
void VoxelStreamHeightmap::set_height_start(float start) {
_range.start = start;
}
float VoxelStreamHeightmap::get_height_start() const {
return _range.start;
}
void VoxelStreamHeightmap::set_height_range(float range) {
_range.height = range;
}
float VoxelStreamHeightmap::get_height_range() const {
return _range.height;
}
void VoxelStreamHeightmap::set_iso_scale(float iso_scale) {
_iso_scale = iso_scale;
}
float VoxelStreamHeightmap::get_iso_scale() const {
return _iso_scale;
}
void VoxelStreamHeightmap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelStreamHeightmap::set_channel);
ClassDB::bind_method(D_METHOD("get_channel"), &VoxelStreamHeightmap::get_channel);
ClassDB::bind_method(D_METHOD("set_height_start", "start"), &VoxelStreamHeightmap::set_height_start);
ClassDB::bind_method(D_METHOD("get_height_start"), &VoxelStreamHeightmap::get_height_start);
ClassDB::bind_method(D_METHOD("set_height_range", "range"), &VoxelStreamHeightmap::set_height_range);
ClassDB::bind_method(D_METHOD("get_height_range"), &VoxelStreamHeightmap::get_height_range);
ClassDB::bind_method(D_METHOD("set_iso_scale", "scale"), &VoxelStreamHeightmap::set_iso_scale);
ClassDB::bind_method(D_METHOD("get_iso_scale"), &VoxelStreamHeightmap::get_iso_scale);
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_start"), "set_height_start", "get_height_start");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_range"), "set_height_range", "get_height_range");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "iso_scale"), "set_iso_scale", "get_iso_scale");
}

View File

@ -1,53 +0,0 @@
#include "voxel_stream_noise_2d.h"
VoxelStreamNoise2D::VoxelStreamNoise2D() {
}
void VoxelStreamNoise2D::set_noise(Ref<OpenSimplexNoise> noise) {
_noise = noise;
}
Ref<OpenSimplexNoise> VoxelStreamNoise2D::get_noise() const {
return _noise;
}
void VoxelStreamNoise2D::set_curve(Ref<Curve> curve) {
_curve = curve;
}
Ref<Curve> VoxelStreamNoise2D::get_curve() const {
return _curve;
}
void VoxelStreamNoise2D::emerge_block(Ref<VoxelBuffer> p_out_buffer, Vector3i origin_in_voxels, int lod) {
ERR_FAIL_COND(_noise.is_null());
VoxelBuffer &out_buffer = **p_out_buffer;
OpenSimplexNoise &noise = **_noise;
if (_curve.is_null()) {
VoxelStreamHeightmap::generate(out_buffer,
[&noise](int x, int z) { return 0.5 + 0.5 * noise.get_noise_2d(x, z); },
origin_in_voxels, lod);
} else {
Curve &curve = **_curve;
VoxelStreamHeightmap::generate(out_buffer,
[&noise, &curve](int x, int z) { return curve.interpolate_baked(0.5 + 0.5 * noise.get_noise_2d(x, z)); },
origin_in_voxels, lod);
}
out_buffer.compress_uniform_channels();
}
void VoxelStreamNoise2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &VoxelStreamNoise2D::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &VoxelStreamNoise2D::get_noise);
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &VoxelStreamNoise2D::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &VoxelStreamNoise2D::get_curve);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
}

View File

@ -27,42 +27,42 @@ VoxelStreamRegionFiles::~VoxelStreamRegionFiles() {
}
void VoxelStreamRegionFiles::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
BlockRequest r;
VoxelBlockRequest r;
r.voxel_buffer = out_buffer;
r.origin_in_voxels = origin_in_voxels;
r.lod = lod;
Vector<BlockRequest> requests;
Vector<VoxelBlockRequest> requests;
requests.push_back(r);
emerge_blocks(requests);
}
void VoxelStreamRegionFiles::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) {
BlockRequest r;
VoxelBlockRequest r;
r.voxel_buffer = buffer;
r.origin_in_voxels = origin_in_voxels;
r.lod = lod;
Vector<BlockRequest> requests;
Vector<VoxelBlockRequest> requests;
requests.push_back(r);
immerge_blocks(requests);
}
void VoxelStreamRegionFiles::emerge_blocks(Vector<BlockRequest> &p_blocks) {
void VoxelStreamRegionFiles::emerge_blocks(Vector<VoxelBlockRequest> &p_blocks) {
VOXEL_PROFILE_SCOPE(profile_scope);
// In order to minimize opening/closing files, requests are grouped according to their region.
// Had to copy input to sort it, as some areas in the module break if they get responses in different order
Vector<BlockRequest> sorted_blocks;
Vector<VoxelBlockRequest> sorted_blocks;
sorted_blocks.append_array(p_blocks);
SortArray<BlockRequest, BlockRequestComparator> sorter;
SortArray<VoxelBlockRequest, BlockRequestComparator> sorter;
sorter.compare.self = this;
sorter.sort(sorted_blocks.ptrw(), sorted_blocks.size());
Vector<BlockRequest> fallback_requests;
Vector<VoxelBlockRequest> fallback_requests;
for (int i = 0; i < sorted_blocks.size(); ++i) {
BlockRequest &r = sorted_blocks.write[i];
VoxelBlockRequest &r = sorted_blocks.write[i];
EmergeResult result = _emerge_block(r.voxel_buffer, r.origin_in_voxels, r.lod);
if (result == EMERGE_OK_FALLBACK) {
fallback_requests.push_back(r);
@ -72,19 +72,19 @@ void VoxelStreamRegionFiles::emerge_blocks(Vector<BlockRequest> &p_blocks) {
emerge_blocks_fallback(fallback_requests);
}
void VoxelStreamRegionFiles::immerge_blocks(Vector<BlockRequest> &p_blocks) {
void VoxelStreamRegionFiles::immerge_blocks(Vector<VoxelBlockRequest> &p_blocks) {
VOXEL_PROFILE_SCOPE(profile_scope);
// Had to copy input to sort it, as some areas in the module break if they get responses in different order
Vector<BlockRequest> sorted_blocks;
Vector<VoxelBlockRequest> sorted_blocks;
sorted_blocks.append_array(p_blocks);
SortArray<BlockRequest, BlockRequestComparator> sorter;
SortArray<VoxelBlockRequest, BlockRequestComparator> sorter;
sorter.compare.self = this;
sorter.sort(sorted_blocks.ptrw(), sorted_blocks.size());
for (int i = 0; i < sorted_blocks.size(); ++i) {
BlockRequest &r = sorted_blocks.write[i];
VoxelBlockRequest &r = sorted_blocks.write[i];
_immerge_block(r.voxel_buffer, r.origin_in_voxels, r.lod);
}
}

View File

@ -21,8 +21,8 @@ public:
void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) override;
void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) override;
void emerge_blocks(Vector<BlockRequest> &p_blocks) override;
void immerge_blocks(Vector<BlockRequest> &p_blocks) override;
void emerge_blocks(Vector<VoxelBlockRequest> &p_blocks) override;
void immerge_blocks(Vector<VoxelBlockRequest> &p_blocks) override;
String get_directory() const;
void set_directory(String dirpath);
@ -94,7 +94,7 @@ private:
VoxelStreamRegionFiles *self = nullptr;
// operator<
_FORCE_INLINE_ bool operator()(const VoxelStreamRegionFiles::BlockRequest &a, const VoxelStreamRegionFiles::BlockRequest &b) const {
_FORCE_INLINE_ bool operator()(const VoxelBlockRequest &a, const VoxelBlockRequest &b) const {
if (a.lod < b.lod) {
return true;
} else if (a.lod > b.lod) {

View File

@ -58,8 +58,8 @@ void VoxelDataLoader::process_blocks_thread_func(const ArraySlice<InputBlock> in
CRASH_COND(inputs.size() != outputs.size());
Vector<VoxelStream::BlockRequest> emerge_requests;
Vector<VoxelStream::BlockRequest> immerge_requests;
Vector<VoxelBlockRequest> emerge_requests;
Vector<VoxelBlockRequest> immerge_requests;
for (size_t i = 0; i < inputs.size(); ++i) {
@ -70,7 +70,7 @@ void VoxelDataLoader::process_blocks_thread_func(const ArraySlice<InputBlock> in
if (ib.data.voxels_to_save.is_null()) {
VoxelStream::BlockRequest r;
VoxelBlockRequest r;
r.voxel_buffer.instance();
r.voxel_buffer->create(bs, bs, bs);
r.origin_in_voxels = block_origin_in_voxels;
@ -79,7 +79,7 @@ void VoxelDataLoader::process_blocks_thread_func(const ArraySlice<InputBlock> in
} else {
VoxelStream::BlockRequest r;
VoxelBlockRequest r;
r.voxel_buffer = ib.data.voxels_to_save;
r.origin_in_voxels = block_origin_in_voxels;
r.lod = ib.lod;

View File

@ -17,6 +17,7 @@ VoxelStringNames::VoxelStringNames() {
emerge_block = StaticCString::create("emerge_block");
immerge_block = StaticCString::create("immerge_block");
generate_block = StaticCString::create("generate_block");
u_transition_mask = StaticCString::create("u_transition_mask");
}

View File

@ -19,6 +19,7 @@ public:
StringName emerge_block;
StringName immerge_block;
StringName generate_block;
StringName u_transition_mask;
};