diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..dbb4484 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.ignoreCMakeListsMissing": true +} diff --git a/MLX42.supp b/MLX42.supp index 06bb237..8175bf6 100644 --- a/MLX42.supp +++ b/MLX42.supp @@ -46,3 +46,11 @@ ... fun:_dl_open } + +{ + + Memcheck:Addr8 + ... + fun:dl_open_worker +} + diff --git a/inc/fdf.h b/inc/fdf.h index a9debbe..1fb9876 100644 --- a/inc/fdf.h +++ b/inc/fdf.h @@ -31,16 +31,30 @@ # define FILE_ERROR "Error: could not open file %s\n" # define USAGE_ERROR "Usage: %s \n" -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif +# ifndef M_PI +# define M_PI 3.14159265358979323846 +# endif # define SQRT2 1.41421356237309514547 # define SQRT6 2.44948974278317788134 # define WIDTH 500 # define HEIGHT 500 -typedef struct s_point_3d +typedef enum e_colormode +{ + COLOR_MODE_DEFAULT, + COLOR_MODE_Z, + COLOR_MODE_GRADIENT +} t_colormode; + +typedef enum e_projection +{ + PROJECTION_ISOMETRIC, + PROJECTION_PARALLEL, + PROJECTION_TRIMETRIC +} t_projection; + +typedef struct s_point_3d { double x; double y; @@ -52,11 +66,12 @@ typedef struct s_point_2d { int x; int y; + int orig_z; int color; } t_point_2d; -typedef struct s_map +typedef struct s_map { t_point_3d *orig; t_point_3d *rot; @@ -68,54 +83,61 @@ typedef struct s_map typedef struct s_fdf { - t_map *map; - mlx_t *mlx; - mlx_image_t *img; - mlx_image_t *menu; - double angle_x; - double angle_y; - double angle_z; - double animate_z; - double zoom; - int offset_x; - int offset_y; - int last_width; - int last_height; - double z_scale; + t_map *map; + mlx_t *mlx; + mlx_image_t *img; + mlx_image_t *menu; + double angle_x; + double angle_y; + double angle_z; + double animate_z; + double zoom; + int offset_x; + int offset_y; + int last_width; + int last_height; + double z_scale; + t_colormode colormode; + t_projection projection; } t_fdf; -int interpolate_color(t_point_2d start, t_point_2d end, t_point_2d current); -int get_color(char *str); -int get_map_sizes(char *filename, t_map *map); -void free_line_and_split(char **line, char ***split); -int read_map(char *filename, t_fdf *fdf); -int parse_map(char *filename, t_fdf *fdf); -void print_map(t_map *map); -void copy_map(t_fdf *fdf); -void fdf_apply_rotation(t_fdf *fdf); -void handle_error(t_fdf *fdf, char *error); +int interpolate_color(t_point_2d start, + t_point_2d end, t_point_2d current); +int get_color(char *str); +int get_map_sizes(char *filename, t_map *map); +void free_line_and_split(char **line, char ***split); +int load_map_from_file(char *filename, t_fdf *fdf); +int parse_map(char *filename, t_fdf *fdf); +void copy_map(t_fdf *fdf); +void fdf_apply_rotation(t_fdf *fdf); +void handle_error(t_fdf *fdf, char *error); -void rotate_x(t_point_3d **points, double angle, int size); -void rotate_y(t_point_3d **points, double angle, int size); -void rotate_z(t_point_3d **points, double angle, int size); -bool fdf_put_pixel(mlx_image_t *img, t_point_2d point); -void fdf_draw_line(mlx_image_t *img, t_point_2d start, - t_point_2d end); -int fdf_hooks(t_fdf *fdf); -void resize_hook(int width, int height, void *param); +void rotate_x(t_point_3d **points, double angle, int size); +void rotate_y(t_point_3d **points, double angle, int size); +void rotate_z(t_point_3d **points, double angle, int size); +bool fdf_put_pixel(t_fdf *fdf, t_point_2d point); +void fdf_draw_line(t_fdf *fdf, t_point_2d start, + t_point_2d end); +int fdf_hooks(t_fdf *fdf); +void resize_hook(int width, int height, void *param); -void draw_hook(void *param); -void key_hook(mlx_key_data_t keydata, void *param); -void fdf_set_background(mlx_image_t *img, int color); -void project_isometric(t_fdf *fdf); -double deg2rad(double deg); -t_fdf *initialise_fdf(void); -bool clean_fdf(t_fdf *fdf); -void get_z_max(t_fdf *fdf); -int init_mlx(t_fdf *fdf); -void set_map_point(t_fdf *fdf, int x, int y, char **str); +void draw_hook(void *param); +void key_hook(mlx_key_data_t keydata, void *param); +void fdf_set_background(mlx_image_t *img, int color); +void project_isometric(t_fdf *fdf); +double deg2rad(double deg); +t_fdf *initialise_fdf(void); +bool clean_fdf(t_fdf *fdf); +void get_z_max(t_fdf *fdf); +int init_mlx(t_fdf *fdf); +void set_map_point(t_fdf *fdf, int x, int y, char **str); mlx_image_t *draw_menu(t_fdf *fdf); -int get_z_color(double z, int z_max); +int get_z_color(double z, int z_max); +void close_hook(void *param); +int get_gradient_color(double z, int z_max); +void project_parallel(t_fdf *fdf); +void project(t_fdf *fdf); + #endif @@ -135,4 +157,4 @@ int get_z_color(double z, int z_max); // [p] Change projection mode // [ESC] Close window -// ============================ \ No newline at end of file +// ============================ diff --git a/maps/42.fdf b/maps/42.fdf index 5547d00..c15deb0 100644 --- a/maps/42.fdf +++ b/maps/42.fdf @@ -1,4 +1,4 @@ -5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 0 0 10 10 0 0 0 10 10 10 10 10 0 0 0 0 0 10 10 0 0 10 10 0 0 0 0 0 0 0 10 10 0 0 diff --git a/src/clean_fdf.c b/src/clean_fdf.c index 2862f63..3920881 100644 --- a/src/clean_fdf.c +++ b/src/clean_fdf.c @@ -14,16 +14,12 @@ bool clean_fdf(t_fdf *fdf) { - mlx_delete_image(fdf->mlx, fdf->img); - mlx_delete_image(fdf->mlx, fdf->menu); - if (fdf->map) { free(fdf->map->orig); free(fdf->map->rot); free(fdf->map->proj); free(fdf->map); - } free(fdf); return (true); diff --git a/src/fdf_color.c b/src/fdf_color.c index 31cf3aa..55af049 100644 --- a/src/fdf_color.c +++ b/src/fdf_color.c @@ -58,15 +58,23 @@ int interpolate_color(t_point_2d start, t_point_2d end, t_point_2d current) return (red << 24 | green << 16 | blue << 8 | 0xFF); } -int get_z_color(double z, int z_max) +int get_z_color(double z, int z_max) { - int red; + int red; int green; - - int temp; + int temp; temp = 255 * z / z_max; red = temp; green = 255 - temp; return (red << 24 | green << 16 | 0x00FF); -} \ No newline at end of file +} + +int get_gradient_color(double z, int z_max) +{ + const int colors[] = {0x0058fbff, 0x007efeff, 0x008fd7ff, 0x0098a3f, + 0x009c7aff, 0x1fa46bff, 0x5eb13dff, 0x83c052ff, + 0xa5cf69ff, 0xc3de81ff, 0xeeffffff, 0xffffffff,0xffffffff}; + + return (colors[(int)(z * 12 / z_max)]); +} diff --git a/src/fdf_draw.c b/src/fdf_draw.c index 1bd4b56..a8d875c 100644 --- a/src/fdf_draw.c +++ b/src/fdf_draw.c @@ -11,16 +11,25 @@ /* ************************************************************************** */ #include "fdf.h" -bool fdf_put_pixel(mlx_image_t *img, t_point_2d point) +bool fdf_put_pixel(t_fdf *fdf, t_point_2d point) { - if (point.x < 0 || point.x >= (int) img->width - || point.y < 0 || point.y >= (int) img->height) + int color; + + color = 0xFFFFFFFF; + if (point.x < 0 || point.x >= (int) fdf->img->width + || point.y < 0 || point.y >= (int) fdf->img->height) return (false); - mlx_put_pixel(img, point.x, point.y, point.color); + if (fdf->colormode == COLOR_MODE_DEFAULT) + color = point.color; + else if (fdf->colormode == COLOR_MODE_Z) + color = get_z_color(point.orig_z, fdf->map->z_max); + else if (fdf->colormode == COLOR_MODE_GRADIENT) + color = get_gradient_color(point.orig_z, fdf->map->z_max); + mlx_put_pixel(fdf->img, point.x, point.y, color); return (true); } -void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end) +void fdf_draw_line_low(t_fdf *fdf, t_point_2d start, t_point_2d end) { int delta; int yi; @@ -37,7 +46,7 @@ void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end) while (current.x <= end.x) { current.color = interpolate_color(start, end, current); - fdf_put_pixel(img, current); + fdf_put_pixel(fdf, current); if (delta > 0) { current.y += yi; @@ -48,7 +57,7 @@ void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end) } } -void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end) +void fdf_draw_line_high(t_fdf *fdf, t_point_2d start, t_point_2d end) { int delta; int xi; @@ -65,7 +74,7 @@ void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end) while (current.y <= end.y) { current.color = interpolate_color(start, end, current); - fdf_put_pixel(img, current); + fdf_put_pixel(fdf, current); if (delta > 0) { current.x += xi; @@ -76,25 +85,25 @@ void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end) } } -void fdf_draw_line(mlx_image_t *img, t_point_2d start, t_point_2d end) +void fdf_draw_line(t_fdf *fdf, t_point_2d start, t_point_2d end) { - if ((start.x < 0 || start.x >= (int) img->width - || start.y < 0 || start.y >= (int) img->height) - && (end.x < 0 || end.x >= (int) img->width - || end.y < 0 || end.y >= (int) img->height)) + if ((start.x < 0 || start.x >= (int) fdf->img->width + || start.y < 0 || start.y >= (int) fdf->img->height) + && (end.x < 0 || end.x >= (int) fdf->img->width + || end.y < 0 || end.y >= (int) fdf->img->height)) return ; if (abs(end.y - start.y) < abs(end.x - start.x)) { if (start.x > end.x) - fdf_draw_line_low(img, end, start); + fdf_draw_line_low(fdf, end, start); else - fdf_draw_line_low(img, start, end); + fdf_draw_line_low(fdf, start, end); } else { if (start.y > end.y) - fdf_draw_line_high(img, end, start); + fdf_draw_line_high(fdf, end, start); else - fdf_draw_line_high(img, start, end); + fdf_draw_line_high(fdf, start, end); } } diff --git a/src/fdf_hooks.c b/src/fdf_hooks.c index bc21927..f530be9 100644 --- a/src/fdf_hooks.c +++ b/src/fdf_hooks.c @@ -17,6 +17,7 @@ int fdf_hooks(t_fdf *fdf) { mlx_loop_hook(fdf->mlx, draw_hook, fdf); mlx_key_hook(fdf->mlx, key_hook, fdf); + mlx_close_hook(fdf->mlx, close_hook, fdf); mlx_resize_hook(fdf->mlx, resize_hook, fdf); return (1); } @@ -30,7 +31,7 @@ void resize_hook(int width, int height, void *param) fdf = (t_fdf *)param; mlx_delete_image(fdf->mlx, fdf->img); fdf->img = mlx_new_image(fdf->mlx, fdf->mlx->width, fdf->mlx->height); - if (!fdf->img + if (!fdf->img || (mlx_image_to_window(fdf->mlx, fdf->img, 0, 0) < 0) || (mlx_image_to_window(fdf->mlx, fdf->menu, 10, 10) < 0)) exit(1); @@ -57,15 +58,15 @@ void draw_hook(void *param) if (fdf->animate_z) fdf->angle_z += deg2rad(fdf->animate_z); fdf_apply_rotation(fdf); - project_isometric(fdf); + project(fdf); i = 0; while (i < fdf->map->width * fdf->map->height) { - fdf_put_pixel(fdf->img, fdf->map->proj[i]); + fdf_put_pixel(fdf, fdf->map->proj[i]); if (i % fdf->map->width != fdf->map->width - 1) - fdf_draw_line(fdf->img, fdf->map->proj[i], fdf->map->proj[i + 1]); + fdf_draw_line(fdf, fdf->map->proj[i], fdf->map->proj[i + 1]); if (i / fdf->map->width != fdf->map->height - 1) - fdf_draw_line(fdf->img, fdf->map->proj[i], fdf->map->proj[i + fdf->map->width]); + fdf_draw_line(fdf, fdf->map->proj[i], fdf->map->proj[i + fdf->map->width]); i++; } // draw_menu(fdf); @@ -98,16 +99,21 @@ mlx_image_t *draw_menu(t_fdf *fdf) return (img); } +void close_hook(void *param) +{ + mlx_close_window(((t_fdf *)param)->mlx); + mlx_terminate(((t_fdf *)param)->mlx); + clean_fdf((t_fdf *)param); + exit(0); +} + void key_hook(mlx_key_data_t keydata, void *param) { t_fdf *fdf; fdf = (t_fdf *)param; if (keydata.key == MLX_KEY_ESCAPE) - { - mlx_close_window(((t_fdf *)param)->mlx); - exit(0); - } + close_hook(fdf); if (keydata.key == MLX_KEY_A && keydata.action != MLX_RELEASE) fdf->angle_z -= deg2rad(5); if (keydata.key == MLX_KEY_D && keydata.action != MLX_RELEASE) @@ -142,5 +148,9 @@ void key_hook(mlx_key_data_t keydata, void *param) fdf->animate_z += 0.5; if (keydata.key == MLX_KEY_SLASH && keydata.action == MLX_PRESS) fdf->menu->enabled = !fdf->menu->enabled; - -} \ No newline at end of file + if (keydata.key == MLX_KEY_C && keydata.action == MLX_PRESS) + fdf->colormode = (fdf->colormode + 1) % 3; + if (keydata.key == MLX_KEY_P && keydata.action == MLX_PRESS) + fdf->projection = (fdf->projection + 1) % 3; + +} diff --git a/src/init_mlx.c b/src/init_mlx.c index 9edb891..d56665a 100644 --- a/src/init_mlx.c +++ b/src/init_mlx.c @@ -16,7 +16,6 @@ int init_mlx(t_fdf *fdf) { mlx_t *mlx; - printf("init_mlx\n"); mlx = mlx_init(WIDTH, HEIGHT, "FdF", true); if (!mlx) handle_error(fdf, "Error: failed to initialise MLX"); diff --git a/src/initialise_fdf.c b/src/initialise_fdf.c index d3fea6f..2945f12 100644 --- a/src/initialise_fdf.c +++ b/src/initialise_fdf.c @@ -36,6 +36,8 @@ t_fdf *initialise_fdf(void) fdf->z_scale = 0.1; fdf->last_width = WIDTH; fdf->last_height = HEIGHT; + fdf->colormode = COLOR_MODE_DEFAULT; + fdf->projection = PROJECTION_ISOMETRIC; fdf->map->orig = NULL; fdf->map->rot = NULL; fdf->map->proj = NULL; diff --git a/src/parse_map.c b/src/parse_map.c index 0ae6993..3602b4c 100644 --- a/src/parse_map.c +++ b/src/parse_map.c @@ -24,9 +24,8 @@ int parse_map(char *filename, t_fdf *fdf) fdf->map->proj = malloc(map_size * sizeof(t_point_2d)); if (!fdf->map->orig || !fdf->map->rot || !fdf->map->proj) handle_error(fdf, MALLOC_ERROR); - if (!read_map(filename, fdf)) + if (!load_map_from_file(filename, fdf)) handle_error(fdf, "Error: failed to read map"); get_z_max(fdf); - ft_printf("%d\n", fdf->map->z_max); return (SUCCESS); } diff --git a/src/project_isometric.c b/src/project_isometric.c index 4b00d95..ae7711f 100644 --- a/src/project_isometric.c +++ b/src/project_isometric.c @@ -12,6 +12,46 @@ #include "fdf.h" +void project_trimetric(t_fdf *fdf) +{ + int i; + double x; + double y; + + i = 0; + if (fdf->zoom == 0) + fdf->zoom = fmin(fdf->mlx->width / fdf->map->width, + fdf->mlx->height / fdf->map->height) / 2; + while (i < fdf->map->width * fdf->map->height) + { + x = fdf->map->rot[i].x - fdf->map->rot[i].y; + y = fdf->map->rot[i].x + fdf->map->rot[i].y - fdf->map->rot[i].z; + fdf->map->proj[i].x = x * fdf->zoom + fdf->offset_x; + fdf->map->proj[i].y = y * fdf->zoom + fdf->offset_y; + fdf->map->proj[i].orig_z = fdf->map->orig[i].z; + fdf->map->proj[i].color = fdf->map->rot[i].color; + i++; + } +} + +void project_parallel(t_fdf *fdf) +{ + int i; + + i = 0; + if (fdf->zoom == 0) + fdf->zoom = fmin(fdf->mlx->width / fdf->map->width, + fdf->mlx->height / fdf->map->height) / 2; + while (i < fdf->map->width * fdf->map->height) + { + fdf->map->proj[i].x = fdf->map->rot[i].x * fdf->zoom + fdf->offset_x; + fdf->map->proj[i].y = fdf->map->rot[i].y * fdf->zoom + fdf->offset_y; + fdf->map->proj[i].orig_z = fdf->map->orig[i].z; + fdf->map->proj[i].color = fdf->map->orig[i].color; + i++; + } +} + void project_isometric(t_fdf *fdf) { int i; @@ -29,8 +69,18 @@ void project_isometric(t_fdf *fdf) - 2 * fdf->map->rot[i].z) / SQRT6; fdf->map->proj[i].x = x * fdf->zoom + fdf->offset_x; fdf->map->proj[i].y = y * fdf->zoom + fdf->offset_y; - fdf->map->proj[i].color = get_z_color(fdf->map->orig[i].z, fdf->map->z_max); - // fdf->map->proj[i].color = fdf->map->rot[i].color; + fdf->map->proj[i].orig_z = fdf->map->orig[i].z; + fdf->map->proj[i].color = fdf->map->rot[i].color; i++; } } + +void project(t_fdf *fdf) +{ + if (fdf->projection == PROJECTION_ISOMETRIC) + project_isometric(fdf); + else if (fdf->projection == PROJECTION_PARALLEL) + project_parallel(fdf); + else if (fdf->projection == PROJECTION_TRIMETRIC) + project_trimetric(fdf); +} diff --git a/src/read_map.c b/src/read_map_from_file.c similarity index 91% rename from src/read_map.c rename to src/read_map_from_file.c index 8ba8582..3366bc5 100644 --- a/src/read_map.c +++ b/src/read_map_from_file.c @@ -1,7 +1,7 @@ /* ************************************************************************** */ /* */ /* ::: o_ :::::: ::: */ -/* read_map.c :+: / :+::+: :+: */ +/* load_map_from_file.c :+: / :+::+: :+: */ /* +:+ > +:++:+ +:+ */ /* By: whaffman +#+ +:+ +#++#++:++#++ */ /* +#+ +#+#+ +#++#+ +#+ \o/ */ @@ -12,7 +12,7 @@ #include "fdf.h" -int read_map(char *filename, t_fdf *fdf) +int load_map_from_file(char *filename, t_fdf *fdf) { int fd; char *line;