Compare commits
8 Commits
082acc4451
...
c++-port
Author | SHA1 | Date | |
---|---|---|---|
fad703d504 | |||
da802cff9d | |||
a64670503a | |||
d6a2727755 | |||
de4e741d6a | |||
2b844647f4 | |||
e9f90bd11c | |||
87b4febc5d |
70
README.md
Normal file
70
README.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# From Flying Balls to Colliding Polygons
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
- [Abstract](#abstract)
|
||||||
|
- [Before vs After](#before-vs-after)
|
||||||
|
- [Context](#context)
|
||||||
|
- [Before](#before)
|
||||||
|
- [After](#after)
|
||||||
|
- [Contact](#contact)
|
||||||
|
|
||||||
|
## Abstract
|
||||||
|
|
||||||
|
> (text taken from the abstract of my report that you can find
|
||||||
|
> [here](https://github.com/karma-riuk/bachelor-project-report/blob/main/bachelorproject.pdf)
|
||||||
|
|
||||||
|
Physics engines are a fun and interesting way to learn about the laws of
|
||||||
|
physics, as well as computer science. They provide a real-time simulation of
|
||||||
|
common physical phenomena, and therefore illustrate theoretical concepts such as
|
||||||
|
the equations that dictate the motion of objects.
|
||||||
|
|
||||||
|
The goal of this project was to extend an existing physics engine built for
|
||||||
|
demonstration purposes. This engine was initially designed and developed to
|
||||||
|
simulate circular objects ("balls") in 2D.
|
||||||
|
|
||||||
|
With this project, we intended to extend this engine to also simulate arbitrary
|
||||||
|
polygons, again in a physically accurate way. The main technical challenges of
|
||||||
|
the project is therefore the correct simulation of the dynamics of rigid,
|
||||||
|
polygonal objects. In particular, we developed a model of polygonal rigid
|
||||||
|
objects:
|
||||||
|
|
||||||
|
- we implemented a simulation of their inertial motion, possibly in the
|
||||||
|
presence of a constant force field such as gravity;
|
||||||
|
- we detect collisions between objects;
|
||||||
|
- we compute and then simulate the dynamic effects of collisions.
|
||||||
|
|
||||||
|
The simulations are animated and displayed in real-time. It is also therefore
|
||||||
|
crucial that the simulation code be efficient to obtain smooth animations.
|
||||||
|
|
||||||
|
## Before vs After
|
||||||
|
|
||||||
|
### Context
|
||||||
|
|
||||||
|
A little of context for the follow videos:
|
||||||
|
|
||||||
|
- in the first video, the special ball with an arrow inside is a "spaceship",
|
||||||
|
that can be controlled by the user;
|
||||||
|
- the yellow bar that appears after midway through both videos represent the
|
||||||
|
restitution coefficient of the collision resolution (the lower it is, the
|
||||||
|
greater the dampening on impact between objects);
|
||||||
|
- the white line with a ball at the end that appears after the restitution
|
||||||
|
coefficient bar represents the gravity vector that gets applied to the speed
|
||||||
|
of each object at each frame, the ball is the direction the vector is pointing
|
||||||
|
it.
|
||||||
|
|
||||||
|
### Before
|
||||||
|
|
||||||
|
[before](https://github.com/karma-riuk/flying-balls/assets/30158492/ddc0d608-9667-4a21-8132-e056e443e0e2)
|
||||||
|
|
||||||
|
### After
|
||||||
|
|
||||||
|
[after](https://github.com/karma-riuk/flying-balls/assets/30158492/bd4013b8-bc01-4d52-aa2f-44dbc25de717)
|
||||||
|
|
||||||
|
<!-- ## Controls -->
|
||||||
|
<!---->
|
||||||
|
<!-- ## Installation -->
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
If you have any question concerning this work, feel free to contact me at [arno.fauconnet@gmail.com](mailto:arno.fauconnet@gmail.com)
|
BIN
before.mp4
Normal file
BIN
before.mp4
Normal file
Binary file not shown.
4
game.h
4
game.h
@ -13,8 +13,8 @@ extern double delta; /* simulation time delta in seconds */
|
|||||||
extern int width; /* game canvas width */
|
extern int width; /* game canvas width */
|
||||||
extern int height; /* game canvas height */
|
extern int height; /* game canvas height */
|
||||||
|
|
||||||
#define DEFAULT_WIDTH 800
|
#define DEFAULT_WIDTH 1000
|
||||||
#define DEFAULT_HEIGHT 800
|
#define DEFAULT_HEIGHT 1000
|
||||||
|
|
||||||
extern GtkWidget* canvas; /* game canvas object */
|
extern GtkWidget* canvas; /* game canvas object */
|
||||||
|
|
||||||
|
41
polygons.cc
41
polygons.cc
@ -14,7 +14,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#define ARROW_VAL_RATIO 1.7
|
#define ARROW_VAL_RATIO 1.7
|
||||||
|
#define SUBSETPS 5
|
||||||
|
|
||||||
bool draw_speed = true;
|
bool draw_speed = true;
|
||||||
|
|
||||||
@ -35,6 +35,21 @@ static double random_color_component() {
|
|||||||
return 1.0 * (rand() % 200 + 56) / 255;
|
return 1.0 * (rand() % 200 + 56) / 255;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static vec2d random_velocity() {
|
||||||
|
double r2;
|
||||||
|
vec2d v;
|
||||||
|
do {
|
||||||
|
v.x = v_min + rand() % (v_max + 1 - v_min);
|
||||||
|
v.y = v_min + rand() % (v_max + 1 - v_min);
|
||||||
|
r2 = vec2d::dot(v, v);
|
||||||
|
} while (r2 > v_max * v_max || r2 < v_min * v_min);
|
||||||
|
if (rand() % 2)
|
||||||
|
v.x = -v.x;
|
||||||
|
if (rand() % 2)
|
||||||
|
v.y = -v.y;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void polygons_init_state() {
|
void polygons_init_state() {
|
||||||
n_polygons = 20;
|
n_polygons = 20;
|
||||||
polygons = new polygon[n_polygons];
|
polygons = new polygon[n_polygons];
|
||||||
@ -68,7 +83,6 @@ void polygons_init_state() {
|
|||||||
.set_center({width / 2., height - height / 17.})
|
.set_center({width / 2., height - height / 17.})
|
||||||
.set_angle(45);
|
.set_angle(45);
|
||||||
|
|
||||||
|
|
||||||
// ---------- Shapes flying around start here ----------
|
// ---------- Shapes flying around start here ----------
|
||||||
polygons[n++] = poly_generate::regular(100, 3)
|
polygons[n++] = poly_generate::regular(100, 3)
|
||||||
.set_center({100, 400})
|
.set_center({100, 400})
|
||||||
@ -88,9 +102,14 @@ void polygons_init_state() {
|
|||||||
.set_speed({10, 0});
|
.set_speed({10, 0});
|
||||||
|
|
||||||
polygons[n++] = poly_generate::rectangle(100, 150).set_center({600, 200});
|
polygons[n++] = poly_generate::rectangle(100, 150).set_center({600, 200});
|
||||||
|
|
||||||
|
polygons[n++] = poly_generate::regular(72, 8)
|
||||||
|
.set_center({500, 500})
|
||||||
|
.set_speed({100, 0});
|
||||||
|
|
||||||
polygons[n++] = poly_generate::regular(50, 5)
|
polygons[n++] = poly_generate::regular(50, 5)
|
||||||
.set_center({150, 150})
|
.set_center({150, 150})
|
||||||
.set_speed({100, 0});
|
.set_speed({150, 0});
|
||||||
|
|
||||||
polygons[n++] = poly_generate::general({{40, 20},
|
polygons[n++] = poly_generate::general({{40, 20},
|
||||||
{40, 40},
|
{40, 40},
|
||||||
@ -232,19 +251,24 @@ static void check_collisions(polygon* current_p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void polygons_update_state() {
|
void polygons_update_state() {
|
||||||
|
const static float sub_delta = delta / SUBSETPS;
|
||||||
|
|
||||||
|
for (uint i = SUBSETPS; i--;) {
|
||||||
for (polygon* p = polygons; p != polygons + n_polygons; ++p) {
|
for (polygon* p = polygons; p != polygons + n_polygons; ++p) {
|
||||||
if (p->mass == INFINITY) // immovable objects don't need to be updated
|
// immovable objects don't need to be updated
|
||||||
|
if (p->mass == INFINITY)
|
||||||
continue;
|
continue;
|
||||||
check_collisions(p);
|
check_collisions(p);
|
||||||
|
|
||||||
p->rotate(delta * p->angular_speed);
|
p->rotate(sub_delta * p->angular_speed);
|
||||||
p->angle = std::fmod(p->angle, 360);
|
p->angle = std::fmod(p->angle, 360);
|
||||||
|
|
||||||
p->translate(delta * p->speed);
|
p->translate(sub_delta * p->speed);
|
||||||
|
|
||||||
vec2d g = gravity_vector(p);
|
vec2d g = gravity_vector(p);
|
||||||
p->translate(.5 * delta * delta * g);
|
p->translate(.5 * sub_delta * sub_delta * g);
|
||||||
p->speed += delta * g;
|
p->speed += sub_delta * g;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +332,6 @@ void polygon::draw(cairo_t* cr) const {
|
|||||||
vec2d centroid = this->centroid();
|
vec2d centroid = this->centroid();
|
||||||
draw_circle(cr, centroid, 1);
|
draw_circle(cr, centroid, 1);
|
||||||
|
|
||||||
|
|
||||||
// draw speed
|
// draw speed
|
||||||
if (draw_speed && this->mass != INFINITY) {
|
if (draw_speed && this->mass != INFINITY) {
|
||||||
hsv_t hsv = rgb2hsv(this->color);
|
hsv_t hsv = rgb2hsv(this->color);
|
||||||
|
Reference in New Issue
Block a user