Interpolation

L'interpolation est une opération très basique en programmation graphique. Il est bon de s'y familiariser afin d'élargir ses horizons en tant que développeur graphique.

L'idée de base est que vous voulez passer de A à B. Une valeur t, représente les états intermédiaires.

Par exemple, si t est 0, alors l'état est A. Si t est 1, alors l'état est B. Tout ce qui se trouve entre les deux est une interpolation.

Entre deux nombres réels (en virgule flottante), une simple interpolation est généralement décrite comme :

interpolation = A * (1 - t) + B * t

Et souvent simplifié à :

interpolation = A + (B - A) * t

Le nom de ce type d'interpolation, qui transforme une valeur en une autre à vitesse constante est "linéaire ". Ainsi, lorsque vous entendez parler d'interpolation linéaire, vous savez qu'il s'agit de cette formule simple.

Il existe d'autres types d'interpolations, qui ne seront pas traités ici. Il est recommandé de lire ensuite la page Bezier.

Interpolation vectorielle

Les types de vecteurs (Vector2 et Vector3) peuvent aussi être interpolés, ils ont des fonctions pratiques pour le faire Vector2.linear_interpolate() et Vector3.linear_interpolate().

For cubic interpolation, there are also Vector2.cubic_interpolate() and Vector3.cubic_interpolate(), which do a Bezier style interpolation.

Voici un simple pseudo-code pour passer du point A au point B par interpolation :

var t = 0.0

func _physics_process(delta):
    t += delta * 0.4

    $Sprite.position = $A.position.linear_interpolate($B.position, t)
private float _t = 0.0f;

public override void _PhysicsProcess(float delta)
{
    _t += delta * 0.4f;

    Position2D a = GetNode<Position2D>("A");
    Position2D b = GetNode<Position2D>("B");
    Sprite sprite = GetNode<Sprite>("Sprite");

    sprite.Position = a.Position.LinearInterpolate(b.Position, _t);
}

Il produira le mouvement suivant :

../../_images/interpolation_vector.gif

Interpolation par transformation

Il est également possible d'interpoler des transformations entières (s'assurer qu'elles ont soit une échelle uniforme, soit, au moins, la même échelle non uniforme). Pour cela, la fonction Transform.interpolate_with() peut être utilisée.

Voici un exemple de transformation d'un singe de Position1 à Position2 :

../../_images/interpolation_positions.png

En utilisant le pseudo-code suivant :

var t = 0.0

func _physics_process(delta):
    t += delta

    $Monkey.transform = $Position1.transform.interpolate_with($Position2.transform, t)
private float _t = 0.0f;

public override void _PhysicsProcess(float delta)
{
    _t += delta;

    Position3D p1 = GetNode<Position3D>("Position1");
    Position3D p2 = GetNode<Position3D>("Position2");
    CSGMesh monkey = GetNode<CSGMesh>("Monkey");

    monkey.Transform = p1.Transform.InterpolateWith(p2.Transform, _t);
}

Et encore une fois, il produira le mouvement suivant :

../../_images/interpolation_monkey.gif

Mouvement lisser

L'interpolation peut être utilisée pour faciliter les mouvements, la rotation, etc. Voici un exemple d'un cercle suivant la souris avec un mouvement lissé :

const FOLLOW_SPEED = 4.0

func _physics_process(delta):
    var mouse_pos = get_local_mouse_position()

    $Sprite.position = $Sprite.position.linear_interpolate(mouse_pos, delta * FOLLOW_SPEED)
private const float FollowSpeed = 4.0f;

public override void _PhysicsProcess(float delta)
{
    Vector2 mousePos = GetLocalMousePosition();

    Sprite sprite = GetNode<Sprite>("Sprite");

    sprite.Position = sprite.Position.LinearInterpolate(mousePos, delta * FollowSpeed);
}

Voici à quoi cela ressemble :

../../_images/interpolation_follow.gif

Ceci est utile pour adoucir les mouvements de la caméra, les alliés qui vous suivent (en s'assurant qu'ils restent à une certaine distance), et bien d'autres modèles de jeu courants.