From 47525f401b450a0ad46f2b94ad078e29cccc3520 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 25 Feb 2023 12:08:49 +0100 Subject: [PATCH] Added noise offset support to TiledWalls. --- modules/props/prop_mesher.cpp | 131 ++++++++++++++++--- modules/props/tiled_wall/tiled_wall_data.cpp | 65 +++++++++ modules/props/tiled_wall/tiled_wall_data.h | 24 ++++ 3 files changed, 200 insertions(+), 20 deletions(-) diff --git a/modules/props/prop_mesher.cpp b/modules/props/prop_mesher.cpp index 66b6fdc91..f8755bfb5 100644 --- a/modules/props/prop_mesher.cpp +++ b/modules/props/prop_mesher.cpp @@ -30,6 +30,11 @@ SOFTWARE. #include "modules/modules_enabled.gen.h" +#ifdef MODULE_FASTNOISE_ENABLED +#include "../fastnoise/fastnoise_noise_params.h" +#include "../fastnoise/noise.h" +#endif + const String PropMesher::BINDING_STRING_BUILD_FLAGS = "Use Lighting,Use AO,Use RAO,Bake Lights"; bool PropMesher::Vertex::operator==(const Vertex &p_vertex) const { @@ -451,6 +456,10 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const return; } +#ifdef MODULE_FASTNOISE_ENABLED + int tiled_wall_vertex_start_index = _vertices.size(); +#endif + float flavour_chance = tiled_wall_data->get_flavour_tile_chance(); //collect rects @@ -483,6 +492,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const } TiledWallData::TiledWallTilingType tiling_type = tiled_wall_data->get_tiling_type(); + float cys = 0; if (tiling_type == TiledWallData::TILED_WALL_TILING_TYPE_NONE) { Rect2 r = normal_rects[0]; @@ -492,31 +502,31 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const if (flavour_rects.size() == 0) { //no flavours for (int x = 0; x < width; ++x) { - float ych = 0; + cys = 0; for (int y = 0; y < height; ++y) { - add_tiled_wall_mesh_rect_simple(x, ych, yh, 0, 0, transform, r, texture_scale); + add_tiled_wall_mesh_rect_simple(x, cys, yh, 0, 0, transform, r, texture_scale); - ych += yh; + cys += yh; } } } else { //has flavours for (int x = 0; x < width; ++x) { - float ych = 0; + cys = 0; for (int y = 0; y < height; ++y) { if (Math::randf() > flavour_chance) { - add_tiled_wall_mesh_rect_simple(x, ych, yh, 0, 0, transform, r, texture_scale); + add_tiled_wall_mesh_rect_simple(x, cys, yh, 0, 0, transform, r, texture_scale); - ych += yh; + cys += yh; } else { int indx = Math::rand() % flavour_rects.size(); float fyh = flavour_data[indx].y_size; - add_tiled_wall_mesh_rect_simple(x, ych, fyh, 0, 0, transform, flavour_rects[indx], flavour_data[indx].texture_scale); + add_tiled_wall_mesh_rect_simple(x, cys, fyh, 0, 0, transform, flavour_rects[indx], flavour_data[indx].texture_scale); - ych += fyh; + cys += fyh; } } } @@ -534,7 +544,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const float z_offset = normal_data[indx].z_offset; int texture_scale = normal_data[indx].texture_scale; - float cys = 0; + cys = 0; for (int y = 0; y < height; ++y) { add_tiled_wall_mesh_rect_simple(x, cys, ysize, z_offset, z_offset, transform, r, texture_scale); @@ -551,7 +561,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const float ysize = normal_data[indx].y_size; int texture_scale = normal_data[indx].texture_scale; - float cys = 0; + cys = 0; for (int y = 0; y < height; ++y) { if (Math::randf() > flavour_chance) { @@ -576,7 +586,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const //no flavours for (int x = 0; x < width; ++x) { - float cys = 0; + cys = 0; float prev_z_offset = 0; @@ -601,7 +611,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const } else { //has flavours for (int x = 0; x < width; ++x) { - float cys = 0; + cys = 0; float prev_z_offset = 0; @@ -639,7 +649,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const if (flavour_rects.size() == 0) { //no flavours for (int x = 0; x < width; ++x) { - float cys = 0; + cys = 0; for (int y = 0; y < height; ++y) { int indx = (x + y) % normal_rects.size(); @@ -655,7 +665,7 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const } else { //has flavours for (int x = 0; x < width; ++x) { - float cys = 0; + cys = 0; for (int y = 0; y < height; ++y) { int indx = (x + y) % normal_rects.size(); @@ -678,12 +688,94 @@ void PropMesher::add_tiled_wall_simple(const int width, const int height, const } } } + +#ifdef MODULE_FASTNOISE_ENABLED + Ref twd = tiled_wall_data; + Ref offset_noise = twd->get_offset_noise(); + + if (offset_noise.is_null()) { + return; + } + + float offset_noise_strength = tiled_wall_data->get_offset_noise_strength(); + Ref noise; + noise.instance(); + offset_noise->setup_noise(noise); + + if (twd->get_offset_noise_randomize_seed()) { + noise->set_seed(Math::rand()); + } + + if (twd->get_offset_noise_skip_edges()) { + //Vector3 vert_min = Vector3(Math_INF, Math_INF, Math_INF); + //Vector3 vert_max = Vector3(-Math_INF, -Math_INF, -Math_INF); + + Vector3 vert_min = transform.xform(Vector3(0, 0, 0)); + Vector3 vert_max = transform.xform(Vector3(width, cys, 0)); + + int vs = _vertices.size(); + PoolVector::Write w = _vertices.write(); + Vertex *wptr = w.ptr(); +/* + for (int i = tiled_wall_vertex_start_index; i < vs; ++i) { + Vertex v = wptr[i]; + + if (v.vertex < vert_min) { + vert_min = v.vertex; + } + + if (v.vertex > vert_max) { + vert_max = v.vertex; + } + } +*/ + for (int i = tiled_wall_vertex_start_index; i < vs; ++i) { + Vertex v = wptr[i]; + + int sim_count = 0; + + if (Math::is_equal_approx(v.vertex.x, vert_min.x) || Math::is_equal_approx(v.vertex.x, vert_max.x)) { + ++sim_count; + } + + if (Math::is_equal_approx(v.vertex.y, vert_min.y) || Math::is_equal_approx(v.vertex.y, vert_max.y)) { + ++sim_count; + } + + if (sim_count == 1 && (Math::is_equal_approx(v.vertex.z, vert_min.z) || Math::is_equal_approx(v.vertex.z, vert_max.z))) { + ++sim_count; + } + + if (sim_count > 1) { + continue; + } + + float n = noise->get_noise_2d(v.vertex.x, v.vertex.z) * offset_noise_strength; + v.vertex += transform.basis.xform(Vector3(0, 0, n)); + + wptr[i] = v; + } + } else { + int vs = _vertices.size(); + PoolVector::Write w = _vertices.write(); + Vertex *wptr = w.ptr(); + for (int i = tiled_wall_vertex_start_index; i < vs; ++i) { + Vertex v = wptr[i]; + + float n = noise->get_noise_2d(v.vertex.x, v.vertex.z) * offset_noise_strength; + v.vertex += transform.basis.xform(Vector3(0, 0, n)); + + wptr[i] = v; + } + } + +#endif } void PropMesher::add_tiled_wall_mesh_rect_simple(const float x, const float y, const float y_size, const float prev_z_offset, const float current_z_offset, const Transform &transform, const Rect2 &texture_rect, const int texture_scale) { int vc = get_vertex_count(); - - float cy = CLAMP(0.0, 1.0, y_size); + + float cy = CLAMP(0.0, 1.0, y_size); //x + 1, y add_normal(transform.basis.xform(Vector3(0, 0, -1))); @@ -727,8 +819,8 @@ _FORCE_INLINE_ Vector2 PropMesher::transform_uv(const Vector2 &uv, const Rect2 & Vector2 PropMesher::transform_uv_scaled(const Vector2 &uv, const Rect2 &rect, const int x, const int y, const int texture_scale) const { Vector2 ruv = uv; - int lx = x % texture_scale; - int ly = y % texture_scale; + int lx = x % texture_scale; + int ly = y % texture_scale; float sizex = rect.size.x / static_cast(texture_scale); float sizey = rect.size.y / static_cast(texture_scale); @@ -742,7 +834,6 @@ Vector2 PropMesher::transform_uv_scaled(const Vector2 &uv, const Rect2 &rect, co return ruv; } - #ifdef MODULE_MESH_DATA_RESOURCE_ENABLED void PropMesher::add_mesh_data_resource(Ref mesh, const Vector3 position, const Vector3 rotation, const Vector3 scale, const Rect2 uv_rect) { Transform transform = Transform(Basis(rotation).scaled(scale), position); @@ -1487,7 +1578,7 @@ void PropMesher::_bind_methods() { //ClassDB::bind_method(D_METHOD("add_tiled_wall_mesh_rect_simple", "x", "y", "y_size", "transform", "texture_rect", "texture_scale"), &PropMesher::add_tiled_wall_mesh_rect_simple); ClassDB::bind_method(D_METHOD("transform_uv", "uv", "rect"), &PropMesher::transform_uv); ClassDB::bind_method(D_METHOD("transform_uv_scaled", "uv", "rect", "x", "y", "texture_scale"), &PropMesher::transform_uv_scaled); - + #ifdef MODULE_MESH_DATA_RESOURCE_ENABLED ClassDB::bind_method(D_METHOD("add_mesh_data_resource", "mesh", "position", "rotation", "scale", "uv_rect"), &PropMesher::add_mesh_data_resource, DEFVAL(Rect2(0, 0, 1, 1)), DEFVAL(Vector3(1.0, 1.0, 1.0)), DEFVAL(Vector3()), DEFVAL(Vector3())); ClassDB::bind_method(D_METHOD("add_mesh_data_resource_transform", "mesh", "transform", "uv_rect"), &PropMesher::add_mesh_data_resource_transform, DEFVAL(Rect2(0, 0, 1, 1))); diff --git a/modules/props/tiled_wall/tiled_wall_data.cpp b/modules/props/tiled_wall/tiled_wall_data.cpp index 44c13c50e..f22d54865 100644 --- a/modules/props/tiled_wall/tiled_wall_data.cpp +++ b/modules/props/tiled_wall/tiled_wall_data.cpp @@ -42,6 +42,10 @@ SOFTWARE. #include "modules/modules_enabled.gen.h" +#ifdef MODULE_FASTNOISE_ENABLED +#include "../../fastnoise/fastnoise_noise_params.h" +#endif + #ifdef MODULE_ENTITY_SPELL_SYSTEM_ENABLED #include "modules/entity_spell_system/material_cache/ess_material_cache.h" #endif @@ -235,6 +239,44 @@ void TiledWallData::set_flavour_tile_chance(const float value) { _flavour_chance = value; } +#ifdef MODULE_FASTNOISE_ENABLED +Ref TiledWallData::get_offset_noise() { + return _offset_noise; +} +void TiledWallData::set_offset_noise(const Ref &val) { + _offset_noise = val; + + emit_changed(); +} + +float TiledWallData::get_offset_noise_strength() const { + return _offset_noise_strength; +} +void TiledWallData::set_offset_noise_strength(const float val) { + _offset_noise_strength = val; + + emit_changed(); +} + +bool TiledWallData::get_offset_noise_randomize_seed() const { + return _offset_noise_randomize_seed; +} +void TiledWallData::set_offset_noise_randomize_seed(const bool val) { + _offset_noise_randomize_seed = val; + + emit_changed(); +} + +bool TiledWallData::get_offset_noise_skip_edges() const { + return _offset_noise_skip_edges; +} +void TiledWallData::set_offset_noise_skip_edges(const bool val) { + _offset_noise_skip_edges = val; + + emit_changed(); +} +#endif + //materials void TiledWallData::material_add(const Ref &value) { ERR_FAIL_COND(!value.is_valid()); @@ -399,6 +441,11 @@ TiledWallData::TiledWallData() { _collider_type = TILED_WALL_COLLIDER_TYPE_PLANE; _flavour_chance = 0.15; _collider_z_offset = 0; +#ifdef MODULE_FASTNOISE_ENABLED + _offset_noise_strength = 0; + _offset_noise_randomize_seed = true; + _offset_noise_skip_edges = true; +#endif } TiledWallData::~TiledWallData() { _tiles.clear(); @@ -599,6 +646,24 @@ void TiledWallData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flavour_tile_chance", "texture"), &TiledWallData::set_flavour_tile_chance); ADD_PROPERTY(PropertyInfo(Variant::REAL, "flavour_tile_chance"), "set_flavour_tile_chance", "get_flavour_tile_chance"); +#ifdef MODULE_FASTNOISE_ENABLED + ClassDB::bind_method(D_METHOD("get_offset_noise"), &TiledWallData::get_offset_noise); + ClassDB::bind_method(D_METHOD("set_offset_noise", "texture"), &TiledWallData::set_offset_noise); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "offset_noise", PROPERTY_HINT_RESOURCE_TYPE, "FastnoiseNoiseParams"), "set_offset_noise", "get_offset_noise"); + + ClassDB::bind_method(D_METHOD("get_offset_noise_strength"), &TiledWallData::get_offset_noise_strength); + ClassDB::bind_method(D_METHOD("set_offset_noise_strength", "texture"), &TiledWallData::set_offset_noise_strength); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset_noise_strength"), "set_offset_noise_strength", "get_offset_noise_strength"); + + ClassDB::bind_method(D_METHOD("get_offset_noise_randomize_seed"), &TiledWallData::get_offset_noise_randomize_seed); + ClassDB::bind_method(D_METHOD("set_offset_noise_randomize_seed", "texture"), &TiledWallData::set_offset_noise_randomize_seed); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "offset_noise_randomize_seed"), "set_offset_noise_randomize_seed", "get_offset_noise_randomize_seed"); + + ClassDB::bind_method(D_METHOD("get_offset_noise_skip_edges"), &TiledWallData::get_offset_noise_skip_edges); + ClassDB::bind_method(D_METHOD("set_offset_noise_skip_edges", "texture"), &TiledWallData::set_offset_noise_skip_edges); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "offset_noise_skip_edges"), "set_offset_noise_skip_edges", "get_offset_noise_skip_edges"); +#endif + //materials ClassDB::bind_method(D_METHOD("material_add", "value"), &TiledWallData::material_add); ClassDB::bind_method(D_METHOD("material_set", "index", "value"), &TiledWallData::material_set); diff --git a/modules/props/tiled_wall/tiled_wall_data.h b/modules/props/tiled_wall/tiled_wall_data.h index a10c44942..1c01895ee 100644 --- a/modules/props/tiled_wall/tiled_wall_data.h +++ b/modules/props/tiled_wall/tiled_wall_data.h @@ -44,6 +44,9 @@ class PropMesher; #ifdef MODULE_ENTITY_SPELL_SYSTEM_ENABLED class ESSMaterialCache; #endif +#ifdef MODULE_FASTNOISE_ENABLED +class FastnoiseNoiseParams; +#endif class TiledWallData : public Resource { GDCLASS(TiledWallData, Resource); @@ -140,6 +143,20 @@ public: float get_flavour_tile_chance() const; void set_flavour_tile_chance(const float value); +#ifdef MODULE_FASTNOISE_ENABLED + Ref get_offset_noise(); + void set_offset_noise(const Ref &val); + + float get_offset_noise_strength() const; + void set_offset_noise_strength(const float val); + + bool get_offset_noise_randomize_seed() const; + void set_offset_noise_randomize_seed(const bool val); + + bool get_offset_noise_skip_edges() const; + void set_offset_noise_skip_edges(const bool val); +#endif + //materials void material_add(const Ref &value); void material_set(const int index, const Ref &value); @@ -185,6 +202,13 @@ private: Vector _flavour_tiles; float _flavour_chance; +#ifdef MODULE_FASTNOISE_ENABLED + Ref _offset_noise; + float _offset_noise_strength; + bool _offset_noise_randomize_seed; + bool _offset_noise_skip_edges; +#endif + Vector> _materials; };