summaryrefslogtreecommitdiff
path: root/2d/rigidbody/rigidbody_2/snippet3.cpp
blob: 7b7130c5ceff4dcbe409746b5046a8babc33043f (plain)
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
78
79
80
81
82
83
84
85
86
87
88

struct Impulse {
    Vector2 force = { 0, 0 };
    Vector2 pointOfApplication = { 0, 0 };
    float32 timeOfApplicationSeconds = 0.25f;
    float32 timeAppliedSeconds = 0.f;
    bool isDead = false;
};

const int32 NUM_IMPULSES = 4;

struct Rigidbody {
    int32 numImpulses = 0;
    Impulse activeImpulses[NUM_IMPULSES];
    Vector2 velocity = { 0, 0 };
    Vector2 position = { 0, 0 };
    float32 mass = 1.f;

	float32 rotationalVelocity = 0.f;
	float32 rotation = 0.f;
	float32 momentOfInertia = 1.f;

    void reset() {
        numImpulses = 0;
        velocity = { 0, 0 };
        rotationalVelocity = 0.f;
        rotation = 0.f;
    }

    void applyImpulse(Impulse i) {
        if (numImpulses > NUM_IMPULSES) {
            printf("Unable to apply impulse. Buffer full.\n");
            return;
        }

        activeImpulses[numImpulses] = i;
        numImpulses++;
    }

    void applyGravity(float32 deltaTimeSeconds) {
        velocity += (Vector2 { 0.f, -9.8f } * deltaTimeSeconds);
    }

    void update(float32 deltaTimeSeconds) {
        applyGravity(deltaTimeSeconds);

        Vector2 force;
        float32 torque = 0.f;
        for (int32 idx = 0; idx < numImpulses; idx++) {
            Impulse& i = activeImpulses[idx];

            float32 nextTimeAppliedSeconds = i.timeAppliedSeconds + deltaTimeSeconds;
            if (nextTimeAppliedSeconds >= i.timeOfApplicationSeconds) {
                nextTimeAppliedSeconds = i.timeOfApplicationSeconds;
                i.isDead = true;
            }
            
            float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
            Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
            force += forceToApply * impulseDtSeconds;

            // New! Increment the torque for each force
            torque += i.pointOfApplication.getPerp().dot(forceToApply);

            i.timeAppliedSeconds = nextTimeAppliedSeconds;
        }
        
        Vector2 acceleration = force / mass;
        velocity += (acceleration * deltaTimeSeconds);
        position += (velocity * deltaTimeSeconds);

        // New! Update the rotational velocity as well
        float32 rotationalAcceleration = torque / momentOfInertia;
        rotationalVelocity += (rotationalAcceleration * deltaTimeSeconds);
        rotation += (rotationalVelocity * deltaTimeSeconds);

        for (int32 idx = 0; idx < numImpulses; idx++) {
            if (activeImpulses[idx].isDead) {
                for (int j = idx + 1; j < numImpulses; j++) {
                    activeImpulses[j - 1] = activeImpulses[j];
                }

                idx = idx - 1;
                numImpulses--;
            }
        }
    }
};