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!