<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Title_Long.gif"/>
</p>
# Dyna-Kinematics
A 2D rigid-body dynamics simulator with some cool features for generating beautiful animations.
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Cool_Dino.gif"/>
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/readme_images/Simulation_Controller_Dino.PNG"/>
<p align="center">
<em>The two components that make up this project: the simulation viewer (left) and the simulation controller (right).</em>
</p>
</p>
**Note**: View this readme [here](https://github.com/diegomacario/Dyna-Kinematics/blob/master/README.md) instead of in the main page of this repository. On some systems Github resizes the GIFs in the main page, which makes them look blurry.
## Motivation
When I was in university I took a class on numerical methods. In that class I was taught many different algorithms for fitting curves, interpolating polynomials and splines, and numerically integrating and differentiating.
The funny thing is that I was taught how to do all those things by hand. I was never asked to implement any of those algorithms in a computer, which felt wrong because they are clearly designed to be executed by a computer.
Since then I have wanted to rectify that wrong by taking what I learned to do by hand and using it to build something cool. The result of that desire is this project, which illustrates the basics of:
- Numerical integration.
- 2D rigid-body dynamics.
- 2D collision detection and response.
## Technical details
In its current form, this project consists of a simulation controller and a simulation viewer.
The simulation controller allows users to:
- Select a scene from a set of hardcoded scenes.
- Play, pause, reset and record simulations as GIFs.
- Change certain simulation and display settings.
The simulation viewer displays simulations in real-time and it can be resized in any way the user wants while maintaining the aspect ratio of the current scene.
The libraries used by this project and their purposes are the following:
- [Qt](https://www.qt.io/) is used for the UI of the simulation controller.
- [GLFW](https://www.glfw.org/) is used for the window of the simulation viewer.
- [GLAD](https://glad.dav1d.de/) is used to load pointers to OpenGL functions.
- [GLM](https://glm.g-truc.net/0.9.9/index.html) is used to perform 3D math.
- [stb_image_write](https://github.com/nothings/stb) is used to save frames as PNGs.
- [FFmpeg](https://ffmpeg.org/) is used to generate GIFs.
For instructions on how to build this project on **Windows**, **macOS** or **Linux**, see [this](https://github.com/diegomacario/Dyna-Kinematics/blob/master/BUILD_INSTRUCTIONS.md) document.
For information on the techniques used by this project to detect and resolve collisions, see the "Physics" section at the end of this document.
## Evolution
Below you will find a description of how this simulator evolved over time, each step illustrated with GIFs recorded in the simulator itself.
Note that in many examples I present the same GIF twice. The first time with the "Remember Frames" feature disabled, and the second time with the same feature enabled. Being able to visualize trajectories is my favorite thing about this project. The results can be very beautiful.
### 1) Body-wall collisions
The first step in the development process was to implement support for collisions between bodies and walls. This type of collision is a lot simpler than collisions between bodies because walls are not affected in any way by the impact. In the code, a wall is treated as a body with an infinite mass, which simplifies the collision response equations significantly.
In the simulation below, notice how the velocity and angular velocity of the body change depending on the way it hits the walls. That's the magic of rigid-body dynamics. The point of contact and linear and angular effects are taken into consideration to produce results that look natural.
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Single_No_Rem_Long.gif"/>
<p align="center">
<em>A single body floating in the vacuum of space.</em>
</p>
</p>
Below is the same simulation but with the "Remember Frames" feature enabled:
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Single_Rem.gif"/>
<p align="center">
<em>This simulation reminds me of Saul Bass' beautiful <a href="http://annyas.com/saul-bass-vertigo-movie-poster-design/">poster</a> for Vertigo.</em>
</p>
</p>
### 2) Body-body collisions
The second step in the development process was to implement support for collisions between bodies. This type of collision can occur in two different ways: between two vertices or between a vertex and an edge.
An important part of resolving a collision is knowing what your collision normal is. In a vertex-edge collision, the collision normal is simply the normal of the edge. But what about vertex-vertex collisions? Vertices are simply points, so they don't have normals. There are many ways to calculate an appropriate normal for this type of collision. In my case, I chose a really simple one: the collision normal is the line that connects the centers of mass of the two colliding bodies. This is a deviation from reality, but it produces good looking results:
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Pair_No_Rem.gif"/>
<p align="center">
<em>Two bodies of equal mass floating in the vacuum of space.</em>
</p>
</p>
### 3) Momentum and torque
The simulations so far probably look a bit cartoony to you. Are we really simulating physics here? Or are we just reflecting velocity vectors when bodies collide to get good looking results?
A cool way to confirm that we are simulating real physics is to visualize momentum and torque in action. This is possible because the collision response equations take a body's mass, center of mass and moment of inertia into consideration.
In the simulation below you can see momentum in action:
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Momentum_No_Rem_Short.gif"/>
<p align="center">
<em>A 100 kilogram body (orange) colliding with a 10 kilogram body (yellow).</em>
</p>
</p>
Since the mass of the orange body is much greater than the mass of the yellow body, its momentum is much greater too. Because of this, the orange body is barely affected by the collision while the yellow one reverses its direction.
Below is the same simulation but with the "Remember Frames" feature enabled:
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Momentum_Rem_Short.gif"/>
<p align="center">
<em>A stoppable force meets a movable object.</em>
</p>
</p>
As for torque, you can see it in action in the simulation below:
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Torque_No_Rem_Short.gif"/>
<p align="center">
<em>A body (pink) getting hit by another body (turquoise) as far away from its center of mass as possible.</em>
</p>
</p>
The center of mass of the pink body is halfway between its ends. The point of contact between the two bodies is at its upper end, or in other words, as far way from its center of mass as possible, which means that the torque that is applied to it by the collision is the maximum possible. That torque translates into the maximum possible angular velocity, which causes it to rotate quickly around its center of mass.
Below is the same simulation but with the "Remember Frames" feature enabled:
<p align="center">
<img src="https://github.com/diegomacario/2D-Rigid-Body-Simulator/blob/master/GIFs/Torque_Rem_Short.gif"/>
<p align=
评论0