feat: implemented smooth paths
This commit is contained in:
parent
9ea66df220
commit
fac1f4c733
3 changed files with 101 additions and 30 deletions
|
|
@ -84,6 +84,9 @@ void TerrainModifierDistance::curves_changed() {
|
|||
if (!update_bounds()) {
|
||||
push_changed(get_bounds());
|
||||
}
|
||||
this->lock.lock_exclusive();
|
||||
this->distance_weight_curve_buffer = this->distance_weight_curve.is_valid() ? this->distance_weight_curve->duplicate(true) : nullptr;
|
||||
this->lock.unlock_exclusive();
|
||||
}
|
||||
|
||||
bool TerrainModifierDistance::update_bounds() {
|
||||
|
|
@ -99,9 +102,9 @@ bool TerrainModifierDistance::update_bounds() {
|
|||
bounds.size = { max_diameter, max_diameter };
|
||||
bounds.position -= { max_radius, max_radius };
|
||||
}
|
||||
bool const changed{ before != bounds };
|
||||
this->lock.unlock_shared();
|
||||
this->lock.lock_exclusive();
|
||||
bool const changed{ before != bounds };
|
||||
set_bounds(bounds);
|
||||
this->lock.unlock_exclusive();
|
||||
return changed;
|
||||
|
|
@ -132,19 +135,17 @@ float TerrainModifierDistance::distance_at(Vector2 const &world_coordinate) {
|
|||
|
||||
float TerrainModifierDistance::evaluate_at(Vector2 world_coordinate, float before) {
|
||||
this->lock.lock_shared();
|
||||
if (this->distance_weight_curve.is_null()) {
|
||||
if (this->distance_weight_curve_buffer.is_null()) {
|
||||
this->lock.unlock_shared();
|
||||
return before;
|
||||
}
|
||||
float const distance{ distance_at(world_coordinate) };
|
||||
if (distance >= this->distance_weight_curve->get_max_domain()) {
|
||||
if (distance >= this->distance_weight_curve_buffer->get_max_domain()) {
|
||||
this->lock.unlock_shared();
|
||||
return before;
|
||||
}
|
||||
float const weight_offset{
|
||||
std::clamp(distance, this->distance_weight_curve->get_min_domain(), this->distance_weight_curve->get_max_domain())
|
||||
};
|
||||
float const weight{ this->distance_weight_curve->sample(weight_offset) };
|
||||
float const weight_offset{ std::clamp(distance, this->distance_weight_curve_buffer->get_min_domain(), this->distance_weight_curve_buffer->get_max_domain()) };
|
||||
float const weight{ this->distance_weight_curve_buffer->sample(weight_offset) };
|
||||
float out{ weight <= 0.f ? before : Math::lerp(before, get_thread_safe_global_position().y, weight) };
|
||||
this->lock.unlock_shared();
|
||||
|
||||
|
|
@ -213,6 +214,10 @@ void TerrainModifierPath::curves_changed() {
|
|||
if (!update_bounds()) {
|
||||
push_changed(get_bounds());
|
||||
}
|
||||
this->lock.lock_exclusive();
|
||||
this->curve_left_buffer = this->curve_left.is_valid() ? this->curve_left->duplicate(true) : nullptr;
|
||||
this->curve_right_buffer = this->curve_right.is_valid() ? this->curve_right->duplicate(true) : nullptr;
|
||||
this->lock.unlock_exclusive();
|
||||
}
|
||||
|
||||
bool TerrainModifierPath::update_bounds() {
|
||||
|
|
@ -240,7 +245,9 @@ bool TerrainModifierPath::update_bounds() {
|
|||
Rect2 bounds{ min, max - min };
|
||||
bool const changed{ bounds != get_bounds() };
|
||||
this->lock.unlock_shared();
|
||||
this->lock.lock_exclusive();
|
||||
set_bounds(bounds);
|
||||
this->lock.unlock_exclusive();
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
|
@ -284,10 +291,14 @@ float TerrainModifierPath::evaluate_line(Vector3 a, bool a_end, Vector3 b, bool
|
|||
|
||||
float TerrainModifierPath::evaluate_at(Vector2 world_coordinate, float before) {
|
||||
this->lock.lock_shared();
|
||||
if (this->curve_left.is_null() || this->curve_right.is_null() || this->points.size() <= 1) {
|
||||
if (this->curve_left_buffer.is_null() || this->points.size() <= 1) {
|
||||
this->lock.unlock_shared();
|
||||
return before;
|
||||
}
|
||||
Ref<Curve> right_curve{ this->curve_right_buffer };
|
||||
if (right_curve.is_null()) {
|
||||
right_curve = this->curve_left_buffer;
|
||||
}
|
||||
float out_score{ 0.f };
|
||||
float out_delta{ 0.f };
|
||||
long const count{ this->closed ? this->points.size() : this->points.size() - 1 };
|
||||
|
|
@ -296,29 +307,30 @@ float TerrainModifierPath::evaluate_at(Vector2 world_coordinate, float before) {
|
|||
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 left{ this->curve_left_buffer->sample(distance) };
|
||||
float const right{ right_curve->sample(distance) };
|
||||
float const ndot{ dot / distance };
|
||||
float separation{ ndot / 2.f + 0.5f };
|
||||
float turn{ ndot };
|
||||
Vector3 const right_direction{ (this->points[Math::wrapi(i + 1, 0, this->points.size())] - ipos).cross({ 0, 1, 0 }) };
|
||||
float turn{ 0.f };
|
||||
Vector3 const right_direction{ (this->points[Math::wrapi(i + 1, 0, this->points.size())] - ipos).normalized().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;
|
||||
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;
|
||||
separation = turn >= 0 ? 0 : 1;
|
||||
} else if (!is_start && !is_end) {
|
||||
separation = Math::round(separation);
|
||||
turn = -dot;
|
||||
}
|
||||
if (turn / turn == dot / dot) {
|
||||
if ((percentage > 0.f && percentage < 1.f) || Math::abs(turn) / turn != Math::abs(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 };
|
||||
float const score{ Math::abs(delta) };
|
||||
if (score > out_score) {
|
||||
out_score = score;
|
||||
out_delta = delta * score;
|
||||
out_delta = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -326,7 +338,7 @@ float TerrainModifierPath::evaluate_at(Vector2 world_coordinate, float before) {
|
|||
if (out_score == 0.f) {
|
||||
return before;
|
||||
}
|
||||
return before + (out_delta / out_score);
|
||||
return before + out_delta;
|
||||
}
|
||||
|
||||
void TerrainModifierPath::path_changed() {
|
||||
|
|
@ -369,6 +381,14 @@ PackedStringArray TerrainModifierPath::get_configuration_warnings() const {
|
|||
|
||||
void TerrainModifierPath::set_curve_left(Ref<Curve> curve) {
|
||||
this->lock.lock_exclusive();
|
||||
if (curve.is_valid() && curve == this->curve_right) {
|
||||
curve = curve->duplicate();
|
||||
} else if (!curve.is_valid() && this->curve_right.is_valid()) {
|
||||
curve = this->curve_right;
|
||||
this->lock.unlock_exclusive();
|
||||
set_curve_right(nullptr);
|
||||
this->lock.lock_exclusive();
|
||||
}
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
if (this->curve_left.is_valid()) {
|
||||
this->curve_left->disconnect_changed(callable_mp(this, &self_type::curves_changed));
|
||||
|
|
@ -389,6 +409,9 @@ Ref<Curve> TerrainModifierPath::get_curve_left() const {
|
|||
|
||||
void TerrainModifierPath::set_curve_right(Ref<Curve> curve) {
|
||||
this->lock.lock_exclusive();
|
||||
if (curve.is_valid() && curve == this->curve_left) {
|
||||
curve = curve->duplicate();
|
||||
}
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
if (this->curve_right.is_valid()) {
|
||||
this->curve_right->disconnect_changed(callable_mp(this, &self_type::curves_changed));
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
private:
|
||||
SharedMutex lock{};
|
||||
Ref<Curve> distance_weight_curve{};
|
||||
Ref<Curve> distance_weight_curve_buffer{};
|
||||
|
||||
public:
|
||||
void set_distance_weight_curve(Ref<Curve> curve);
|
||||
|
|
@ -99,7 +100,9 @@ private:
|
|||
float max_height{};
|
||||
bool closed{ false };
|
||||
Vector<Vector3> points{};
|
||||
Ref<Curve> curve_left_buffer{};
|
||||
Ref<Curve> curve_left{};
|
||||
Ref<Curve> curve_right_buffer{};
|
||||
Ref<Curve> curve_right{};
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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.030682996, 0, 0, Vector2(100, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 2
|
||||
_data = [Vector2(0, 1), 0.0, -0.019399326, 0, 0, Vector2(43.078506, 0.46632487), -0.02627238, -0.02627238, 0, 0, Vector2(100, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="Curve" id="Curve_w3uoq"]
|
||||
_limits = [0.0, 1.0, 0.0, 101.07341]
|
||||
|
|
@ -24,7 +24,12 @@ point_count = 2
|
|||
|
||||
[sub_resource type="Curve" id="Curve_chm2y"]
|
||||
_limits = [0.0, 1.0, 0.0, 300.0]
|
||||
_data = [Vector2(0, 1), -0.005856493, -0.0020244052, 0, 0, Vector2(195.24551, 0.17229712), -0.0043557375, -0.0043557375, 0, 0, Vector2(300, 0), 0.00031304389, -0.05797184, 0, 0]
|
||||
_data = [Vector2(0, 1), -0.005856493, -0.00037566788, 0, 0, Vector2(103.49251, 0.80491185), -0.0043557375, -0.0043557375, 0, 0, Vector2(300, 0), 0.00031304389, -0.05797184, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="Curve" id="Curve_o3i6r"]
|
||||
_limits = [0.0, 1.0, 0.0, 5.0]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.5354336, 1), 0.0, 0.0, 0, 0, Vector2(5, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_kbmr5"]
|
||||
|
|
@ -40,38 +45,78 @@ chunk_size = 100
|
|||
thread_count = 5
|
||||
|
||||
[node name="TerrainModifierPath" type="TerrainModifierPath" parent="Terrain" unique_id=462259542]
|
||||
transform = Transform3D(1.9138145, 0, 0, 0, 0.6860331, 0, 0, 0, 2.7343204, 190.712, 125.888245, 634.1432)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 377.77588, 108.75322, 652.4378)
|
||||
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.99999976, -5.4521523, -33.998764, -98.341095)
|
||||
transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.99999976, -180.28406, -81.73056, -295.60077)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[node name="TerrainModifierPathPoint5" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=2007122252]
|
||||
transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, 33.986214, 4.6532135, -47.78543)
|
||||
transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, -117.323944, -72.07858, -209.4972)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[node name="TerrainModifierPathPoint2" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=88875414]
|
||||
transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, -45.605103, -77.62694, -7.8362274)
|
||||
transform = Transform3D(0.9999999, 0, 0, 0, 1, 0, 0, 0, 0.9999999, -186.47693, -104.63211, -100.22473)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[node name="TerrainModifierPathPoint3" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=910243114]
|
||||
transform = Transform3D(-0.08673841, 0, 0.9962309, 0, 1, 0, -0.99623066, 0, -0.0867384, 51.146767, 185.18083, 46.93416)
|
||||
transform = Transform3D(0.9999996, 0, 0, 0, 1, 0, 0, 0, 0.9999998, -72.87836, -24.743164, -14.561768)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[node name="TerrainModifierPathPoint4" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=738726374]
|
||||
transform = Transform3D(-0.5568029, 0, 0.8306443, 0, 1, 0, -0.83064425, 0, -0.556803, 181.23196, -50.373947, -56.57155)
|
||||
transform = Transform3D(0.99999976, 0, 0, 0, 1, 0, 0, 0, 0.99999976, 69.492004, -25.579193, -103.737305)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[node name="TerrainModifierPathPoint6" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=868243973]
|
||||
transform = Transform3D(-0.5568028, 0, 0.8306443, 0, 1, 0, -0.830644, 0, -0.55680287, 206.74478, -50.373917, 13.438446)
|
||||
transform = Transform3D(0.9999994, 0, 0, 0, 1, 0, 0, 0, 0.9999997, 191.05371, -25.255402, -19.047241)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[node name="TerrainModifierPathPoint7" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath" unique_id=601656436]
|
||||
transform = Transform3D(-0.5568028, 0, 0.8306443, 0, 1, 0, -0.8306439, 0, -0.55680287, 192.3706, 12.87825, 78.11276)
|
||||
transform = Transform3D(0.99999934, 0, 0, 0, 1, 0, 0, 0, 0.9999997, 160.64337, -4.200287, 123.704346)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[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)
|
||||
transform = Transform3D(0.99999934, 0, 0, 0, 1, 0, 0, 0, 0.9999997, 271.10236, -19.105774, 225.51074)
|
||||
gizmo_extents = 10.0
|
||||
|
||||
[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)
|
||||
distance_weight_curve = SubResource("Curve_chm2y")
|
||||
|
||||
[node name="TerrainModifierPath2" type="TerrainModifierPath" parent="Terrain" unique_id=515690726]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 368.5579, 5.0770416, 414.4787)
|
||||
curve_left = SubResource("Curve_o3i6r")
|
||||
|
||||
[node name="TerrainModifierPathPoint7" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=283037782]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 30.025024, -5.665145, -37.19107)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="TerrainModifierPathPoint6" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=1696432484]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12.917389, -9.399911, -41.447937)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="TerrainModifierPathPoint" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=870583505]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.7605286, -10.70397, -33.974182)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="TerrainModifierPathPoint2" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=2085062411]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -17.681885, -11.332738, -8.841034)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="TerrainModifierPathPoint3" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=1608777346]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -21.356476, -11.604663, 8.474121)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="TerrainModifierPathPoint4" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=2089784013]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -14.419983, -9.546529, 16.345459)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="TerrainModifierPathPoint5" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath2" unique_id=732306824]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.16311646, -7.533708, 20.998108)
|
||||
gizmo_extents = 1.0
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1089775425]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 625.56537, 191.07982, 795.4992)
|
||||
mesh = SubResource("BoxMesh_kbmr5")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue