Move rotation sampling from Path2D to Curve2D
The rotation sampling code is moved from Path2D to a new method `sample_baked_with_rotation` on Curve2D.
This commit is contained in:
parent
c29fe310f1
commit
399c2a8dea
|
@ -102,6 +102,22 @@
|
||||||
Cubic interpolation tends to follow the curves better, but linear is faster (and often, precise enough).
|
Cubic interpolation tends to follow the curves better, but linear is faster (and often, precise enough).
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="sample_baked_with_rotation" qualifiers="const">
|
||||||
|
<return type="Transform2D" />
|
||||||
|
<param index="0" name="offset" type="float" />
|
||||||
|
<param index="1" name="cubic" type="bool" default="false" />
|
||||||
|
<param index="2" name="loop" type="bool" default="true" />
|
||||||
|
<param index="3" name="lookahead" type="float" default="4.0" />
|
||||||
|
<description>
|
||||||
|
Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve. Returns empty transform if length of the curve is [code]0[/code].
|
||||||
|
Use [param loop] to smooth the tangent at the end of the curve. [param lookahead] defines the distance to a nearby point for calculating the tangent vector.
|
||||||
|
[codeblock]
|
||||||
|
var transform = curve.sample_baked_with_rotation(offset)
|
||||||
|
position = transform.get_origin()
|
||||||
|
rotation = transform.get_rotation()
|
||||||
|
[/codeblock]
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="samplef" qualifiers="const">
|
<method name="samplef" qualifiers="const">
|
||||||
<return type="Vector2" />
|
<return type="Vector2" />
|
||||||
<param index="0" name="fofs" type="float" />
|
<param index="0" name="fofs" type="float" />
|
||||||
|
|
|
@ -175,51 +175,18 @@ void PathFollow2D::_update_transform() {
|
||||||
if (path_length == 0) {
|
if (path_length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Vector2 pos = c->sample_baked(progress, cubic);
|
|
||||||
|
|
||||||
if (rotates) {
|
if (rotates) {
|
||||||
real_t ahead = progress + lookahead;
|
Transform2D xform = c->sample_baked_with_rotation(progress, cubic, loop, lookahead);
|
||||||
|
xform.translate_local(v_offset, h_offset);
|
||||||
if (loop && ahead >= path_length) {
|
set_rotation(xform[1].angle());
|
||||||
// If our lookahead will loop, we need to check if the path is closed.
|
set_position(xform[2]);
|
||||||
int point_count = c->get_point_count();
|
|
||||||
if (point_count > 0) {
|
|
||||||
Vector2 start_point = c->get_point_position(0);
|
|
||||||
Vector2 end_point = c->get_point_position(point_count - 1);
|
|
||||||
if (start_point == end_point) {
|
|
||||||
// Since the path is closed we want to 'smooth off'
|
|
||||||
// the corner at the start/end.
|
|
||||||
// So we wrap the lookahead back round.
|
|
||||||
ahead = Math::fmod(ahead, path_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 ahead_pos = c->sample_baked(ahead, cubic);
|
|
||||||
|
|
||||||
Vector2 tangent_to_curve;
|
|
||||||
if (ahead_pos == pos) {
|
|
||||||
// This will happen at the end of non-looping or non-closed paths.
|
|
||||||
// We'll try a look behind instead, in order to get a meaningful angle.
|
|
||||||
tangent_to_curve =
|
|
||||||
(pos - c->sample_baked(progress - lookahead, cubic)).normalized();
|
|
||||||
} else {
|
|
||||||
tangent_to_curve = (ahead_pos - pos).normalized();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 normal_of_curve = -tangent_to_curve.orthogonal();
|
|
||||||
|
|
||||||
pos += tangent_to_curve * h_offset;
|
|
||||||
pos += normal_of_curve * v_offset;
|
|
||||||
|
|
||||||
set_rotation(tangent_to_curve.angle());
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
Vector2 pos = c->sample_baked(progress, cubic);
|
||||||
pos.x += h_offset;
|
pos.x += h_offset;
|
||||||
pos.y += v_offset;
|
pos.y += v_offset;
|
||||||
}
|
|
||||||
|
|
||||||
set_position(pos);
|
set_position(pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathFollow2D::_notification(int p_what) {
|
void PathFollow2D::_notification(int p_what) {
|
||||||
|
|
|
@ -936,6 +936,46 @@ Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform2D Curve2D::sample_baked_with_rotation(real_t p_offset, bool p_cubic, bool p_loop, real_t p_lookahead) const {
|
||||||
|
real_t path_length = get_baked_length(); // Ensure baked.
|
||||||
|
ERR_FAIL_COND_V_MSG(path_length == 0, Transform2D(), "Length of Curve2D is 0.");
|
||||||
|
|
||||||
|
Vector2 pos = sample_baked(p_offset, p_cubic);
|
||||||
|
|
||||||
|
real_t ahead = p_offset + p_lookahead;
|
||||||
|
|
||||||
|
if (p_loop && ahead >= path_length) {
|
||||||
|
// If our lookahead will loop, we need to check if the path is closed.
|
||||||
|
int point_count = get_point_count();
|
||||||
|
if (point_count > 0) {
|
||||||
|
Vector2 start_point = get_point_position(0);
|
||||||
|
Vector2 end_point = get_point_position(point_count - 1);
|
||||||
|
if (start_point == end_point) {
|
||||||
|
// Since the path is closed we want to 'smooth off'
|
||||||
|
// the corner at the start/end.
|
||||||
|
// So we wrap the lookahead back round.
|
||||||
|
ahead = Math::fmod(ahead, path_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 ahead_pos = sample_baked(ahead, p_cubic);
|
||||||
|
|
||||||
|
Vector2 tangent_to_curve;
|
||||||
|
if (ahead_pos == pos) {
|
||||||
|
// This will happen at the end of non-looping or non-closed paths.
|
||||||
|
// We'll try a look behind instead, in order to get a meaningful angle.
|
||||||
|
tangent_to_curve =
|
||||||
|
(pos - sample_baked(p_offset - p_lookahead, p_cubic)).normalized();
|
||||||
|
} else {
|
||||||
|
tangent_to_curve = (ahead_pos - pos).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 normal_of_curve = -tangent_to_curve.orthogonal();
|
||||||
|
|
||||||
|
return Transform2D(normal_of_curve, tangent_to_curve, pos);
|
||||||
|
}
|
||||||
|
|
||||||
PackedVector2Array Curve2D::get_baked_points() const {
|
PackedVector2Array Curve2D::get_baked_points() const {
|
||||||
if (baked_cache_dirty) {
|
if (baked_cache_dirty) {
|
||||||
_bake();
|
_bake();
|
||||||
|
@ -1184,6 +1224,7 @@ void Curve2D::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
|
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
|
||||||
ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve2D::sample_baked, DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve2D::sample_baked, DEFVAL(false));
|
||||||
|
ClassDB::bind_method(D_METHOD("sample_baked_with_rotation", "offset", "cubic", "loop", "lookahead"), &Curve2D::sample_baked_with_rotation, DEFVAL(false), DEFVAL(true), DEFVAL(4.0));
|
||||||
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
|
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
|
||||||
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve2D::get_closest_point);
|
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve2D::get_closest_point);
|
||||||
ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve2D::get_closest_offset);
|
ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve2D::get_closest_offset);
|
||||||
|
|
|
@ -216,6 +216,7 @@ public:
|
||||||
|
|
||||||
real_t get_baked_length() const;
|
real_t get_baked_length() const;
|
||||||
Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const;
|
Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const;
|
||||||
|
Transform2D sample_baked_with_rotation(real_t p_offset, bool p_cubic = false, bool p_loop = true, real_t p_lookahead = 4.0) const;
|
||||||
PackedVector2Array get_baked_points() const; //useful for going through
|
PackedVector2Array get_baked_points() const; //useful for going through
|
||||||
Vector2 get_closest_point(const Vector2 &p_to_point) const;
|
Vector2 get_closest_point(const Vector2 &p_to_point) const;
|
||||||
real_t get_closest_offset(const Vector2 &p_to_point) const;
|
real_t get_closest_offset(const Vector2 &p_to_point) const;
|
||||||
|
|
Loading…
Reference in New Issue