Skip to content

Commit

Permalink
Fix Pathfollow direction
Browse files Browse the repository at this point in the history
Co-authored-by: aaronfranke <arnfranke@yahoo.com>
  • Loading branch information
TokageItLab and aaronfranke committed May 24, 2023
1 parent dc625bc commit 42aa539
Show file tree
Hide file tree
Showing 12 changed files with 60 additions and 53 deletions.
1 change: 1 addition & 0 deletions doc/classes/Basis.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
<description>
Creates a Basis with a rotation such that the forward axis (-Z) points towards the [param target] position.
The up axis (+Y) points as close to the [param up] vector as possible while staying perpendicular to the forward axis. The resulting Basis is orthonormalized. The [param target] and [param up] vectors cannot be zero, and cannot be parallel to each other.
If [param use_model_front] is [code]true[/code], the +Z axis (asset front) is treated as forward (implies +X is left) and points toward the [param target] position. By default, the -Z axis (camera forward) is treated as forward (implies +X is right).
</description>
</method>
<method name="orthonormalized" qualifiers="const">
Expand Down
3 changes: 2 additions & 1 deletion doc/classes/Node3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@
<param index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<param index="2" name="use_model_front" type="bool" default="false" />
<description>
Rotates the node so that the local forward axis (-Z, [constant Vector3.FORWARD]) points toward the [param target] position. If the [param use_model_front] options is specified, then the model is oriented in reverse, towards the model front axis (+Z, [constant Vector3.MODEL_FRONT]), which is more useful for orienting 3D models.
Rotates the node so that the local forward axis (-Z, [constant Vector3.FORWARD]) points toward the [param target] position.
The local up axis (+Y) points as close to the [param up] vector as possible while staying perpendicular to the local forward axis. The resulting transform is orthogonal, and the scale is preserved. Non-uniform scaling may not work correctly.
The [param target] position cannot be the same as the node's position, the [param up] vector cannot be zero, and the direction from the node's position to the [param target] vector cannot be parallel to the [param up] vector.
Operations take place in global space, which means that the node must be in the scene tree.
If [param use_model_front] is [code]true[/code], the +Z axis (asset front) is treated as forward (implies +X is left) and points toward the [param target] position. By default, the -Z axis (camera forward) is treated as forward (implies +X is right).
</description>
</method>
<method name="look_at_from_position">
Expand Down
3 changes: 0 additions & 3 deletions doc/classes/PathFollow2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
<member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset" default="0.0">
The node's offset along the curve.
</member>
<member name="lookahead" type="float" setter="set_lookahead" getter="get_lookahead" default="4.0">
How far to look ahead of the curve to calculate the tangent if the node is rotating. E.g. shorter lookaheads will lead to faster rotations.
</member>
<member name="loop" type="bool" setter="set_loop" getter="has_loop" default="true">
If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths.
</member>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/PathFollow3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
<member name="tilt_enabled" type="bool" setter="set_tilt_enabled" getter="is_tilt_enabled" default="true">
If [code]true[/code], the tilt property of [Curve3D] takes effect.
</member>
<member name="use_model_front" type="bool" setter="set_use_model_front" getter="is_using_model_front" default="false">
If [code]true[/code], the node moves on the travel path with orienting the +Z axis as forward. See also [constant Vector3.FORWARD] and [constant Vector3.MODEL_FRONT].
</member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The node's offset perpendicular to the curve.
</member>
Expand Down
1 change: 1 addition & 0 deletions doc/classes/Transform3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<description>
Returns a copy of the transform rotated such that the forward axis (-Z) points towards the [param target] position.
The up axis (+Y) points as close to the [param up] vector as possible while staying perpendicular to the forward axis. The resulting transform is orthonormalized. The existing rotation, scale, and skew information from the original transform is discarded. The [param target] and [param up] vectors cannot be zero, cannot be parallel to each other, and are defined in global/parent space.
If [param use_model_front] is [code]true[/code], the +Z axis (asset front) is treated as forward (implies +X is left) and points toward the [param target] position. By default, the -Z axis (camera forward) is treated as forward (implies +X is right).
</description>
</method>
<method name="orthonormalized" qualifiers="const">
Expand Down
4 changes: 2 additions & 2 deletions editor/plugins/path_3d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ void Path3DGizmo::redraw() {

// Fish Bone.
v3p.push_back(p1);
v3p.push_back(p1 + (side - forward + up * 0.3) * 0.06);
v3p.push_back(p1 + (side + forward + up * 0.3) * 0.06);

v3p.push_back(p1);
v3p.push_back(p1 + (-side - forward + up * 0.3) * 0.06);
v3p.push_back(p1 + (-side + forward + up * 0.3) * 0.06);
}

add_lines(v3p, path_material);
Expand Down
32 changes: 10 additions & 22 deletions scene/2d/path_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,11 @@ void PathFollow2D::_notification(int p_what) {
}
}

void PathFollow2D::set_cubic_interpolation(bool p_enable) {
cubic = p_enable;
void PathFollow2D::set_cubic_interpolation_enabled(bool p_enabled) {
cubic = p_enabled;
}

bool PathFollow2D::get_cubic_interpolation() const {
bool PathFollow2D::is_cubic_interpolation_enabled() const {
return cubic;
}

Expand Down Expand Up @@ -312,26 +312,22 @@ void PathFollow2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_progress_ratio", "ratio"), &PathFollow2D::set_progress_ratio);
ClassDB::bind_method(D_METHOD("get_progress_ratio"), &PathFollow2D::get_progress_ratio);

ClassDB::bind_method(D_METHOD("set_rotates", "enable"), &PathFollow2D::set_rotates);
ClassDB::bind_method(D_METHOD("is_rotating"), &PathFollow2D::is_rotating);
ClassDB::bind_method(D_METHOD("set_rotates", "enabled"), &PathFollow2D::set_rotation_enabled);
ClassDB::bind_method(D_METHOD("is_rotating"), &PathFollow2D::is_rotation_enabled);

ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &PathFollow2D::set_cubic_interpolation);
ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow2D::get_cubic_interpolation);
ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enabled"), &PathFollow2D::set_cubic_interpolation_enabled);
ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow2D::is_cubic_interpolation_enabled);

ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow2D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow2D::has_loop);

ClassDB::bind_method(D_METHOD("set_lookahead", "lookahead"), &PathFollow2D::set_lookahead);
ClassDB::bind_method(D_METHOD("get_lookahead"), &PathFollow2D::get_lookahead);

ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_less,or_greater,suffix:px"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_less,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotates"), "set_rotates", "is_rotating");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001"), "set_lookahead", "get_lookahead");
}

void PathFollow2D::set_progress(real_t p_progress) {
Expand Down Expand Up @@ -395,20 +391,12 @@ real_t PathFollow2D::get_progress_ratio() const {
}
}

void PathFollow2D::set_lookahead(real_t p_lookahead) {
lookahead = p_lookahead;
}

real_t PathFollow2D::get_lookahead() const {
return lookahead;
}

void PathFollow2D::set_rotates(bool p_rotates) {
rotates = p_rotates;
void PathFollow2D::set_rotation_enabled(bool p_enabled) {
rotates = p_enabled;
_update_transform();
}

bool PathFollow2D::is_rotating() const {
bool PathFollow2D::is_rotation_enabled() const {
return rotates;
}

Expand Down
12 changes: 4 additions & 8 deletions scene/2d/path_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ class PathFollow2D : public Node2D {
Timer *update_timer = nullptr;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
real_t lookahead = 4.0;
bool cubic = true;
bool loop = true;
bool rotates = true;
Expand Down Expand Up @@ -98,17 +97,14 @@ class PathFollow2D : public Node2D {
void set_progress_ratio(real_t p_ratio);
real_t get_progress_ratio() const;

void set_lookahead(real_t p_lookahead);
real_t get_lookahead() const;

void set_loop(bool p_loop);
bool has_loop() const;

void set_rotates(bool p_rotates);
bool is_rotating() const;
void set_rotation_enabled(bool p_enabled);
bool is_rotation_enabled() const;

void set_cubic_interpolation(bool p_enable);
bool get_cubic_interpolation() const;
void set_cubic_interpolation_enabled(bool p_enabled);
bool is_cubic_interpolation_enabled() const;

PackedStringArray get_configuration_warnings() const override;

Expand Down
29 changes: 22 additions & 7 deletions scene/3d/path_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
t.origin = pos;
} else {
t = c->sample_baked_with_rotation(progress, cubic, false);
if (use_model_front) {
t.basis *= Basis::from_scale(Vector3(-1.0, 1.0, -1.0));
}
Vector3 forward = t.basis.get_column(2); // Retain tangent for applying tilt
t = PathFollow3D::correct_posture(t, rotation_mode);

Expand Down Expand Up @@ -230,11 +233,11 @@ void PathFollow3D::_notification(int p_what) {
}
}

void PathFollow3D::set_cubic_interpolation(bool p_enable) {
cubic = p_enable;
void PathFollow3D::set_cubic_interpolation_enabled(bool p_enabled) {
cubic = p_enabled;
}

bool PathFollow3D::get_cubic_interpolation() const {
bool PathFollow3D::is_cubic_interpolation_enabled() const {
return cubic;
}

Expand Down Expand Up @@ -314,8 +317,11 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rotation_mode", "rotation_mode"), &PathFollow3D::set_rotation_mode);
ClassDB::bind_method(D_METHOD("get_rotation_mode"), &PathFollow3D::get_rotation_mode);

ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &PathFollow3D::set_cubic_interpolation);
ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow3D::get_cubic_interpolation);
ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enabled"), &PathFollow3D::set_cubic_interpolation_enabled);
ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow3D::is_cubic_interpolation_enabled);

ClassDB::bind_method(D_METHOD("set_use_model_front", "enabled"), &PathFollow3D::set_use_model_front);
ClassDB::bind_method(D_METHOD("is_using_model_front"), &PathFollow3D::is_using_model_front);

ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop);
Expand All @@ -330,6 +336,7 @@ void PathFollow3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_model_front"), "set_use_model_front", "is_using_model_front");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tilt_enabled"), "set_tilt_enabled", "is_tilt_enabled");
Expand Down Expand Up @@ -412,6 +419,14 @@ PathFollow3D::RotationMode PathFollow3D::get_rotation_mode() const {
return rotation_mode;
}

void PathFollow3D::set_use_model_front(bool p_use_model_front) {
use_model_front = p_use_model_front;
}

bool PathFollow3D::is_using_model_front() const {
return use_model_front;
}

void PathFollow3D::set_loop(bool p_loop) {
loop = p_loop;
}
Expand All @@ -420,8 +435,8 @@ bool PathFollow3D::has_loop() const {
return loop;
}

void PathFollow3D::set_tilt_enabled(bool p_enable) {
tilt_enabled = p_enable;
void PathFollow3D::set_tilt_enabled(bool p_enabled) {
tilt_enabled = p_enabled;
}

bool PathFollow3D::is_tilt_enabled() const {
Expand Down
11 changes: 8 additions & 3 deletions scene/3d/path_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class PathFollow3D : public Node3D {
ROTATION_ORIENTED
};

bool use_model_front = false;

static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);

private:
Expand Down Expand Up @@ -108,14 +110,17 @@ class PathFollow3D : public Node3D {
void set_loop(bool p_loop);
bool has_loop() const;

void set_tilt_enabled(bool p_enable);
void set_tilt_enabled(bool p_enabled);
bool is_tilt_enabled() const;

void set_rotation_mode(RotationMode p_rotation_mode);
RotationMode get_rotation_mode() const;

void set_cubic_interpolation(bool p_enable);
bool get_cubic_interpolation() const;
void set_use_model_front(bool p_use_model_front);
bool is_using_model_front() const;

void set_cubic_interpolation_enabled(bool p_enabled);
bool is_cubic_interpolation_enabled() const;

PackedStringArray get_configuration_warnings() const override;

Expand Down
8 changes: 4 additions & 4 deletions scene/resources/curve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1648,9 +1648,9 @@ void Curve3D::_bake() const {
Vector3 forward = forward_ptr[0];

if (abs(forward.dot(Vector3(0, 1, 0))) > 1.0 - UNIT_EPSILON) {
frame_prev = Basis::looking_at(-forward, Vector3(1, 0, 0));
frame_prev = Basis::looking_at(forward, Vector3(1, 0, 0));
} else {
frame_prev = Basis::looking_at(-forward, Vector3(0, 1, 0));
frame_prev = Basis::looking_at(forward, Vector3(0, 1, 0));
}

up_write[0] = frame_prev.get_column(1);
Expand Down Expand Up @@ -1809,8 +1809,8 @@ Basis Curve3D::_sample_posture(Interval p_interval, bool p_apply_tilt) const {
}

// Build frames at both ends of the interval, then interpolate.
const Basis frame_begin = Basis::looking_at(-forward_begin, up_begin);
const Basis frame_end = Basis::looking_at(-forward_end, up_end);
const Basis frame_begin = Basis::looking_at(forward_begin, up_begin);
const Basis frame_end = Basis::looking_at(forward_end, up_end);
const Basis frame = frame_begin.slerp(frame_end, frac).orthonormalized();

if (!p_apply_tilt) {
Expand Down
6 changes: 3 additions & 3 deletions tests/scene/test_curve_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ TEST_CASE("[Curve3D] Sampling") {
}

SUBCASE("sample_baked_with_rotation") {
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0))) == Transform3D(Basis(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0)), Vector3(0, 0, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0))) == Transform3D(Basis(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0)), Vector3(0, 25, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0))) == Transform3D(Basis(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0)), Vector3(0, 50, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 0, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 0, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 25, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 25, 0)));
CHECK(curve->sample_baked_with_rotation(curve->get_closest_offset(Vector3(0, 50, 0))) == Transform3D(Basis(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0)), Vector3(0, 50, 0)));
}

SUBCASE("sample_baked_tilt") {
Expand Down

0 comments on commit 42aa539

Please sign in to comment.