Skip to content

Commit

Permalink
Merge pull request #78378 from 0xafbf/curve-evaluate-correct-transform
Browse files Browse the repository at this point in the history
Changed the way the rotation of a curve at a point is evaluated to match PathFollow2D
  • Loading branch information
akien-mga committed Jan 4, 2024
2 parents 0d18a94 + acae382 commit b88eddb
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 19 deletions.
10 changes: 4 additions & 6 deletions doc/classes/Curve2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
8 changes: 4 additions & 4 deletions scene/2d/path_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion scene/resources/curve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
36 changes: 28 additions & 8 deletions tests/scene/test_curve_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));

t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 25)));
const real_t half_pi = pi * 0.5;
Ref<Curve2D> rot_curve = memnew(Curve2D);
Transform2D t;

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(), pi));
CHECK(Math::is_equal_approx(t.get_rotation(), half_pi));

t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 50)));
CHECK(t.get_origin() == Vector2(0, 50));
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));

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") {
Expand Down

0 comments on commit b88eddb

Please sign in to comment.