Added mapper
This commit is contained in:
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -2,3 +2,7 @@
|
|||||||
path = src/godot
|
path = src/godot
|
||||||
url = git@github.com:godotengine/godot
|
url = git@github.com:godotengine/godot
|
||||||
branch = 3.x
|
branch = 3.x
|
||||||
|
[submodule "src/modules/voxel"]
|
||||||
|
path = src/modules/voxel
|
||||||
|
url = git@github.com:Zylann/godot_voxel
|
||||||
|
branch = godot3.x
|
||||||
|
|||||||
14
src/modules/imgmapper/SCsub
Normal file
14
src/modules/imgmapper/SCsub
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
Import("env_modules")
|
||||||
|
|
||||||
|
env_imgmapper = env_modules.Clone()
|
||||||
|
|
||||||
|
# Godot source files
|
||||||
|
|
||||||
|
module_obj = []
|
||||||
|
|
||||||
|
env_imgmapper.add_source_files(module_obj, "*.cpp")
|
||||||
|
env.modules_sources += module_obj
|
||||||
|
|
||||||
14
src/modules/imgmapper/config.py
Normal file
14
src/modules/imgmapper/config.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
def can_build(env, platform):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def configure(env):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_doc_classes():
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def get_doc_path():
|
||||||
|
return "doc_classes"
|
||||||
11
src/modules/imgmapper/register_types.cpp
Normal file
11
src/modules/imgmapper/register_types.cpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include "register_types.h"
|
||||||
|
#include "voxel_generator_imgmapper.h"
|
||||||
|
|
||||||
|
void register_imgmapper_types()
|
||||||
|
{
|
||||||
|
ClassDB::register_class<VoxelGeneratorImgMapper>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void unregister_imgmapper_types()
|
||||||
|
{
|
||||||
|
}
|
||||||
7
src/modules/imgmapper/register_types.h
Normal file
7
src/modules/imgmapper/register_types.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef IMGMAPPER_REGISTER_TYPES_H
|
||||||
|
#define IMGMAPPER_REGISTER_TYPES_H
|
||||||
|
|
||||||
|
void register_imgmapper_types();
|
||||||
|
void unregister_imgmapper_types();
|
||||||
|
|
||||||
|
#endif // IMGMAPPER_REGISTER_TYPES_H
|
||||||
461
src/modules/imgmapper/voxel_generator_imgmapper.cpp
Normal file
461
src/modules/imgmapper/voxel_generator_imgmapper.cpp
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
#include "voxel_generator_imgmapper.h"
|
||||||
|
#include <modules/voxel/util/fixed_array.h>
|
||||||
|
#include "modules/voxel/util/span.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline float get_height_repeat(const Image &im, int x, int y) {
|
||||||
|
int xx = (float)x * 0.1f + im.get_width() / 2;
|
||||||
|
int yy = (float)y * 0.1f + im.get_height() / 2;
|
||||||
|
float r = im.get_pixel(wrap(xx, im.get_width()), wrap(yy, im.get_height())).r;
|
||||||
|
float px = (r - 0.5) * 2.0f;
|
||||||
|
float s = (px >= 0.0f) ? 1.0f : -1.0f;
|
||||||
|
float m = px * px * s * 0.5f;
|
||||||
|
return m + 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float get_height_blurred(const Image &im, int x, int y) {
|
||||||
|
int xx = x;
|
||||||
|
int yy = y;
|
||||||
|
float h = 0.0f;
|
||||||
|
int i, j, count = 0;
|
||||||
|
for (i = -24; i < 25; i += 2)
|
||||||
|
for (j = -24; j < 25; j += 2) {
|
||||||
|
h += get_height_repeat(im, xx + j, yy + i);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
return h / (float)count;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
VoxelGeneratorImgMapper::VoxelGeneratorImgMapper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelGeneratorImgMapper::~VoxelGeneratorImgMapper() {
|
||||||
|
if (_parameters.image.is_valid()) {
|
||||||
|
_parameters.image->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_image_bg(Ref<Image> im) {
|
||||||
|
if (im == _image_bg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!im.is_valid())
|
||||||
|
return;
|
||||||
|
_image_bg = im;
|
||||||
|
compose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Image> VoxelGeneratorImgMapper::get_image_bg() const {
|
||||||
|
return _image_bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_image_overlay(Ref<Image> im)
|
||||||
|
{
|
||||||
|
if (im == _image_overlay || !im.is_valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_image_overlay = im;
|
||||||
|
compose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Image> VoxelGeneratorImgMapper::get_image_overlay() const {
|
||||||
|
return _image_overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_image_buildings(Ref<Image> im)
|
||||||
|
{
|
||||||
|
if (im == _image_buildings || !im.is_valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_image_buildings = im;
|
||||||
|
compose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Image> VoxelGeneratorImgMapper::get_image_buildings() const {
|
||||||
|
return _image_buildings;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_image_draw(Ref<Image> im)
|
||||||
|
{
|
||||||
|
if (im == _image_draw || !im.is_valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_image_draw = im;
|
||||||
|
compose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Image> VoxelGeneratorImgMapper::get_image_draw() const {
|
||||||
|
return _image_draw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_blur_enabled(bool enable) {
|
||||||
|
RWLockWrite wlock(_parameters_lock);
|
||||||
|
_parameters.blur_enabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelGeneratorImgMapper::is_blur_enabled() const {
|
||||||
|
RWLockRead rlock(_parameters_lock);
|
||||||
|
return _parameters.blur_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelGenerator::Result VoxelGeneratorImgMapper::generate_block(VoxelBlockRequest &input) {
|
||||||
|
VoxelBufferInternal &out_buffer = input.voxel_buffer;
|
||||||
|
|
||||||
|
Parameters params;
|
||||||
|
{
|
||||||
|
RWLockRead rlock(_parameters_lock);
|
||||||
|
params = _parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(params.image.is_null(), result);
|
||||||
|
ERR_FAIL_COND_V(params.image->get_width() == 0, result);
|
||||||
|
ERR_FAIL_COND_V(params.image->get_height() == 0, result);
|
||||||
|
const Image &image = **params.image;
|
||||||
|
|
||||||
|
if (params.blur_enabled) {
|
||||||
|
result = VoxelGeneratorHeightmap::generate(
|
||||||
|
out_buffer,
|
||||||
|
[&image](int x, int z) { return get_height_blurred(image, x, z); },
|
||||||
|
input.origin_in_voxels, input.lod);
|
||||||
|
} else {
|
||||||
|
result = VoxelGeneratorHeightmap::generate(
|
||||||
|
out_buffer,
|
||||||
|
[&image](int x, int z) { return get_height_repeat(image, x, z); },
|
||||||
|
input.origin_in_voxels, input.lod);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_buffer.compress_uniform_channels();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_height(const Vector3 &v, float height)
|
||||||
|
{
|
||||||
|
ERR_FAIL_COND(!_image_overlay.is_valid());
|
||||||
|
float h = CLAMP(height, -100.0f, 100.0f);
|
||||||
|
float c = (h + 100.0f) / 200.0;
|
||||||
|
Vector2 pt = Vector2(v.x * 0.1f + _image_overlay->get_width() / 2,
|
||||||
|
v.z * 0.1f + _image_overlay->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_overlay->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_overlay->get_height() - 1);
|
||||||
|
_image_overlay->fill_rect(Rect2(pt - Vector2(3, 3), Vector2(6, 6)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
float VoxelGeneratorImgMapper::get_height(const Vector3 &v)
|
||||||
|
{
|
||||||
|
if (_parameters.blur_enabled)
|
||||||
|
return get_height_blurred(**_parameters.image, v.x, v.z);
|
||||||
|
else
|
||||||
|
return get_height_repeat(**_parameters.image, v.x, v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float VoxelGeneratorImgMapper::get_height_full(const Vector3 &v)
|
||||||
|
{
|
||||||
|
return get_height(v) * 200.0f - 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::draw_brush(const Vector3 &v, float r, float s, int id)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
if (r < 1.0f)
|
||||||
|
r = 1.0f;
|
||||||
|
ERR_FAIL_COND(!_image_draw.is_valid());
|
||||||
|
float c = 0.5f;
|
||||||
|
int xs = 3 * r;
|
||||||
|
float base_h = get_height_full(v);
|
||||||
|
float scale = s / 100.0f;
|
||||||
|
switch (id) {
|
||||||
|
case 0:
|
||||||
|
/* flat stuff */
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->fill_rect(Rect2(pt - Vector2(1, 1), Vector2(2, 2)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* erase stuff */
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->fill_rect(Rect2(pt - Vector2(1, 1), Vector2(2, 2)), Color(c, 0, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* abs draw curve */
|
||||||
|
ERR_FAIL_COND(!curve1.is_valid());
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
float h = curve1->interpolate_baked(xr / r) * scale;
|
||||||
|
h = CLAMP(h, -100.0, 100.0f);
|
||||||
|
c = (h + 100.0f) / 200.0;
|
||||||
|
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->fill_rect(Rect2(pt - Vector2(1, 1), Vector2(2, 2)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* rel draw curve1 */
|
||||||
|
ERR_FAIL_COND(!curve1.is_valid());
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
float h = curve1->interpolate_baked(xr / r) * scale;
|
||||||
|
if (h < -2.0f || h > 2.0f) {
|
||||||
|
h += get_height_full(v + Vector3(i, 0.0f, j));
|
||||||
|
h = CLAMP(h, -100.0, 100.0f);
|
||||||
|
c = (h + 100.0f) / 200.0;
|
||||||
|
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->fill_rect(Rect2(pt - Vector2(1, 1), Vector2(2, 2)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
/* rel draw curve2 */
|
||||||
|
ERR_FAIL_COND(!curve2.is_valid());
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
float h = curve2->interpolate_baked(xr / r) * scale;
|
||||||
|
if (h < -2.0f || h > 2.0f) {
|
||||||
|
h += get_height_full(v + Vector3(i, 0.0f, j));
|
||||||
|
h = CLAMP(h, -100.0, 100.0f);
|
||||||
|
c = (h + 100.0f) / 200.0;
|
||||||
|
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->fill_rect(Rect2(pt - Vector2(1, 1), Vector2(2, 2)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
Ref<Curve> curve;
|
||||||
|
if (id == 3)
|
||||||
|
curve = curve1;
|
||||||
|
else if (id == 4)
|
||||||
|
curve = curve2;
|
||||||
|
ERR_FAIL_COND(!curve.is_valid());
|
||||||
|
Ref<Image> img;
|
||||||
|
img.instance();
|
||||||
|
img->create(xs * 2, xs * 2, false, Image::FORMAT_RGBA8);
|
||||||
|
img->fill(Color(0, 0, 0, 0));
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
float h = curve->interpolate_baked(xr / r);
|
||||||
|
if (h < -2.0f || h > 2.0f) {
|
||||||
|
h += get_height_full(v + Vector3(i, 0.0f, j));
|
||||||
|
h = CLAMP(h, -100.0, 100.0f);
|
||||||
|
c = (h + 100.0f) / 200.0;
|
||||||
|
|
||||||
|
img->fill_rect(Rect2(Vector2(i + xs, j + xs), Vector2(1, 1)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vector3 pos(v.x, v.y, v.z);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->blend_rect(img,
|
||||||
|
Rect2(Vector2(), Vector2(img->get_width(), img->get_height())),
|
||||||
|
Vector2(pt.x - xs, pt.y - xs));
|
||||||
|
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
float h = get_height_full(v) + 2.0f;
|
||||||
|
h = CLAMP(h, -100.0, 100.0f);
|
||||||
|
for (i = -8 ; i < 8 + 1; i++)
|
||||||
|
for (j = -8 ; j < 8 + 1; j++) {
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
h = MAX(h, get_height_full(pos) + 2.0f);
|
||||||
|
}
|
||||||
|
c = (h + 100.0f) / 200.0;
|
||||||
|
for (i = -xs ; i < xs + 1; i++)
|
||||||
|
for (j = -xs ; j < xs + 1; j++) {
|
||||||
|
float xr = Vector2(i, j).length();
|
||||||
|
if (xr < r) {
|
||||||
|
Vector3 pos(v.x + i, v.y, v.z + j);
|
||||||
|
Vector2 pt = Vector2(pos.x * 0.1f + _image_draw->get_width() / 2,
|
||||||
|
pos.z * 0.1f + _image_draw->get_height() / 2);
|
||||||
|
pt.x = CLAMP(pt.x, 1, _image_draw->get_width() - 1);
|
||||||
|
pt.y = CLAMP(pt.y, 1, _image_draw->get_height() - 1);
|
||||||
|
_image_draw->fill_rect(Rect2(pt - Vector2(1, 1), Vector2(2, 2)), Color(c, 0, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::compose()
|
||||||
|
{
|
||||||
|
Ref<Image> copy;
|
||||||
|
ERR_FAIL_COND(!_image_bg.is_valid());
|
||||||
|
ERR_FAIL_COND(!_image_overlay.is_valid());
|
||||||
|
ERR_FAIL_COND(!_image_draw.is_valid());
|
||||||
|
copy = _image_bg->duplicate();
|
||||||
|
if (copy->get_width() == _image_draw->get_width() &&
|
||||||
|
copy->get_height() == _image_draw->get_height()) {
|
||||||
|
copy->blend_rect(_image_draw,
|
||||||
|
Rect2(0, 0, _image_draw->get_width(),
|
||||||
|
_image_draw->get_height()),
|
||||||
|
Vector2());
|
||||||
|
}
|
||||||
|
if (copy->get_width() == _image_overlay->get_width() &&
|
||||||
|
copy->get_height() == _image_overlay->get_height()) {
|
||||||
|
copy->blend_rect(_image_overlay,
|
||||||
|
Rect2(0, 0, _image_overlay->get_width(),
|
||||||
|
_image_overlay->get_height()),
|
||||||
|
Vector2());
|
||||||
|
}
|
||||||
|
RWLockWrite wlock(_parameters_lock);
|
||||||
|
// lock() prevents us from reading the same image from multiple threads, so we lock it up-front.
|
||||||
|
// This might no longer be needed in Godot 4.
|
||||||
|
if (_parameters.image.is_valid()) {
|
||||||
|
_parameters.image->unlock();
|
||||||
|
}
|
||||||
|
_parameters.image = copy;
|
||||||
|
if (_parameters.image.is_valid()) {
|
||||||
|
_parameters.image->lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::save_png()
|
||||||
|
{
|
||||||
|
if (_image_bg.is_valid())
|
||||||
|
_image_bg->save_png("res://textures/terrain.png");
|
||||||
|
if (_image_draw.is_valid())
|
||||||
|
_image_draw->save_png("res://textures/terrain_draw.png");
|
||||||
|
if (_image_overlay.is_valid())
|
||||||
|
_image_overlay->save_png("res://textures/terrain_edit.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_curve1(const Ref<Curve> &curve)
|
||||||
|
{
|
||||||
|
ERR_FAIL_COND(!curve.is_valid());
|
||||||
|
curve1 = curve;
|
||||||
|
curve1->bake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Curve> VoxelGeneratorImgMapper::get_curve1() const
|
||||||
|
{
|
||||||
|
return curve1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_curve2(const Ref<Curve> &curve)
|
||||||
|
{
|
||||||
|
ERR_FAIL_COND(!curve.is_valid());
|
||||||
|
curve2 = curve;
|
||||||
|
curve2->bake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Curve> VoxelGeneratorImgMapper::get_curve2() const
|
||||||
|
{
|
||||||
|
return curve2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_curve3(const Ref<Curve> &curve)
|
||||||
|
{
|
||||||
|
ERR_FAIL_COND(!curve.is_valid());
|
||||||
|
curve3 = curve;
|
||||||
|
curve3->bake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Curve> VoxelGeneratorImgMapper::get_curve3() const
|
||||||
|
{
|
||||||
|
return curve3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::set_curve4(const Ref<Curve> &curve)
|
||||||
|
{
|
||||||
|
ERR_FAIL_COND(!curve.is_valid());
|
||||||
|
curve4 = curve;
|
||||||
|
curve4->bake();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Curve> VoxelGeneratorImgMapper::get_curve4() const
|
||||||
|
{
|
||||||
|
return curve4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorImgMapper::_bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("set_image_bg", "image"), &VoxelGeneratorImgMapper::set_image_bg);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_image_bg"), &VoxelGeneratorImgMapper::get_image_bg);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_image_overlay", "image"), &VoxelGeneratorImgMapper::set_image_overlay);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_image_overlay"), &VoxelGeneratorImgMapper::get_image_overlay);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_image_draw", "image"), &VoxelGeneratorImgMapper::set_image_draw);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_image_draw"), &VoxelGeneratorImgMapper::get_image_draw);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_curve1", "curve"), &VoxelGeneratorImgMapper::set_curve1);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_curve1"), &VoxelGeneratorImgMapper::get_curve1);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_curve2", "curve"), &VoxelGeneratorImgMapper::set_curve2);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_curve2"), &VoxelGeneratorImgMapper::get_curve2);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_curve3", "curve"), &VoxelGeneratorImgMapper::set_curve3);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_curve3"), &VoxelGeneratorImgMapper::get_curve3);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_curve4", "curve"), &VoxelGeneratorImgMapper::set_curve4);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_curve4"), &VoxelGeneratorImgMapper::get_curve4);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_height", "v", "height"), &VoxelGeneratorImgMapper::set_height);
|
||||||
|
ClassDB::bind_method(D_METHOD("draw_brush", "v", "r", "s", "id"), &VoxelGeneratorImgMapper::draw_brush);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_height", "v"), &VoxelGeneratorImgMapper::get_height);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_height_full", "v"), &VoxelGeneratorImgMapper::get_height_full);
|
||||||
|
ClassDB::bind_method(D_METHOD("compose"), &VoxelGeneratorImgMapper::compose);
|
||||||
|
ClassDB::bind_method(D_METHOD("save_png"), &VoxelGeneratorImgMapper::save_png);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_blur_enabled", "enable"), &VoxelGeneratorImgMapper::set_blur_enabled);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_blur_enabled"), &VoxelGeneratorImgMapper::is_blur_enabled);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image_bg", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_image_bg", "get_image_bg");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image_overlay", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_image_overlay", "get_image_overlay");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image_draw", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_image_draw", "get_image_draw");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve1", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve1", "get_curve1");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve2", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve2", "get_curve2");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve3", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve3", "get_curve3");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve4", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve4", "get_curve4");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blur_enabled"), "set_blur_enabled", "is_blur_enabled");
|
||||||
|
}
|
||||||
78
src/modules/imgmapper/voxel_generator_imgmapper.h
Normal file
78
src/modules/imgmapper/voxel_generator_imgmapper.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#ifndef HEADER_VOXEL_GENERATOR_IMGMAPPER
|
||||||
|
#define HEADER_VOXEL_GENERATOR_IMGMAPPER
|
||||||
|
|
||||||
|
#include <modules/voxel/generators/simple/voxel_generator_heightmap.h>
|
||||||
|
#include <core/image.h>
|
||||||
|
#include <scene/resources/curve.h>
|
||||||
|
|
||||||
|
// Provides infinite tiling heightmap based on an image
|
||||||
|
class VoxelGeneratorImgMapper : public VoxelGeneratorHeightmap {
|
||||||
|
GDCLASS(VoxelGeneratorImgMapper, VoxelGeneratorHeightmap)
|
||||||
|
|
||||||
|
public:
|
||||||
|
VoxelGeneratorImgMapper();
|
||||||
|
~VoxelGeneratorImgMapper();
|
||||||
|
|
||||||
|
void set_image_bg(Ref<Image> im);
|
||||||
|
Ref<Image> get_image_bg() const;
|
||||||
|
|
||||||
|
void set_image_draw(Ref<Image> im);
|
||||||
|
Ref<Image> get_image_draw() const;
|
||||||
|
|
||||||
|
void set_image_overlay(Ref<Image> im);
|
||||||
|
Ref<Image> get_image_overlay() const;
|
||||||
|
|
||||||
|
void set_image_buildings(Ref<Image> im);
|
||||||
|
Ref<Image> get_image_buildings() const;
|
||||||
|
|
||||||
|
void set_blur_enabled(bool enable);
|
||||||
|
bool is_blur_enabled() const;
|
||||||
|
|
||||||
|
Result generate_block(VoxelBlockRequest &input) override;
|
||||||
|
|
||||||
|
void set_height(const Vector3 &v, float height);
|
||||||
|
void draw_brush(const Vector3 &v, float r, float s, int id);
|
||||||
|
float get_height(const Vector3 &v);
|
||||||
|
float get_height_full(const Vector3 &v);
|
||||||
|
void compose();
|
||||||
|
void save_png();
|
||||||
|
|
||||||
|
void set_curve1(const Ref<Curve> &curve);
|
||||||
|
Ref<Curve> get_curve1() const;
|
||||||
|
|
||||||
|
void set_curve2(const Ref<Curve> &curve);
|
||||||
|
Ref<Curve> get_curve2() const;
|
||||||
|
|
||||||
|
void set_curve3(const Ref<Curve> &curve);
|
||||||
|
Ref<Curve> get_curve3() const;
|
||||||
|
|
||||||
|
void set_curve4(const Ref<Curve> &curve);
|
||||||
|
Ref<Curve> get_curve4() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Proper reference used for external access.
|
||||||
|
Vector<float> height_data;
|
||||||
|
Ref<Image> _image_bg;
|
||||||
|
Ref<Image> _image_overlay, _image_buildings;
|
||||||
|
Ref<Image> _image_draw;
|
||||||
|
|
||||||
|
Ref<Curve> curve1, curve2, curve3, curve4;
|
||||||
|
|
||||||
|
struct Parameters {
|
||||||
|
int width, height;
|
||||||
|
// This is a read-only copy of the image.
|
||||||
|
// It wastes memory for sure, but Godot does not offer any way to secure this better.
|
||||||
|
// If this is a problem one day, we could add an option to dereference the external image in game.
|
||||||
|
Ref<Image> image;
|
||||||
|
// Mostly here as demo/tweak. It's better recommended to use an EXR/float image.
|
||||||
|
bool blur_enabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Parameters _parameters;
|
||||||
|
RWLock _parameters_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HEADER_VOXEL_GENERATOR_IMGMAPPER
|
||||||
1
src/modules/voxel
Submodule
1
src/modules/voxel
Submodule
Submodule src/modules/voxel added at dbca142dff
Reference in New Issue
Block a user