diff --git a/modules/terrain/terrain_modifier.cpp b/modules/terrain/terrain_modifier.cpp index 2d5e2a85..cee3550d 100644 --- a/modules/terrain/terrain_modifier.cpp +++ b/modules/terrain/terrain_modifier.cpp @@ -262,7 +262,7 @@ void TerrainModifierPath::_notification(int what) { } } -float TerrainModifierPath::evaluate_line(Vector3 a, bool a_end, Vector3 b, bool b_end, Vector2 world_coordinate, float &out_dot, float &out_distance) { +float TerrainModifierPath::evaluate_line(Vector3 a, bool a_end, Vector3 b, bool b_end, Vector2 world_coordinate, float &out_dot, float &out_distance, float &out_percentage) { Vector2 a2{ a.x, a.z }, b2{ b.x, b.z }; Vector2 const relative_coordinate{ world_coordinate - a2 }; Vector2 const difference2{ b2 - a2 }; @@ -272,10 +272,11 @@ float TerrainModifierPath::evaluate_line(Vector3 a, bool a_end, Vector3 b, bool Vector2 const right{ -difference.z, difference.x }; out_dot = right.normalized().dot(relative_coordinate); out_distance = world_coordinate.distance_to({ closest_on_line.x, closest_on_line.z }); - if (a_end) { + out_percentage = w; + if (!a_end) { w = w > 0 ? w : 0; } - if (b_end) { + if (!b_end) { w = w < 1 ? w : 1; } return a.y + (b.y - a.y) * w; @@ -287,30 +288,45 @@ float TerrainModifierPath::evaluate_at(Vector2 world_coordinate, float before) { this->lock.unlock_shared(); return before; } - float const max_distance{ this->curve_left->get_max_domain() > this->curve_right->get_max_domain() ? this->curve_left->get_max_domain() : this->curve_right->get_max_domain() }; - float out_score{ -INFINITY }; - float out_height{ 0 }; + float out_score{ 0.f }; + float out_delta{ 0.f }; long const count{ this->closed ? this->points.size() : this->points.size() - 1 }; for (int i{ 0 }; i < count; i++) { - float dot, distance; - float const height{ evaluate_line(this->points[i], !this->closed && i == 0, this->points[Math::wrapi(i + 1, 0, this->points.size())], !this->closed && i == count - 1, world_coordinate, dot, distance) }; + Vector3 const ipos{ this->points[i] }; + float dot, distance, percentage; + bool const is_start{ !this->closed && i == 0 }, is_end{ !this->closed && i == count - 1 }; + float const height{ evaluate_line(ipos, is_start, this->points[Math::wrapi(i + 1, 0, this->points.size())], is_end, world_coordinate, dot, distance, percentage) }; float const left{ this->curve_left->sample(distance) }; float const right{ this->curve_right->sample(distance) }; float const ndot{ dot / distance }; float separation{ ndot / 2.f + 0.5f }; - if (closed || (i > 0 && i < count - 1)) { + float turn{ ndot }; + Vector3 const right_direction{ (this->points[Math::wrapi(i + 1, 0, this->points.size())] - ipos).cross({ 0, 1, 0 }) }; + if (!is_end && percentage >= 1.f) { + turn = (this->points[Math::wrapi(i + 2, 0, this->points.size())] - ipos).dot(right_direction); + separation = turn <= 0 ? 0 : 1; + } else if (!is_start && percentage <= 0.f) { + turn = (this->points[Math::wrapi(i - 1, 0, this->points.size())] - ipos).dot(right_direction); + separation = turn <= 0 ? 0 : 1; + } else if (!is_start && !is_end) { separation = Math::round(separation); } - float const weight{ left * (1 - separation) + right * separation }; - float const blended_height{ Math::lerp(before, height, weight) }; - float const score{ weight - (1 - Math::abs(ndot)) * 2.f - (distance / max_distance) }; - if (score > out_score) { - out_score = score; - out_height = blended_height; + if (turn / turn == dot / dot) { + float const weight{ left * (1 - separation) + right * separation }; + float const blended_height{ Math::lerp(before, height, weight) }; + float const delta{ blended_height - before }; + float const score{ weight }; + if (score > out_score) { + out_score = score; + out_delta = delta * score; + } } } this->lock.unlock_shared(); - return out_height; + if (out_score == 0.f) { + return before; + } + return before + (out_delta / out_score); } void TerrainModifierPath::path_changed() { diff --git a/modules/terrain/terrain_modifier.h b/modules/terrain/terrain_modifier.h index 4585a6f6..b34146f9 100644 --- a/modules/terrain/terrain_modifier.h +++ b/modules/terrain/terrain_modifier.h @@ -86,7 +86,7 @@ class TerrainModifierPath : public TerrainModifier { protected: void _notification(int what); - float evaluate_line(Vector3 a, bool a_end, Vector3 b, bool b_end, Vector2 world_coordinate, float &out_dot, float &out_distance); + float evaluate_line(Vector3 a, bool a_end, Vector3 b, bool b_end, Vector2 world_coordinate, float &out_dot, float &out_distance, float &out_percentage); public: float evaluate_at(Vector2 world_coordinate, float before) override; diff --git a/project/scenes/terrain_test.tscn b/project/scenes/terrain_test.tscn index e955b2b6..060776e4 100644 --- a/project/scenes/terrain_test.tscn +++ b/project/scenes/terrain_test.tscn @@ -14,8 +14,8 @@ sky = SubResource("Sky_w3uoq") [sub_resource type="Curve" id="Curve_kbmr5"] _limits = [0.0, 1.0, 0.0, 100.0] -_data = [Vector2(0, 1), 0.0, -0.0015643721, 0, 0, Vector2(60.370926, 0.60930693), -0.018071167, -0.018071167, 0, 0, Vector2(100, 0), 0.0, 0.0, 0, 0] -point_count = 3 +_data = [Vector2(0, 1), 0.0, -0.030682996, 0, 0, Vector2(100, 0), 0.0, 0.0, 0, 0] +point_count = 2 [sub_resource type="Curve" id="Curve_w3uoq"] _limits = [0.0, 1.0, 0.0, 101.07341] @@ -40,30 +40,33 @@ chunk_size = 100 thread_count = 5 [node name="TerrainModifierPath" type="TerrainModifierPath" parent="Terrain" unique_id=462259542] -transform = Transform3D(2.7896824, 0, 0, 0, 1, 0, 0, 0, 3.9856973, 188.70874, 151.32993, 528.5824) +transform = Transform3D(1.9138145, 0, 0, 0, 0.6860331, 0, 0, 0, 2.7343204, 190.712, 125.888245, 634.1432) curve_left = SubResource("Curve_kbmr5") curve_right = SubResource("Curve_w3uoq") [node name="TerrainModifierPathPoint" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=1975236067] -transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, -6.678116, -33.99875, -74.15768) +transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.99999976, -5.4521523, -33.998764, -98.341095) [node name="TerrainModifierPathPoint5" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=2007122252] -transform = Transform3D(0.99999994, 0, 0, 0, 1, 0, 0, 0, 0.99999994, 41.63815, 4.6532288, -38.86402) +transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, 33.986214, 4.6532135, -47.78543) [node name="TerrainModifierPathPoint2" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=88875414] -transform = Transform3D(0.99999994, 0, 0, 0, 1, 0, 0, 0, 0.99999994, 4.2666435, -27.249336, 5.506424) +transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, -45.605103, -77.62694, -7.8362274) [node name="TerrainModifierPathPoint3" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=910243114] -transform = Transform3D(-0.08673841, 0, 0.9962309, 0, 1, 0, -0.9962308, 0, -0.08673839, 77.83667, 84.083954, 12.383522) +transform = Transform3D(-0.08673841, 0, 0.9962309, 0, 1, 0, -0.99623066, 0, -0.0867384, 51.146767, 185.18083, 46.93416) [node name="TerrainModifierPathPoint4" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=738726374] -transform = Transform3D(-0.08673839, 0, 0.9962309, 0, 1, 0, -0.9962308, 0, -0.08673841, 124.05687, -50.373947, -21.531578) +transform = Transform3D(-0.5568029, 0, 0.8306443, 0, 1, 0, -0.83064425, 0, -0.556803, 181.23196, -50.373947, -56.57155) [node name="TerrainModifierPathPoint6" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=868243973] -transform = Transform3D(-0.08673839, 0, 0.9962309, 0, 1, 0, -0.99623066, 0, -0.08673841, 163.78015, -50.373917, 24.09636) +transform = Transform3D(-0.5568028, 0, 0.8306443, 0, 1, 0, -0.830644, 0, -0.55680287, 206.74478, -50.373917, 13.438446) [node name="TerrainModifierPathPoint7" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=601656436] -transform = Transform3D(-0.08673839, 0, 0.9962309, 0, 1, 0, -0.99623054, 0, -0.08673841, 106.59272, 12.878235, 75.88286) +transform = Transform3D(-0.5568028, 0, 0.8306443, 0, 1, 0, -0.8306439, 0, -0.55680287, 192.3706, 12.87825, 78.11276) + +[node name="TerrainModifierPathPoint8" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=300006660] +transform = Transform3D(-0.5568028, 0, 0.8306443, 0, 1, 0, -0.8306439, 0, -0.55680287, 289.17203, 36.37845, 54.197342) [node name="TerrainModifierDistance8" type="TerrainModifierDistance" parent="Terrain" unique_id=1993490768] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 784.91595, 251.11382, 135.92102)