diff --git a/CelestialObject.h b/CelestialObject.h
index 1732f78a5383e3a85ef62d4de9e25aa889523816..266f603f86c9fda21c33d15efb527a15374a62b8 100644
--- a/CelestialObject.h
+++ b/CelestialObject.h
@@ -2,7 +2,6 @@
 #define CELESTIAL_OBJECT_H
 
 #include "Vector2.h"
-#include "gfx/gfx.h"
 
 typedef struct CelestialObject CelestialObject;
 typedef struct CelestialObject {
diff --git a/Makefile b/Makefile
index b8b51028b0c6945ea9c5a358e5a1e2d25742298b..602e97af934bbc6076aeb65c69f807fd88cb6a2b 100644
--- a/Makefile
+++ b/Makefile
@@ -2,14 +2,13 @@ TARGET = main
 CC:=gcc
 # CFLAGS:=-g -Ofast -Wall -Wextra -fsanitize=address -fsanitize=leak -std=gnu11
 # CFLAGS:=-fsanitize=address
-CFLAGS:=-g -Ofast -Wall -Wextra -std=gnu11
-LDFLAGS:=-lm -lSDL2
-VPATH:=gfx
+CFLAGS:=-g -O3 -Wall -Wextra -std=gnu11
+LDFLAGS:=-lm -lGL -lGLU -lglut
 
 %.o: %.c $(HEADERS)
 	$(CC) $(CFLAGS) -c $< -o $@
 
-$(TARGET): main.o Vector2.o CelestialObject.o PlanetarySystem.o gfx.o
+$(TARGET): main.o Vector2.o CelestialObject.o PlanetarySystem.o
 	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
 
 clean:
diff --git a/PlanetarySystem.c b/PlanetarySystem.c
index a27f9eed57a0a5d763435501f0f7ecbd1e2629a4..962676b780b3b6ed322d36e17c0bb96b16ad5a91 100644
--- a/PlanetarySystem.c
+++ b/PlanetarySystem.c
@@ -1,10 +1,11 @@
 #include "PlanetarySystem.h"
 
+#include <GL/glut.h>
+#include <math.h>
 #include <stdlib.h>
 
 #include "CelestialObject.h"
 #include "Vector2.h"
-#include "gfx/gfx.h"
 
 const uint32_t SCREEN_WIDTH = 1000;
 const uint32_t SCREEN_HEIGHT = 1000;
@@ -30,20 +31,19 @@ const double VENUS_SEMI_MAJOR_AXIS = 108.208475 * 1E9;
 const double EARTH_SEMI_MAJOR_AXIS = 149.598262 * 1E9;
 const double MARS_SEMI_MAJOR_AXIS = 227.943824 * 1E9;
 
-PlanetarySystem *planetary_system_create(double interval) {
+PlanetarySystem *planetary_system_create() {
     PlanetarySystem *planetary_system = (PlanetarySystem *)malloc(sizeof(PlanetarySystem));
 
     planetary_system->objects_length = 6;
     planetary_system->objects = (CelestialObject **)malloc(sizeof(PlanetarySystem *) * planetary_system->objects_length);
-    planetary_system->interval = interval;
     planetary_system->zoom_factor = 1;
     planetary_system->reference_frame_object_index = 0;
 
-    planetary_system->objects[0] = celestial_object_create(SUN_MASS, 0, 0, 50, 0x00FFFFFF);
-    planetary_system->objects[1] = celestial_object_create(MERCURY_MASS, MERCURY_SEMI_MAJOR_AXIS, MERCURY_ECCENTRICITY, 10, 0x00DBCECA);
-    planetary_system->objects[2] = celestial_object_create(VENUS_MASS, VENUS_SEMI_MAJOR_AXIS, VENUS_ECCENTRICITY, 20, 0x008B7D82);
-    planetary_system->objects[3] = celestial_object_create(EARTH_MASS, EARTH_SEMI_MAJOR_AXIS, EARTH_ECCENTRICITY, 20, 0x006b93d6);
-    planetary_system->objects[4] = celestial_object_create(MARS_MASS, MARS_SEMI_MAJOR_AXIS, MARS_ECCENTRICITY, 12, 0x00BC2732);
+    planetary_system->objects[0] = celestial_object_create(SUN_MASS, 0, 0, 50, 0xFFFFFF);
+    planetary_system->objects[1] = celestial_object_create(MERCURY_MASS, MERCURY_SEMI_MAJOR_AXIS, MERCURY_ECCENTRICITY, 10, 0xDBCECA);
+    planetary_system->objects[2] = celestial_object_create(VENUS_MASS, VENUS_SEMI_MAJOR_AXIS, VENUS_ECCENTRICITY, 20, 0x8B7D82);
+    planetary_system->objects[3] = celestial_object_create(EARTH_MASS, EARTH_SEMI_MAJOR_AXIS, EARTH_ECCENTRICITY, 20, 0x6b93d6);
+    planetary_system->objects[4] = celestial_object_create(MARS_MASS, MARS_SEMI_MAJOR_AXIS, MARS_ECCENTRICITY, 12, 0xBC2732);
     planetary_system->objects[5] = celestial_object_create(7.34767309 * 1E22, 384.399 * 1E6, 0.0549, 5, 0x8A2BE2);
     planetary_system->objects[5]->current_position.x += planetary_system->objects[3]->current_position.x;
 
@@ -68,7 +68,7 @@ Vector2 calculate_gravitational_acceleration(PlanetarySystem *planetary_system,
     return a;
 }
 
-void planetary_system_update(PlanetarySystem *planetary_system) {
+void planetary_system_update(PlanetarySystem *planetary_system, double interval) {
     for (uint32_t i = 1; i < planetary_system->objects_length; i += 1) {
         CelestialObject *object = planetary_system->objects[i];
         Vector2 current_position = object->current_position;
@@ -84,20 +84,19 @@ void planetary_system_update(PlanetarySystem *planetary_system) {
             double periapsis_velocity_scalar = sqrt((G * star->mass * (1 + object->eccentricity)) / (object->semi_major_axis * (1 - object->eccentricity)));
 
             if (i == 5) {
-                printf("%lf\n", periapsis_velocity_scalar);
                 periapsis_velocity_scalar += 30290.322245;
             }
 
             Vector2 r = vector2_normalize(vector2_create(current_position.y, -current_position.x));
             Vector2 periapsis_velocity = vector2_multiply(r, periapsis_velocity_scalar);
 
-            new_position = vector2_add(current_position, vector2_multiply(periapsis_velocity, planetary_system->interval));
+            new_position = vector2_add(current_position, vector2_multiply(periapsis_velocity, interval));
             Vector2 a = calculate_gravitational_acceleration(planetary_system, i);
-            new_position = vector2_add(new_position, vector2_multiply(a, 0.5 * pow(planetary_system->interval, 2)));
+            new_position = vector2_add(new_position, vector2_multiply(a, 0.5 * pow(interval, 2)));
         } else {
             new_position = vector2_substract(vector2_multiply(current_position, 2), object->previous_position);
             Vector2 a = calculate_gravitational_acceleration(planetary_system, i);
-            new_position = vector2_add(new_position, vector2_multiply(a, pow(planetary_system->interval, 2)));
+            new_position = vector2_add(new_position, vector2_multiply(a, pow(interval, 2)));
         }
 
         object->previous_position = object->current_position;
@@ -106,20 +105,29 @@ void planetary_system_update(PlanetarySystem *planetary_system) {
 }
 
 Vector2 scale_position(Vector2 position) {
-    Vector2 scaled_position = vector2_multiply(position, 1.0 / (250 * 1E9));
+    Vector2 scaled_position = vector2_multiply(position, 1.0 / (260 * 1E9));
     scaled_position = vector2_fit_canvas(scaled_position, SCREEN_WIDTH, SCREEN_HEIGHT);
     return scaled_position;
 }
 
-void planetary_system_draw(PlanetarySystem *planetary_system, struct gfx_context_t *context) {
-    gfx_clear(context, COLOR_BLACK);
-
+void planetary_system_draw(PlanetarySystem *planetary_system) {
     for (uint32_t i = 0; i < planetary_system->objects_length; i += 1) {
         CelestialObject *object = planetary_system->objects[i];
-        Vector2 tmp = vector2_substract(object->current_position, planetary_system->objects[planetary_system->reference_frame_object_index]->current_position);
-        tmp = vector2_multiply(tmp, planetary_system->zoom_factor);
-        Vector2 scaled_position = scale_position(tmp);
+        Vector2 unscaled_position = vector2_substract(object->current_position, planetary_system->objects[planetary_system->reference_frame_object_index]->current_position);
+        unscaled_position = vector2_multiply(unscaled_position, planetary_system->zoom_factor);
+        Vector2 scaled_position = scale_position(unscaled_position);
+
+        uint32_t color = object->drawing_color;
+        glColor3ub((color & 0xFF0000) >> 16, (color & 0x00FF00) >> 8, (color & 0x0000FF) >> 0);
+        glBegin(GL_POLYGON);
+
+        for (uint32_t i = 0; i < 360; i += 1) {
+            double theta = i * 3.1415 / 180;
+            double x = scaled_position.x + object->drawing_disc_radius * cos(theta);
+            double y = scaled_position.y + object->drawing_disc_radius * sin(theta);
+            glVertex2f(x, y);
+        }
 
-        draw_full_circle(context, scaled_position.x, scaled_position.y, object->drawing_disc_radius, object->drawing_color);
+        glEnd();
     }
 }
diff --git a/PlanetarySystem.h b/PlanetarySystem.h
index 4fdf97fe53d19402d65404dbf1e577d23a003fe7..7c7f12c4b45ded30596fdb4cfa28bfcd2200a81a 100644
--- a/PlanetarySystem.h
+++ b/PlanetarySystem.h
@@ -4,7 +4,6 @@
 #include <stdint.h>
 
 #include "CelestialObject.h"
-#include "gfx/gfx.h"
 
 const uint32_t SCREEN_WIDTH;
 const uint32_t SCREEN_HEIGHT;
@@ -17,8 +16,8 @@ typedef struct {
     int32_t reference_frame_object_index;
 } PlanetarySystem;
 
-PlanetarySystem *planetary_system_create(double interval);
-void planetary_system_update(PlanetarySystem *planetary_system);
-void planetary_system_draw(PlanetarySystem *planetary_system, struct gfx_context_t *context);
+PlanetarySystem *planetary_system_create();
+void planetary_system_update(PlanetarySystem *planetary_system, double interval);
+void planetary_system_draw(PlanetarySystem *planetary_system);
 
 #endif
diff --git a/README b/README
new file mode 100644
index 0000000000000000000000000000000000000000..59f8fb0015dfe2f35550678a47552639c71997f0
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+sudo apt-get install freeglut3-dev
diff --git a/gfx/gfx.c b/gfx/gfx.c
deleted file mode 100644
index 3821077bbbf7964c49e73b9b94d6dc123bcb9d9f..0000000000000000000000000000000000000000
--- a/gfx/gfx.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/// @file gfx.c
-/// @author Florent Gluck
-/// @date November 6, 2016
-/// Helper routines to render pixels in fullscreen graphic mode.
-/// Uses the SDL2 library.
-/// Update : Add full circle
-/// @author Michaƫl El Kharroubi
-/// @date 19 November 2021
-
-#include "gfx.h"
-#include <assert.h>
-
-/// Create a fullscreen graphic window.
-/// @param title Title of the window.
-/// @param width Width of the window in pixels.
-/// @param height Height of the window in pixels.
-/// @return a pointer to the graphic context or NULL if it failed.
-struct gfx_context_t *gfx_create(char *title, uint32_t width, uint32_t height)
-{
-    if (SDL_Init(SDL_INIT_VIDEO) != 0)
-        goto error;
-    SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED,
-                                          SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE);
-    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
-    SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
-                                             SDL_TEXTUREACCESS_STREAMING, width, height);
-    uint32_t *pixels = malloc(width * height * sizeof(uint32_t));
-    struct gfx_context_t *ctxt = malloc(sizeof(struct gfx_context_t));
-
-    if (!window || !renderer || !texture || !pixels || !ctxt)
-        goto error;
-
-    ctxt->renderer = renderer;
-    ctxt->texture = texture;
-    ctxt->window = window;
-    ctxt->width = width;
-    ctxt->height = height;
-    ctxt->pixels = pixels;
-
-    SDL_ShowCursor(SDL_DISABLE);
-    gfx_clear(ctxt, COLOR_BLACK);
-    return ctxt;
-
-error:
-    return NULL;
-}
-
-/// Draw a pixel in the specified graphic context.
-/// @param ctxt Graphic context where the pixel is to be drawn.
-/// @param column X coordinate of the pixel.
-/// @param row Y coordinate of the pixel.
-/// @param color Color of the pixel.
-void gfx_putpixel(struct gfx_context_t *ctxt, uint32_t column, uint32_t row, uint32_t color)
-{
-    if (column < ctxt->width && row < ctxt->height)
-        ctxt->pixels[ctxt->width * row + column] = color;
-}
-
-/// Clear the specified graphic context.
-/// @param ctxt Graphic context to clear.
-/// @param color Color to use.
-void gfx_clear(struct gfx_context_t *ctxt, uint32_t color)
-{
-    int n = ctxt->width * ctxt->height;
-    while (n)
-        ctxt->pixels[--n] = color;
-}
-
-/// Display the graphic context.
-/// @param ctxt Graphic context to clear.
-void gfx_present(struct gfx_context_t *ctxt)
-{
-    SDL_UpdateTexture(
-        ctxt->texture, NULL, ctxt->pixels, ctxt->width * sizeof(uint32_t));
-    SDL_RenderCopy(ctxt->renderer, ctxt->texture, NULL, NULL);
-    SDL_RenderPresent(ctxt->renderer);
-}
-
-/// Destroy a graphic window.
-/// @param ctxt Graphic context of the window to close.
-void gfx_destroy(struct gfx_context_t *ctxt)
-{
-    SDL_ShowCursor(SDL_ENABLE);
-    SDL_DestroyTexture(ctxt->texture);
-    SDL_DestroyRenderer(ctxt->renderer);
-    SDL_DestroyWindow(ctxt->window);
-    free(ctxt->pixels);
-    ctxt->texture = NULL;
-    ctxt->renderer = NULL;
-    ctxt->window = NULL;
-    ctxt->pixels = NULL;
-    SDL_Quit();
-    free(ctxt);
-}
-
-/// If a key was pressed, returns its key code (non blocking call).
-/// List of key codes: https://wiki.libsdl.org/SDL_Keycode
-/// @return the key that was pressed or 0 if none was pressed.
-SDL_Keycode gfx_keypressed()
-{
-    SDL_Event event;
-    if (SDL_PollEvent(&event))
-    {
-        if (event.type == SDL_KEYDOWN)
-            return event.key.keysym.sym;
-    }
-    return 0;
-}
-
-/// Draw a full circle using Andres's discrete circle algorithm.
-/// @param ctxt Graphic context to clear.
-/// @param c_column X coordinate of the circle center.
-/// @param c_row Y coordinate of the circle center.
-/// @param r The radius of circle (in pixels).
-/// @param color Color to use.
-void draw_full_circle(struct gfx_context_t *ctxt, uint32_t c_column, uint32_t c_row, uint32_t r, uint32_t color)
-{
-    int32_t x = 0, y = r, d = r - 1;
-    while (y >= x)
-    {
-        gfx_putpixel(ctxt, c_column + x, c_row + y, color);
-        gfx_putpixel(ctxt, c_column + y, c_row + x, color);
-        gfx_putpixel(ctxt, c_column - x, c_row + y, color);
-        gfx_putpixel(ctxt, c_column - y, c_row + x, color);
-
-        gfx_putpixel(ctxt, c_column + x, c_row - y, color);
-        gfx_putpixel(ctxt, c_column + y, c_row - x, color);
-        gfx_putpixel(ctxt, c_column - x, c_row - y, color);
-        gfx_putpixel(ctxt, c_column - y, c_row - x, color);
-
-        if ((2 * x) <= d)
-        {
-            d -= 2 * x + 1;
-            x += 1;
-        }
-        else if (d < (2 * (((int32_t)r) - y)))
-        {
-            d += 2 * y - 1;
-            y -= 1;
-        }
-        else
-        {
-            d -= 2 * (x - y + 1);
-            y -= 1;
-            x += 1;
-        }
-    }
-    if (r > 0)
-        draw_full_circle(ctxt, c_column, c_row, r - 1, color);
-}
diff --git a/gfx/gfx.h b/gfx/gfx.h
deleted file mode 100644
index 20b7815e4c5ef7a8daa871153c3f4affeeb448b6..0000000000000000000000000000000000000000
--- a/gfx/gfx.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _GFX_H_
-#define _GFX_H_
-
-#include <SDL2/SDL.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#define MAKE_COLOR(r, g, b) \
-    ((uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16))
-
-#define COLOR_GET_B(color) (color & 0xff)
-#define COLOR_GET_G(color) ((color >> 8) & 0xff)
-#define COLOR_GET_R(color) ((color >> 16) & 0xff)
-
-#define COLOR_BLACK 0x00000000
-#define COLOR_RED 0x00FF0000
-#define COLOR_GREEN 0x0000FF00
-#define COLOR_BLUE 0x000000FF
-#define COLOR_WHITE 0x00FFFFFF
-#define COLOR_YELLOW 0x00FFFF00
-
-struct gfx_context_t
-{
-    SDL_Window *window;
-    SDL_Renderer *renderer;
-    SDL_Texture *texture;
-    uint32_t *pixels;
-    uint32_t width;
-    uint32_t height;
-};
-
-extern void gfx_putpixel(
-    struct gfx_context_t *ctxt, uint32_t column, uint32_t row, uint32_t color);
-extern void gfx_clear(struct gfx_context_t *ctxt, uint32_t color);
-extern struct gfx_context_t *gfx_create(char *text, uint32_t width, uint32_t height);
-extern void gfx_destroy(struct gfx_context_t *ctxt);
-extern void gfx_present(struct gfx_context_t *ctxt);
-extern SDL_Keycode gfx_keypressed();
-extern void draw_full_circle(struct gfx_context_t *ctxt, uint32_t c_column, uint32_t c_row, uint32_t r, uint32_t color);
-
-#endif
diff --git a/main.c b/main.c
index 336ce592e500fbec6127a6a4f355b9169eacbe12..31e44e23080359a24451f75d87596366adbd2cdf 100644
--- a/main.c
+++ b/main.c
@@ -1,3 +1,4 @@
+#include <GL/glut.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -5,79 +6,115 @@
 
 #include "PlanetarySystem.h"
 #include "Vector2.h"
-#include "gfx/gfx.h"
 
-int main() {
-    // srand(time(NULL));
-    // srand(0);
+#define WINDOW_NAME "Solar System"
+#define REFRESH_RATE 100
+#define UPDATE_RATE 10000
+#define TIME_ELASPING_PER_SECOND 3600 * 24 * 30
+
+// https://stackoverflow.com/questions/3417837/what-is-the-best-way-to-suppress-a-unused-variable-x-warning
+#ifdef UNUSED
+#elif defined(__GNUC__)
+#define UNUSED(x) UNUSED_##x __attribute__((unused))
+#elif defined(__LCLINT__)
+#define UNUSED(x) /*@unused@*/ x
+#else
+#define UNUSED(x) x
+#endif
+
+PlanetarySystem *planetary_system;
+uint32_t elapsed_time = 0;
+uint32_t true_time_shift = 0;
+
+void draw_timer() {
+    glutPostRedisplay();
+    glutTimerFunc(1000 / REFRESH_RATE, draw_timer, 0);
+    elapsed_time += 1;
+}
+
+void update_timer() {
+    for (uint32_t i = 0; i < UPDATE_RATE / REFRESH_RATE; i += 1) {
+        planetary_system_update(planetary_system, (double)TIME_ELASPING_PER_SECOND / UPDATE_RATE);
+    }
 
-    struct gfx_context_t *context = gfx_create("Solar System", SCREEN_WIDTH, SCREEN_HEIGHT);
+    glutTimerFunc(1000 / REFRESH_RATE, update_timer, 0);
+}
+
+void draw() {
+    glClearColor(0.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
 
-    if (!context) {
-        fprintf(stderr, "Graphics initialization failed!\n");
-        return EXIT_FAILURE;
+    if (elapsed_time % REFRESH_RATE == 0) {
+        char title[100];
+        sprintf(title, "Solar System (%d : %ld)", elapsed_time / REFRESH_RATE, (time(NULL) - true_time_shift) % 1000);
+        glutSetWindowTitle(title);
     }
 
-    int32_t time_elapsing_per_second = 3600 * 24 * 5;
-    int32_t refresh_rate = 240;
-    int32_t elapsed_time = 0;
-    double sleep_duration = 1.0 / refresh_rate * 1E9;
-    printf("%lf\n", (double)time_elapsing_per_second / refresh_rate);
+    planetary_system_draw(planetary_system);
 
-    PlanetarySystem *planetary_system = planetary_system_create((double)time_elapsing_per_second / refresh_rate);
+    glFlush();
+}
 
-    int64_t tmp = time(NULL) % 1000;
+void handle_keyboard_input(unsigned char key, int UNUSED(x), int UNUSED(y)) {
+    if (key == 27) {
+        exit(0);
+    }
+}
 
-    while (true) {
-        planetary_system_update(planetary_system);
-        gfx_present(context);
-        planetary_system_draw(planetary_system, context);
+void handle_special_keyboard_input(int key, int UNUSED(x), int UNUSED(y)) {
+    if (key == GLUT_KEY_LEFT) {
+        planetary_system->reference_frame_object_index -= 1;
 
-        if (elapsed_time % refresh_rate == 0) {
-            char title[100];
-            sprintf(title, "Solar System (%d : %ld)", elapsed_time / refresh_rate, (time(NULL) - tmp) % 1000);
-            SDL_SetWindowTitle(context->window, title);
+        if (planetary_system->reference_frame_object_index < 0) {
+            planetary_system->reference_frame_object_index = planetary_system->objects_length - 1;
         }
+    }
 
-        SDL_Event event;
-        if (SDL_PollEvent(&event)) {
-            if (event.type == SDL_MOUSEWHEEL) {
-                if (event.wheel.y > 0) {
-                    planetary_system->zoom_factor *= 1.1;
-                } else if (event.wheel.y < 0) {
-                    planetary_system->zoom_factor /= 1.1;
-
-                    if (planetary_system->zoom_factor < 1) {
-                        planetary_system->zoom_factor = 1;
-                    }
-                }
-            }
-
-            if (event.type == SDL_KEYDOWN) {
-                if (event.key.keysym.sym == SDLK_ESCAPE) {
-                    break;
-                }
+    if (key == GLUT_KEY_RIGHT) {
+        planetary_system->reference_frame_object_index += 1;
+        planetary_system->reference_frame_object_index %= planetary_system->objects_length;
+    }
+}
 
-                if (event.key.keysym.sym == SDLK_LEFT) {
-                    planetary_system->reference_frame_object_index -= 1;
+void handle_mouse_input(int button, int state, int UNUSED(x), int UNUSED(y)) {
+    if (button == 3 || button == 4) {
+        if (state == GLUT_UP) return;
 
-                    if (planetary_system->reference_frame_object_index < 0) {
-                        planetary_system->reference_frame_object_index = planetary_system->objects_length - 1;
-                    }
-                }
+        if (button == 3) {
+            planetary_system->zoom_factor *= 1.1;
+        } else {
+            planetary_system->zoom_factor /= 1.1;
 
-                if (event.key.keysym.sym == SDLK_RIGHT) {
-                    planetary_system->reference_frame_object_index += 1;
-                    planetary_system->reference_frame_object_index %= planetary_system->objects_length;
-                }
+            if (planetary_system->zoom_factor < 1) {
+                planetary_system->zoom_factor = 1;
             }
         }
-
-        struct timespec t = {.tv_sec = 0, .tv_nsec = sleep_duration};
-        nanosleep(&t, NULL);
-        elapsed_time += 1;
     }
+}
+
+int main(int argc, char *argv[]) {
+    planetary_system = planetary_system_create();
+
+    glutInit(&argc, argv);
+    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
+    glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);
+    glutCreateWindow(WINDOW_NAME);
+
+    glClearColor(0.0, 0.0, 0.0, 1.0);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluOrtho2D(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
+
+    glutDisplayFunc(draw);
+    glutKeyboardFunc(handle_keyboard_input);
+    glutSpecialFunc(handle_special_keyboard_input);
+    glutMouseFunc(handle_mouse_input);
+
+    true_time_shift = time(NULL) % 1000;
+    glutTimerFunc(1000 / REFRESH_RATE, update_timer, 0);
+    glutTimerFunc(1000 / REFRESH_RATE, draw_timer, 0);
+
+    glutMainLoop();
 
-    gfx_destroy(context);
     return EXIT_SUCCESS;
 }