Merge pull request #78378 from 0xafbf/curve-evaluate-correct-transform

Changed the way the rotation of a curve at a point is evaluated to match PathFollow2D
This commit is contained in:
Rémi Verschelde 2024-01-04 16:38:38 +01:00
commit b88eddb682
No known key found for this signature in database
GPG key ID: C3336907360768E1
4 changed files with 36 additions and 18 deletions

View file

@ -107,16 +107,14 @@
<param index="0" name="offset" type="float" default="0.0" />
<param index="1" name="cubic" type="bool" default="false" />
<description>
Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve, with [member Transform2D.origin] as the point position, [member Transform2D.x] as the sideways vector, and [member Transform2D.y] as the forward vector. Returns an empty transform if the length of the curve is [code]0[/code].
Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve, with [member Transform2D.origin] as the point position and the [member Transform2D.x] vector pointing in the direction of the path at that point. Returns an empty transform if the length of the curve is [code]0[/code].
[codeblock]
var baked = curve.sample_baked_with_rotation(offset)
# This will rotate and position the node with the up direction pointing along the curve.
# The returned Transform2D can be set directly.
transform = baked
# You can also read the origin and rotation separately from the returned Transform2D.
position = baked.get_origin()
rotation = baked.get_rotation()
# Alternatively, not preserving scale.
transform = baked * Transform2D.FLIP_Y
# To match the rotation of PathFollow2D, not preserving scale.
transform = Transform2D(baked.y, baked.x, baked.origin)
[/codeblock]
</description>
</method>

View file

@ -146,8 +146,8 @@ void Path2D::_notification(int p_what) {
for (int i = 0; i < sample_count; i++) {
const Vector2 p = r[i].get_origin();
const Vector2 side = r[i].columns[0];
const Vector2 forward = r[i].columns[1];
const Vector2 side = r[i].columns[1];
const Vector2 forward = r[i].columns[0];
// Fish Bone.
w[0] = p + (side - forward) * 5;
@ -232,8 +232,8 @@ void PathFollow2D::_update_transform() {
if (rotates) {
Transform2D xform = c->sample_baked_with_rotation(progress, cubic);
xform.translate_local(v_offset, h_offset);
set_rotation(xform[1].angle());
xform.translate_local(h_offset, v_offset);
set_rotation(xform[0].angle());
set_position(xform[2]);
} else {
Vector2 pos = c->sample_baked(progress, cubic);

View file

@ -977,7 +977,7 @@ Transform2D Curve2D::_sample_posture(Interval p_interval) const {
const Vector2 forward = forward_begin.slerp(forward_end, frac).normalized();
const Vector2 side = Vector2(-forward.y, forward.x);
return Transform2D(side, forward, Vector2(0.0, 0.0));
return Transform2D(forward, side, Vector2(0.0, 0.0));
}
Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {

View file

@ -155,17 +155,37 @@ TEST_CASE("[Curve2D] Sampling") {
SUBCASE("sample_baked_with_rotation") {
const real_t pi = 3.14159;
Transform2D t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 0)));
CHECK(t.get_origin() == Vector2(0, 0));
CHECK(Math::is_equal_approx(t.get_rotation(), pi));
const real_t half_pi = pi * 0.5;
Ref<Curve2D> rot_curve = memnew(Curve2D);
Transform2D t;
t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 25)));
rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(50, 0));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(25, 0));
CHECK(Math::is_equal_approx(t.get_rotation(), 0));
rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(0, 50));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(0, 25));
CHECK(Math::is_equal_approx(t.get_rotation(), half_pi));
rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(-50, 0));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(-25, 0));
CHECK(Math::is_equal_approx(t.get_rotation(), pi));
t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 50)));
CHECK(t.get_origin() == Vector2(0, 50));
CHECK(Math::is_equal_approx(t.get_rotation(), pi));
rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(0, -50));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(0, -25));
CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi));
}
SUBCASE("get_closest_point") {