diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-09-25 22:09:07 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-09-25 22:09:07 -0400 |
| commit | b49b7d276558404f71be3bd9f366ed73d9b5e46c (patch) | |
| tree | 50cb5f52f46330a8986fa6f7f7b0367c14c24684 | |
| parent | e421e04d5f2481eb6b3cfffa4055b6f70e35332d (diff) | |
| download | balls-b49b7d276558404f71be3bd9f366ed73d9b5e46c.zip | |
design doc
| -rw-r--r-- | design.txt | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/design.txt b/design.txt new file mode 100644 index 0000000..9d1495a --- /dev/null +++ b/design.txt @@ -0,0 +1,84 @@ += Multithreaded 2D Bouncing Balls Simulation = + +The goal is to simulate and render multiple balls bouncing in a rectangular +container (the window). The number of balls is confurable by a command line +argument at runtime. + +# Collisions + +When a collision occurs, there are two steps: 1) detect the collision, and 2) +respond to the collision. + +1) Collision detection + +Collision between two balls is detected by comparing the distance between +them to the sum of their radii. Calculating the distance involves a square +root operation, but the compution can be simplified by comparing the square +of both sides of the equation. I.e. rather than checking + +sqrt((x2-x1)^2 + (y2-y1)^2) < (r1+r2) + +the formula is simplified using the identity + +(a < b) <=> (a^2 < b^2) + +to avoid the square root: + +(x2-x1)^2 + (y2-y1) < (r1+r2)^2 + + +2) Collision response + +Once a collision is detected, the reaction of the ball should be calculated. +Each ball has a position, a velocity, a radius and a mass. The first step is +to correct the position so that the two balls don't overlap. This is done +by first finding the vector from ball 2 to ball 1, and then normalizing it. +Then multiply the normal vector by the sum of the radii of the two balls---this +will be the final distance between the two. Calculate the final position +of ball 1 as the endpoint of the aforementioned vector beginning at ball +2's position. + +Once the corrected position of the ball is known, then next step is to +calculate its velocity after the collision. Collisions are assumed to +be perfectly elastic: kinetic energy is conserved. The final velocity is +calculated by a sequence of vector operations outlined at the following link: + +https://en.wikipedia.org/wiki/Elastic_collision#Two-dimensional_collision_with_two_moving_objects + +The "angle-free representation" is used. + +# Implementation + +The simulation is implemented using the Plan 9 thread and graphics libraries: + +https://man.cat-v.org/plan_9/2/thread +https://man.cat-v.org/plan_9/2/graphics + +Each ball is simulated in its own computation thread. With each frame, +the thread updates the ball's velocity and position, checks for collisions +with other balls and the edges of the screen, and redraws the ball on the +screen. Threads communicate the positions, velocities, etc. of their ball +via "Channels" provided by the thread library. "A Channel is a buffered or +unbuffered queue for fixed-size messages." In this case, buffered channels +are used to send Ball data structures between threads. Before calculating +collisions, each ball thread broadcasts its Ball to other threads. Then, for +each ball, it receives a Ball from the channel it shares with another thread +and checks for a collision between its own ball and the ball it just received. + +Not only does this provide race-free communication, it also enforces a +"soft synchronization." If one thread runs faster than the others, it will +be forced to synchronize with the others when either its outgoing channel +fills up or its incoming channel runs dry. + +There is also a frame-timing mechanism that keeps the whole simulation +running at a steady pace. This is implemented as a "frametick" thread that +broadcasts "tick" messages to all computation threads at a fixed interval +(approximately every 16666667 ns.) Each thread waits for this message before +redrawing its ball on the screen. + +There is a single control thread that initializes all of the necessary data +structures, starts the computation threads, and listens for system events. + +The control thread creates the specified number of balls as well as the +n*(n-1) channels used to communicate between the worker threads. It then +enters a loop waiting for window resize and keyboard input events. |