Merge pull request #76252 from lawnjelly/fti_2d
[3.x] 2D Fixed Timestep Interpolation
This commit is contained in:
@ -30,6 +30,51 @@
|
||||
|
||||
#include "transform_interpolator.h"
|
||||
|
||||
#include "core/math/transform_2d.h"
|
||||
|
||||
void TransformInterpolator::interpolate_transform_2d(const Transform2D &p_prev, const Transform2D &p_curr, Transform2D &r_result, real_t p_fraction) {
|
||||
// Extract parameters.
|
||||
Vector2 p1 = p_prev.get_origin();
|
||||
Vector2 p2 = p_curr.get_origin();
|
||||
|
||||
// Special case for physics interpolation, if flipping, don't interpolate basis.
|
||||
// If the determinant polarity changes, the handedness of the coordinate system changes.
|
||||
if (_sign(p_prev.determinant()) != _sign(p_curr.determinant())) {
|
||||
r_result.elements[0] = p_curr.elements[0];
|
||||
r_result.elements[1] = p_curr.elements[1];
|
||||
r_result.set_origin(Vector2::linear_interpolate(p1, p2, p_fraction));
|
||||
return;
|
||||
}
|
||||
|
||||
real_t r1 = p_prev.get_rotation();
|
||||
real_t r2 = p_curr.get_rotation();
|
||||
|
||||
Size2 s1 = p_prev.get_scale();
|
||||
Size2 s2 = p_curr.get_scale();
|
||||
|
||||
// Slerp rotation.
|
||||
Vector2 v1(Math::cos(r1), Math::sin(r1));
|
||||
Vector2 v2(Math::cos(r2), Math::sin(r2));
|
||||
|
||||
real_t dot = v1.dot(v2);
|
||||
|
||||
dot = CLAMP(dot, -1, 1);
|
||||
|
||||
Vector2 v;
|
||||
|
||||
if (dot > 0.9995f) {
|
||||
v = Vector2::linear_interpolate(v1, v2, p_fraction).normalized(); // Linearly interpolate to avoid numerical precision issues.
|
||||
} else {
|
||||
real_t angle = p_fraction * Math::acos(dot);
|
||||
Vector2 v3 = (v2 - v1 * dot).normalized();
|
||||
v = v1 * Math::cos(angle) + v3 * Math::sin(angle);
|
||||
}
|
||||
|
||||
// Construct matrix.
|
||||
r_result = Transform2D(Math::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_fraction));
|
||||
r_result.scale_basis(Vector2::linear_interpolate(s1, s2, p_fraction));
|
||||
}
|
||||
|
||||
void TransformInterpolator::interpolate_transform(const Transform &p_prev, const Transform &p_curr, Transform &r_result, real_t p_fraction) {
|
||||
r_result.origin = p_prev.origin + ((p_curr.origin - p_prev.origin) * p_fraction);
|
||||
interpolate_basis(p_prev.basis, p_curr.basis, r_result.basis, p_fraction);
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
// several frames may occur between each physics tick, which will make it cheaper
|
||||
// than performing every frame.
|
||||
|
||||
class Transform;
|
||||
struct Transform2D;
|
||||
|
||||
class TransformInterpolator {
|
||||
public:
|
||||
@ -66,6 +66,7 @@ private:
|
||||
static Quat _basis_to_quat_unchecked(const Basis &p_basis);
|
||||
static bool _basis_is_orthogonal(const Basis &p_basis, real_t p_epsilon = 0.01f);
|
||||
static bool _basis_is_orthogonal_any_scale(const Basis &p_basis);
|
||||
static bool _sign(real_t p_val) { return p_val >= 0; }
|
||||
|
||||
static void interpolate_basis_linear(const Basis &p_prev, const Basis &p_curr, Basis &r_result, real_t p_fraction);
|
||||
static void interpolate_basis_scaled_slerp(Basis p_prev, Basis p_curr, Basis &r_result, real_t p_fraction);
|
||||
@ -75,6 +76,7 @@ public:
|
||||
// These will be slower.
|
||||
static void interpolate_transform(const Transform &p_prev, const Transform &p_curr, Transform &r_result, real_t p_fraction);
|
||||
static void interpolate_basis(const Basis &p_prev, const Basis &p_curr, Basis &r_result, real_t p_fraction);
|
||||
static void interpolate_transform_2d(const Transform2D &p_prev, const Transform2D &p_curr, Transform2D &r_result, real_t p_fraction);
|
||||
|
||||
// Optimized function when you know ahead of time the method
|
||||
static void interpolate_transform_via_method(const Transform &p_prev, const Transform &p_curr, Transform &r_result, real_t p_fraction, Method p_method);
|
||||
|
||||
@ -67,6 +67,7 @@ public:
|
||||
virtual void input_text(const String &p_text);
|
||||
|
||||
virtual void init();
|
||||
virtual void iteration_prepare() {}
|
||||
virtual bool iteration(float p_time);
|
||||
virtual void iteration_end() {}
|
||||
virtual bool idle(float p_time);
|
||||
|
||||
Reference in New Issue
Block a user