Handmade Hero»Forums»Game
15 posts
Analytic integration in the PID camera
Edited by Terans on

In the code of the PID camera on Day 504 (https://guide.handmadehero.org/code/day504/#10452 ), it seems that Casey is doing an analytic integration of the acceleration to compute the camera position. But I have always been told that analytic integration of the equations of movement only works in simple cases, when the acceleration is constant, and otherwise we have to use the Euler method or something.

In the camera code, the acceleration is computed with a spring-like equation, but Casey computes the position (DeltaP) by integrating this acceleration twice, like if it was a constant. Here is the code in question:

    v3 ddP = A*TotalDeltaP + B*TotalDeltadP;
    v3 dP = dt*ddP + Camera->dP;
    
    v3 DeltaP = 0.5f*dt*dt*ddP + dt*Camera->dP;
    if((LengthSq(DeltaP) < LengthSq(TotalDeltaP)) ||
       (LengthSq(Hadamard(dPTarget - dP, Camera->MovementMask)) < Square(0.001f)))
    {
        P += DeltaP;
    }

If this is correct, why would we ever want to use approximate numerical methods like

dP += ddP * dt;
P += dP * dt;

if we can always compute the position with the full equation?

Simon Anciaux
1184 posts
Analytic integration in the PID camera

Casey is trying/experimenting with things he doesn't know, so don't treat his solution as a perfect solution or the way to go. If it's working well enough than that's fine, but you should verify that it would work for your specific case.

I'm not good at math (particularly with derivative, integration ...) but using

dP += ddP * dt;
P += dP * dt;

Is a very simple model than anybody can easily understand and implement. The issue with it is that at different value of dt (60hz, 30hz...) you will get a slightly different trajectory.

P = 0, dP=0, ddP=50, dt=1
0 += 50 * 1 => dP=50
0 += 50 * 1 => P=50
50 += 50 * 1 => dP=100
50 += 100 * 1 => P=150

After 2dt we are at 150

P = 0, dP=0, ddP=50, dt=0.5
0 += 50 * 0.5 => dP=25
0 += 25 * 0.5 => P=12.5
25 += 50 * 0.5 => dP=50
12.5 += 50 * 0.5 => P=27.5
50 += 50 * 0.5 => dP=75
27.5 += 75 * 0.5 => P=65
75 += 50*0.5 => dP=100
65 += 100*0.5 => dP=115

After 2dt we are at 115

If that doesn't matter (in some camera movement for example) than you can use that simple thing, but in case where it matters (player movement for example) you'd better find a better solution.