From 44bdc63c6f3ffe2c50f35a2b1be81364e2d07963 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Fri, 28 Sep 2018 01:11:28 +0100 Subject: [PATCH] Added an image-based terrain generator for testing (ported from the GDScript demo) --- register_types.cpp | 2 + voxel_provider.cpp | 5 ++- voxel_provider_image.cpp | 79 ++++++++++++++++++++++++++++++++++++++++ voxel_provider_image.h | 29 +++++++++++++++ 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 voxel_provider_image.cpp create mode 100644 voxel_provider_image.h diff --git a/register_types.cpp b/register_types.cpp index 0f7ccf3..95a68ad 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -5,6 +5,7 @@ #include "voxel_map.h" #include "voxel_terrain.h" #include "voxel_provider_test.h" +#include "voxel_provider_image.h" #include "voxel_mesher_smooth.h" void register_voxel_types() { @@ -17,6 +18,7 @@ void register_voxel_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); } diff --git a/voxel_provider.cpp b/voxel_provider.cpp index 5db8333..4f34b08 100644 --- a/voxel_provider.cpp +++ b/voxel_provider.cpp @@ -36,7 +36,8 @@ void VoxelProvider::_immerge_block(Ref buffer, Vector3 origin_in_vo } void VoxelProvider::_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("emerge_block", "out_buffer", "block_pos"), &VoxelProvider::_emerge_block); - ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "block_pos"), &VoxelProvider::_immerge_block); + ClassDB::bind_method(D_METHOD("emerge_block", "out_buffer", "origin_in_voxels"), &VoxelProvider::_emerge_block); + ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels"), &VoxelProvider::_immerge_block); } diff --git a/voxel_provider_image.cpp b/voxel_provider_image.cpp new file mode 100644 index 0000000..380c931 --- /dev/null +++ b/voxel_provider_image.cpp @@ -0,0 +1,79 @@ +#include "voxel_provider_image.h" + +VoxelProviderImage::VoxelProviderImage(): _channel(0) { +} + +void VoxelProviderImage::set_image(Ref im) { + _image = im; +} + +Ref VoxelProviderImage::get_image() const { + return _image; +} + +void VoxelProviderImage::set_channel(int channel) { + _channel = channel; +} + +int VoxelProviderImage::get_channel() const { + return _channel; +} + +void VoxelProviderImage::emerge_block(Ref p_out_buffer, Vector3i origin_in_voxels) { + + int ox = origin_in_voxels.x; + int oy = origin_in_voxels.y; + int oz = origin_in_voxels.z; + + Image &image = **_image; + VoxelBuffer &out_buffer = **p_out_buffer; + + image.lock(); + + int im_w = image.get_width(); + int im_h = image.get_height(); + int im_wm = im_w - 1; + int im_hm = im_h - 1; + + int x = 0; + int z = 0; + + int bs = out_buffer.get_size().x; + + int dirt = 1; + + while (z < bs) { + while (x < bs) { + + Color c = image.get_pixel((ox + x) & im_wm, (oz + z) & im_hm); + int h = int(c.r * 200.0) - 50; + h -= oy; + if (h > 0) { + if (h > bs) { + h = bs; + } + out_buffer.fill_area(dirt, Vector3(x, 0, z), Vector3(x + 1, h, z + 1), _channel); + } + + x += 1; + } + z += 1; + x = 0; + } + + image.unlock(); +} + +void VoxelProviderImage::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_image", "image"), &VoxelProviderImage::set_image); + ClassDB::bind_method(D_METHOD("get_image"), &VoxelProviderImage::get_image); + + ClassDB::bind_method(D_METHOD("set_channel", "channel"), &VoxelProviderImage::set_channel); + ClassDB::bind_method(D_METHOD("get_channel"), &VoxelProviderImage::get_channel); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_image", "get_image"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "channel"), "set_channel", "get_channel"); +} + + diff --git a/voxel_provider_image.h b/voxel_provider_image.h new file mode 100644 index 0000000..2393cb6 --- /dev/null +++ b/voxel_provider_image.h @@ -0,0 +1,29 @@ +#ifndef HEADER_VOXEL_PROVIDER_IMAGE +#define HEADER_VOXEL_PROVIDER_IMAGE + +#include "voxel_provider.h" +#include + +// Provides infinite tiling heightmap based on an image +class VoxelProviderImage : public VoxelProvider { + GDCLASS(VoxelProviderImage, VoxelProvider) +public: + VoxelProviderImage(); + + void set_image(Ref im); + Ref get_image() const; + + void set_channel(int channel); + int get_channel() const; + + void emerge_block(Ref p_out_buffer, Vector3i origin_in_voxels); + +private: + static void _bind_methods(); + +private: + Ref _image; + int _channel; +}; + +#endif // HEADER_VOXEL_PROVIDER_IMAGE