4coder » Forums » Casey's 4Coder Smooth Scroll
braksten
4 posts
This newly registered member has not yet activated their account.
#17089 Casey's 4Coder Smooth Scroll
2 months, 2 weeks ago Edited by braksten on Dec. 29, 2018, 11:13 p.m.

Hi Guys, I just made the switch to 4Coder from Sublime Text. I'm using Casey's 4Coder config as a base for mine, but I'm a bit lost with this set of functions that he uses for smooth scroll:

I sorta get the idea, it seems (because of the function name) like he is using a cubic function in order to non-uniformly steepen then flatten the velocity of the scroll, but I'm pretty confused as to what's actually happening.

seems to me like dt is meant to be the time step. duration is meant to be the length of the scroll? so i assume at the start every scroll has 0.1f (i guess seconds of duration)? then the cubic transform happens, followed by clamping to 0 if it hit that. i'm not sure if that's right but that's what i understand so far.

however, i am very confused with how the CubicUpdateFixedDuration1 works, and would love if I could get some insight into it, since I don't want to put it in my config without understanding. I am not super mathy, but it seems to me like he is doing some sort of derivative stuff with dC0 and dC1, etc; I don't really know what C0 - C3 and B0 - B3 are coming from at all.

thanks!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
bool
CubicUpdateFixedDuration1(float *P0, float *V0, float P1, float V1, float Duration, float dt)
{
    bool Result = false;
    
    if(dt > 0)
    {
        if(Duration < dt)
        {
            *P0 = P1 + (dt - Duration)*V1;
            *V0 = V1;
            Result = true;
        }
        else
        {
            float t = (dt / Duration);
            float u = (1.0f - t);
            
            float C0 = 1*u*u*u;
            float C1 = 3*u*u*t;
            float C2 = 3*u*t*t;
            float C3 = 1*t*t*t;
            
            float dC0 = -3*u*u;
            float dC1 = -6*u*t + 3*u*u;
            float dC2 =  6*u*t - 3*t*t;
            float dC3 =  3*t*t;
            
            float B0 = *P0;
            float B1 = *P0 + (Duration / 3.0f) * *V0;
            float B2 = P1 - (Duration / 3.0f) * V1;
            float B3 = P1;
            
            *P0 = C0*B0 + C1*B1 + C2*B2 + C3*B3;
            *V0 = (dC0*B0 + dC1*B1 + dC2*B2 + dC3*B3) * (1.0f / Duration);
        }
    }
    
    return(Result);
}

struct Casey_Scroll_Velocity
{
    float x, y, t;
};

Casey_Scroll_Velocity casey_scroll_velocity_[16] = {0};
Casey_Scroll_Velocity *casey_scroll_velocity = casey_scroll_velocity_ - 1;

SCROLL_RULE_SIG(casey_smooth_scroll_rule){
    Casey_Scroll_Velocity *velocity = casey_scroll_velocity + view_id;
    int result = 0;
    if(is_new_target)
    {
        if((*scroll_x != target_x) ||
           (*scroll_y != target_y))
        {
            velocity->t = 0.1f;
        }
    }
    
    if(velocity->t > 0)
    {
        result = !(CubicUpdateFixedDuration1(scroll_x, &velocity->x, target_x, 0.0f, velocity->t, dt) ||
                   CubicUpdateFixedDuration1(scroll_y, &velocity->y, target_y, 0.0f, velocity->t, dt));
    }
    
    velocity->t -= dt;
    if(velocity->t < 0)
    {
        velocity->t = 0;
        *scroll_x = target_x;
        *scroll_y = target_y;
    }
    
    return(result);
}


EDIT: this seems, after some research, like a bezier curve equation. i think i mostly understand it, but it seems like since the end velocity is always set to 0, it would just output straight lines, so i find it odd Casey didn't just use a linear blend between start / end points + while i totally get how C0...C3 and dC0...dC3 were calculated, i don't get how B1 and B2 were done; particularly the Duration / 3.0f.