C++ linear interpolation Bezier curve non-linear animation

        Nonlinear animation is widely used in programs, games and animations, so how should we implement it?

The points on the nonlinear animation are nonlinear on the st image, that is, not a linear function, but a continuous curve everywhere

        For this curve can be simulated, here we use the Bezier curve

1. Basic introduction

        At a certain time ts, AE/AB=BF/BC=EG/EF

        Imagine that there are points A, B, C in the plane, and there are moving points E, F on the line segments AB, CB respectively, and the distance between E, F and its starting point (A, B) accounts for the same proportion of the line segment within a certain period of time. On the line There is a point G on the segment EF, its mechanism is the same as that of E and F, and it is conceivable that the motion track of point G forms a curve

This is the quadratic Bezier curve

Second, linear interpolation

        Ok, you already have a basic understanding of what we do, which is to simulate the G-point trajectory to complete the curve simulation

        To complete this task, the G-point trajectory must be obtained. We need a function that describes the movement of a single chip:

lerp function

        There are two fixed points AB in the plane Cartesian coordinate system yOx, point E is the moving point moving on the line segment AB

If w=AE/AB, w∈[0, 1.0]
Easy to get vector OE=OA+AE
∵AE=wAB
∴OE=OA+wAB
That is, for the structure Point E=A+w(BA)=A-wA+wB=(1-w)A+wB
There is a function f(A, B, w)=(1-w)A+wB
This function describes the movement of moving point E on line segment AB within 1s (w is time, w∈[0, 1.0])

This function is called linear interpolation, denoted as lerp(A, B, t)

Third, find the G-point trajectory

        We have basically completed the universal function describing the motion state of a linear interpolation point, and now we use it to complete the G point motion trajectory

E=lerp(A, B, t) , F=lerp(B ,C, t)

        t is the time to describe the motion, between 0-1s, and it can also be regarded as the w (weight weight, AE/AB=BF/BC=EG/EF) for each linear interpolation point, so we guarantee Motion equality for each line segment insertion point----move at the same time at t=0, and stop at the same time at t=1

Similarly, G=lerp(E, F, t)

        So the trajectory of the G point is ready to come out:

E=lerp(A, B, t)
F=lerp(B ,C, t)
G=lerp(E, F, t)
G=lerp(lerp(A, B, t) , lerp(B ,C, t), t)
=>  G=lerp((1-t)A+tB, (1-t)B+tC, t)
=(1-t)[(1-t)A+tB]+t[(1-t)B+tC]
=(1-t)^2 A+2t(1-t)B+t^2 C

        This is the quadratic Bezier curve equation , and the same for the cubic

Let's simulate it in C++:

code show as below:

        The G-point trajectory is on line 21, the IDE is Red Panda C++, the environment is Win11, and the drawing library is EGE

Effect:

        Well, generally speaking, the effect is not bad.

        Next, with the curve equation, we can start to do some nonlinearity

Four, non-linear animation

Here we take the quadratic Bezier curve as an example

        If you want to achieve a nonlinear effect, you have to make the character's movement speed nonlinear (nonsense)

        Even if the speed of the object changes with time (acceleration changes): v/t=a≠C

        Put the Bezier curve on the vt coordinate system with A as the origin, let Ay=Cy, obviously this is a nonlinear motion picture

        The red line is the obtained G-point trajectory

        Label the red line as the function g(t)

        Then we can know from simple differential knowledge

Character motion acceleration a=v/t=lim(Δt→0) g(t+Δt)/Δt

        Since the step size is limited, and the animation does not need to be too precise, here we take Δt=step (step size, I set it at 0.001 in the program)

Then the acceleration a=(Gy-G'y)/(Gx-G'.x)

        G' here refers to the position of G in the previous step (the last unit is often in the step)

        In this way, we have completed the change of acceleration through the quadratic Bezier curve

        This means that we can use this to change the instantaneous rate at which an object moves (acceleration), so that the velocity of the object changes continuously over time as it moves

        In this way, we only need to add the acceleration of the object's motion speed to each refresh to achieve non-linearity:

        The effect is not displayed

code show as below:

Try to copy it yourself:

#include<bits/stdc++.h>
#include<ege.h>

#define get_key(k) (GetAsyncKeyState(k)&0x8000)
using namespace std;
using namespace ege;

float t = 0, step = 0.01;
ege_point A, B, C;
ege_point G = {0.0, 0.0}, nG = {100000, 1};
float v = 0.0, x = 1280, y = 240, r = 10;
float wt = 1, wv = 0.1; //wt偏移调整加速度和曲线相关性 wv速度缩放值

int main() {
    A = {0, 480}, B = {240, 0}, C = {480, 480};
    initgraph(2560, 480);
    getch();
    setcolor(YELLOW);
    while (t < 1) {        
        G = {(1 - t)*(1 - t)*A.x + 2 * t*(1 - t)*B.x + t*t * C.x, (1 - t)*(1 - t)*A.y + 2 * t*(1 - t)*B.y + t*t * C.y};
        float delta = (G.y - nG.y) / (G.x - nG.x);
        nG = G;
        t += step;
        Sleep(0);
        cleardevice();
        circle(x, y, r);
        v += (wt * delta);
        x += (v * wv);
        cout << "delta_v " << v << endl;
    }
    system("pause");
    return 0;
}

Five, conclusion

        In this tutorial, we have gone through the process from discovering problems→abstracting problems→building models→solving problems→practical applications . This is our common progress

        We also use knowledge of acceleration, functions, derivatives, equations, etc. when dealing with problems. This is an important leap in our ability to comprehensively apply and solve problems!

        Mathematics is a powerful tool. Any problem in this world can be transformed into a mathematical problem. May you and I think together and make progress together!

Guess you like

Origin blog.csdn.net/leyang0910/article/details/132020086