summaryrefslogtreecommitdiff
path: root/frontend/rigidbody.html
blob: 2cc32b750561a8ea0d386c8addfa1a39f2c3da0f (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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <script src="scripts/jquery-3.5.1.min.js"></script>
        <script src="index.js"></script>
        <link rel="stylesheet" href="/../index.css">
        <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,300" rel="stylesheet" type="text/css">
        <title>Simple Website</title>

        <script src="_rigidbody/vec2.js"></script>
        <script src="_rigidbody/mat4.js"></script>
        <script src="_rigidbody/shader.js"></script>
        <script src="_rigidbody/circle.js"></script>
        <script src="_rigidbody/program_common.js"></script>
        <script src="_rigidbody/rigidbody_1.js"></script>
        <script src="_rigidbody/rigidbody_2.js"></script>
    </head>
    <body>
        <header>
            <h1>Matt Kae's Programming Blog</h1>
        </header>
        <nav>
            <a href="/">Home</a>
            <a href="rigidbody.html">Rigid Body</a>
            <a href="references.html">Books n' References</a>
        </nav>
        <main>
            <section>
                <p>
                    <ul>
                        <li><a href="#introduction">Introduction</a></li>
                        <li><a href="#linear-forces">Part 1: Linear Forces</a></li>
                        <li><a href="#rotational-forces">Part 2: Rotational Forces</a></li>
                    </ul>
                </p>
            </section>
            <section id='introduction'>
                <h2>Introduction: Rigid Body Physics</h2>
                <p>
                    You're most likely here because you have some interest in the world of rigid body physics. Maybe you have some knowledge of rendering via OpenGL or Vulkan, 
                    and you want to begin watching your up-until-now static scene come to life. Well, you're in the right place! In the course of this tutorial series I will walk
                    you through the entirety of a 2D rigid body physics system entirely in the web. All of this information will be extendable to other languages, but we will use
                    JavaScript and WebGL in these blog posts. Additionally, much of the information presented here can be extended to 3 dimensions, but 3D carries some complications
                    with it, that we will discuss in future blog posts.
                </p>
                <p>
                    In implementing a rigidy body physics system, we're primarily interested in two sub-fields of physics, namely <b>dynamics</b> and <b>kinematics</b>. Although I'm
                    far as can be from being an expert in either of these fields, I will explain - from a programmer's persepctive - what they mean to me:
                    <ul>
                        <li>
                            <b>Kinematics</b> is the study of how an object's movement changes over time. These are the classic position, velocity, and acceleration equations
                            that you're most likely familiar with from high school or college physics.
                        </li>
                        <li>
                            <b>Dynamics</b> is the study of whats <i>causes</i> kinematic movement. These are the classic force and momentum equations that you may already be familiar
                            with as well.
                        </li>
                    </ul>
                </p>
                <p>
                    Finally, I must provide a disclaimer that all of rigid body systems are very math-y. You will need to know a decent amount of vector calculus and linear algebra to really understand
                    what's going on here. I am going to assume that you have this knowledge. If you don't already have this knowledge, I will try and provide some resources on the Books
                    n' References page of the website.
                </p>
            </section>
            <hr />
            <section id="linear-forces">
                <h2>Part 1: Linear Forces</h2>
                <p>
                    The first - and perhaps easiest - part of implementing any rigid body physics system is getting the entities in your scene to move in response to linear forces.
                    With this implementation alone, you can achieve an interesting level of realism in your 2D (and even 3D) scene.
                </p>
                <p>
                    Let's begin by recalling the relationships between acceleration, velocity, and position.
                </p>
                <p>
                    Knowing all this, you should be able to understand the following source code fairly easily;
                    <pre>
                        <code>
<span class="code_keyword">function</span> update(dtSeconds) {
    <span class="code_comment">// Add up the forces acting on the circle</span>
    <span class="code_keyword">const</span> GRAVITY = 9.8;
    <span class="code_keyword">const</span> lGravityForce = vec2(0, -1.0 * (lCircle.mass * <span class="code_constant">GRAVITY</span>));
    lCircle.force = addVec2(lCircle.force, lGravityForce);

    <span class="code_comment">// Figure out acceleration (a = F / m)</span>
    <span class="code_keyword">const</span> lCurrentAcceleration = scaleVec2(lCircle.force, 1.0 / lCircle.mass);

    <span class="code_comment">// Calculate the new velocity: v = v0 + a * t</span>
    lCircle.velocity = addVec2(lCircle.velocity, scaleVec2(lCurrentAcceleration, dtSeconds));

    <span class="code_comment">// Update the position based on velocity: x = x0 + v * t</span>
    lCircle.position = addVec2(lCircle.position, scaleVec2(lCircle.velocity, dtSeconds));

    <span class="code_comment">// Update the model matrix accordingly</span>
    lCircle.model = translateMatrix(mat4(), lCircle.position.x, lCircle.position.y, 0);

    <span class="code_comment">// Reset the force vector for the next update</span>
    lCircle.force = vec2()
}
                        </code>
                    </pre>
                </p>
                <div id="rigidbody_1" class="opengl_canvas_container">
                    <canvas width="640" height="480"></canvas>
                    <div class="opengl_canvas_sidebar">
                        <ul class="opengl_value_tracker">
                            <li><b>Force:</b><span id="rigidbody_1_force_field">N/A</span></li>
                            <li><b>Acceleration:</b><span id="rigidbody_1_acceleration_field">N/A</span></li>
                            <li><b>Velocity:</b><span id="rigidbody_1_velocity_field">N/A</span></li>
                            <li><b>Position:</b><span id="rigidbody_1_position_field">N/A</span></li>
                        </ul>
                        <form id="rigidbody_1_force_submit_button" style="text-align: right; padding: 0.5rem;">
                            <div class="vec2_input_group">
                                <label>Force Vector</label>
                                <input class="vec2_x_input" type="number" placeholder="X (Default 0)"/>
                                <input class="vec2_y_input" type="number" placeholder="Y (Default 5000 N)"/>
                            </div>
                            <input type="submit" value="Apply Force"></input>
                        </form>
                    </div>
                    <button class="play_button">
                        Play
                    </button>
                    <button class="stop_button">
                        Stop
                    </button>
                </div>
            </section>
            <hr />
            <section id="rotational-forces">
                <h2>Part 2: Rotational Forces</h2>
                <p>
                </p>
                <div id="rigidbody_2" class="opengl_canvas_container">
                    <canvas width="640" height="480"></canvas>
                    <div class="opengl_canvas_sidebar">
                        <ul class="opengl_value_tracker">
                            <li><b>Force:</b><span id="rigidbody_1_force_field">N/A</span></li>
                            <li><b>Acceleration:</b><span id="rigidbody_2_acceleration_field">N/A</span></li>
                            <li><b>Velocity:</b><span id="rigidbody_2_velocity_field">N/A</span></li>
                            <li><b>Position:</b><span id="rigidbody_2_position_field">N/A</span></li>
                        </ul>
                        <form id="rigidbody_2_force_submit_button" style="text-align: right; padding: 0.5rem;">
                            <div id="rigidbody_2_force_input" class="vec2_input_group">
                                <label>Force Vector</label>
                                <input class="vec2_x_input" type="number" placeholder="X (Default 0)"/>
                                <input class="vec2_y_input" type="number" placeholder="Y (Default 5000 N)"/>
                            </div>
                            <div id="rigidbody_2_position_input" class="vec2_input_group">
                                <label>Point of Application (Unit Vector)</label>
                                <input class="vec2_x_input" type="number" placeholder="X (Default 2 Root 2)"/>
                                <input class="vec2_y_input" type="number" placeholder="Y (Default 2 Root 2)"/>
                            </div>
                            <input type="submit" value="Apply Force"></input>
                        </form>
                    </div>
                    <button class="play_button">
                        Play
                    </button>
                    <button class="stop_button">
                        Stop
                    </button>
                </div>
            </section>

            <section style="height: 50vh;"></section>
        </main>
    </body>
</html>