Skip to content
Snippets Groups Projects
Commit 4e094ac6 authored by Boris Stefanovic's avatar Boris Stefanovic
Browse files

init

parents
No related branches found
No related tags found
No related merge requests found
*.o
main
tests
Makefile 0 → 100644
#The compiler
CC:=gcc
#The flags passed to the compiler
CFLAGS:=-g -Ofast -Wall -Wextra -fsanitize=address -fsanitize=leak -std=gnu11
#The flags passed to the linker
LDFLAGS:=-lm -lSDL2
#Path to the lib Vec2
VPATH:=vec2 gfx planet
main: main.o vec2.o gfx.o planet.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
run_tests: tests
./$<
tests: vec_tests.o vec2.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
planet.o: planet.h
vec2.o: vec2.h
gfx.o: gfx.h
clean:
rm -f *.o main tests
gfx/gfx.c 0 → 100644
/// @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);
}
\ No newline at end of file
#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
main.c 0 → 100644
#include "gfx/gfx.h"
#include "vec2/vec2.h"
#include "planet/planet.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SCREEN_WIDTH 1000
#define SCREEN_HEIGHT 1000
int main()
{
srand(time(NULL));
struct gfx_context_t *ctxt =
gfx_create("Planetary system", SCREEN_WIDTH, SCREEN_HEIGHT);
if (!ctxt)
{
fprintf(stderr, "Graphics initialization failed!\n");
return EXIT_FAILURE;
}
// TODO : create your system
while (true)
{
gfx_present(ctxt);
// TODO : draw the current state of your system
// TODO : update your system
gfx_clear(ctxt, COLOR_BLACK);
if (gfx_keypressed() == SDLK_ESCAPE)
{
break;
}
}
// TODO : Free your system
gfx_destroy(ctxt);
return EXIT_SUCCESS;
}
#include "planet.h"
#include <stdlib.h>
#define G 6.67e-11
#define M_SOLEIL 1.989e30
// TODO : magic
\ No newline at end of file
#ifndef _PLANET_H_
#define _PLANET_H_
#include "../vec2/vec2.h"
#include "../gfx/gfx.h"
typedef struct _planet
{
double mass;
vec2 pos; // x(t)
vec2 prec_pos; // x(t - dt)
} planet_t;
typedef struct _system
{
planet_t star; // ex. The sun
uint32_t nb_planets; // The number of orbiting planets
planet_t *planets; // An array of orbiting planets
} system_t;
// Those function are not mandatory to implement,
// it's rather a hint of what you should have.
planet_t create_planet(double mass, vec2 pos);
system_t create_system(double delta_t);
void show_system(struct gfx_context_t *ctxt, system_t *system);
void update_system(system_t *system, double delta_t);
void free_system(system_t *system);
#endif
\ No newline at end of file
// TODO : Replace this file by your vec2.c from last tp.
#ifndef _VEC2_H_
#define _VEC2_H_
#include <stdbool.h>
#include <stdint.h>
typedef struct _vec2
{
double x, y;
} vec2;
typedef struct _coordinates
{
uint32_t row, column;
} coordinates;
vec2 vec2_create(double x_, double y_);
vec2 vec2_create_zero();
vec2 vec2_add(vec2 lhs, vec2 rhs);
vec2 vec2_sub(vec2 lhs, vec2 rhs);
vec2 vec2_mul(double scalar, vec2 rhs);
double vec2_dot(vec2 lhs, vec2 rhs);
double vec2_norm_sqr(vec2 v);
double vec2_norm(vec2 v);
vec2 vec2_normalize(vec2 v);
bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps);
coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height);
void vec2_print(vec2 v);
#endif
#include "vec2.h"
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
typedef struct _test_result
{
bool passed;
const char *name;
} test_result;
typedef test_result (*unit_test_t)(void);
void print_in_color(char *color, char *text)
{
printf("\033%s", color);
printf("%s", text);
printf("\033[0m");
}
void print_in_red(char *text)
{
print_in_color("[0;31m", text);
}
void print_in_green(char *text)
{
print_in_color("[0;32m", text);
}
bool dbl_eq(double a, double b)
{
return fabs(a - b) < 1e-6;
}
/*
*
* Write your tests here
*
*/
/* TODO
vec2 vec2_create(double x_, double y_); -- Ok
vec2 vec2_create_zero(); -- Ok
vec2 vec2_add(vec2 lhs, vec2 rhs); -- Ok
vec2 vec2_sub(vec2 lhs, vec2 rhs); -- Ok
vec2 vec2_mul(double scalar, vec2 lhs); -- Ok
double vec2_dot(vec2 lhs, vec2 rhs); -- Ok
double vec2_norm_sqr(vec2 v); -- Ok
double vec2_norm(vec2 v); -- Ok
vec2 vec2_normalize(vec2 v); -- Ok
bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps);
coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height);
*/
const double u_x[] = {1.25, 3.53, 2.64, 8.8};
const double u_y[] = {3.42, 7.22, 5.32, 2.44};
const double v_x[] = {4.32, 6.21, 7.42, 9.32};
const double v_y[] = {5.22, 3.56, 8.65, 6.44};
const uint32_t nb_tests = sizeof(u_x) / sizeof(double);
test_result t_vec2_create_0()
{
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 v = vec2_create(u_x[i], u_y[i]);
if (u_x[i] != v.x || u_y[i] != v.y)
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_create 0"};
}
test_result t_vec2_create_zero_0()
{
vec2 v = vec2_create_zero();
return (test_result){.passed = v.x == 0.0 && v.y == 0.0,
.name = "Test vec2_create_zero 0"};
}
test_result t_vec2_add_0()
{
double r_x[] = {5.57, 9.74, 10.06, 18.12};
double r_y[] = {8.64, 10.78, 13.97, 8.88};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
vec2 v = vec2_create(v_x[i], v_y[i]);
vec2 r = vec2_add(u, v);
if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_add 0"};
}
test_result t_vec2_sub_0()
{
double r_x[] = {-3.07, -2.68, -4.78, -0.52};
double r_y[] = {-1.80, 3.66, -3.33, -4.00};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
vec2 v = vec2_create(v_x[i], v_y[i]);
vec2 r = vec2_sub(u, v);
if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_sub 0"};
}
test_result t_vec2_mul_0()
{
double r_x[] = {5.40, 21.9213, 19.5888, 82.016};
double r_y[] = {14.7744, 44.8362, 39.4744, 22.740800};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
double alpha = v_x[i];
vec2 u = vec2_create(u_x[i], u_y[i]);
vec2 r = vec2_mul(alpha, u);
if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_mul 0"};
}
test_result t_vec2_dot_0()
{
double r[] = {23.2524, 47.6245, 65.6068, 97.7296};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
vec2 v = vec2_create(v_x[i], v_y[i]);
double res = vec2_dot(u, v);
if (!dbl_eq(res, r[i]))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_dot 0"};
}
test_result t_vec2_norm_sqr_0()
{
double r[] = {13.2589, 64.5893, 35.272, 83.3936};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
double res = vec2_norm_sqr(u);
if (!dbl_eq(res, r[i]))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_norm_sqr 0"};
}
test_result t_vec2_norm_0()
{
double r[] = {3.641277, 8.036747, 5.939023, 9.132010};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
double res = vec2_norm(u);
if (!dbl_eq(res, r[i]))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_norm 0"};
}
test_result t_vec2_normalize_0()
{
double r_x[] = {0.343286, 0.439232, 0.444518, 0.963643};
double r_y[] = {0.939231, 0.898373, 0.895770, 0.267192};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
vec2 r = vec2_normalize(u);
if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i])))
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_normalize 0"};
}
test_result t_vec2_is_approx_equal_0()
{
bool r[] = {true, true, false, false};
double t_x[] = {u_x[0], u_x[1] + 1e-4, u_x[2] + 15.0, u_x[3] + 1e-2};
double t_y[] = {u_y[0], u_y[1] - 1e-4, u_y[2] + 15.0, u_y[3] + 1e-2};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 u = vec2_create(u_x[i], u_y[i]);
vec2 t = vec2_create(t_x[i], t_y[i]);
if (vec2_is_approx_equal(u, t, 1e-3) != r[i])
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_is_approx_equal 0"};
}
test_result t_vec2_to_coordinates_0()
{
uint32_t height = 300;
uint32_t width = 100;
double t_x[] = {0.25, 0.5, 0.75, 1};
double t_y[] = {0, 1.0 / 3.0, 2.0 / 3.0, 1};
uint32_t r_col[] = {62, 74, 87, 99};
uint32_t r_row[] = {150, 199, 249, 299};
bool passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
vec2 t = vec2_create(t_x[i], t_y[i]);
coordinates r = vec2_to_coordinates(t, width, height);
if (r.row != r_row[i] || r.column != r_col[i])
{
passed = false;
break;
}
}
return (test_result){.passed = passed,
.name = "Test vec2_to_coordinates 0"};
}
//Add or remove your test function name here
const unit_test_t tests[] = {
t_vec2_create_0,
t_vec2_create_zero_0,
t_vec2_add_0,
t_vec2_sub_0,
t_vec2_mul_0,
t_vec2_dot_0,
t_vec2_norm_sqr_0,
t_vec2_norm_0,
t_vec2_normalize_0,
t_vec2_is_approx_equal_0,
t_vec2_to_coordinates_0};
int main()
{
uint32_t nb_tests = sizeof(tests) / sizeof(unit_test_t);
char message[256];
bool all_passed = true;
for (uint32_t i = 0; i < nb_tests; i++)
{
printf("Running test n°%d: ...\n", i);
test_result r = tests[i]();
if (r.passed)
{
sprintf(message, "\t- %s : OK", r.name);
print_in_green(message);
}
else
{
all_passed = false;
sprintf(message, "\t- %s : FAILED", r.name);
print_in_red(message);
}
printf("\n");
}
if (all_passed)
print_in_green("\nTests suite result : OK\n");
else
print_in_red("\nTests suite result : FAILED\n");
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment