From 2a1e5b53e592fd8db4e3ee43831884214f4305db Mon Sep 17 00:00:00 2001 From: whaffman Date: Wed, 11 Dec 2024 20:07:29 +0100 Subject: [PATCH] handle errors more yes animations and color parse and interpolate --- inc/fdf.h | 13 +++++- lib/libft | 2 +- src/fdf.c | 94 +++++++++++++++++++++++--------------------- src/fdf_color.c | 51 ++++++++++++++++++++++++ src/fdf_draw.c | 9 +++++ src/fdf_hooks.c | 63 ++++++++++++++++++++++++----- src/fdf_rotations.c | 3 +- valgrind-supressions | 16 ++++++++ 8 files changed, 193 insertions(+), 58 deletions(-) create mode 100644 src/fdf_color.c create mode 100644 valgrind-supressions diff --git a/inc/fdf.h b/inc/fdf.h index a8c7bc9..bf5f9c0 100644 --- a/inc/fdf.h +++ b/inc/fdf.h @@ -19,6 +19,7 @@ # include # include # include +# include # include "libft.h" # include "MLX42.h" @@ -74,19 +75,25 @@ typedef struct s_fdf 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_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_map *map); +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); void rotate_x(t_point_3d **points, double angle, int size); void rotate_y(t_point_3d **points, double angle, int size); @@ -95,10 +102,12 @@ 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 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 fdf_project_isometric(t_map *map); +void fdf_project_isometric(t_fdf *fdf); double deg2rad(double deg); diff --git a/lib/libft b/lib/libft index a6830f9..27f7d3e 160000 --- a/lib/libft +++ b/lib/libft @@ -1 +1 @@ -Subproject commit a6830f9b33e2f87a7675ff193a2879c816c55693 +Subproject commit 27f7d3e9e02cccf7092f3101b939d381198a595b diff --git a/src/fdf.c b/src/fdf.c index b345ecd..888de8f 100644 --- a/src/fdf.c +++ b/src/fdf.c @@ -54,7 +54,7 @@ void free_line_and_split(char **line, char ***split) *split = NULL; } -int read_map(char *filename, t_map *map) +int read_map(char *filename, t_fdf *fdf) { int fd; char *line; @@ -65,8 +65,8 @@ int read_map(char *filename, t_map *map) fd = open(filename, O_RDONLY); if (fd < 0) - return (ft_printf(FILE_ERROR, filename), 0); - y = map->height - 1; + handle_error(NULL, FILE_ERROR); + y = fdf->map->height - 1; while (true) { x = 0; @@ -76,10 +76,10 @@ int read_map(char *filename, t_map *map) split = ft_split(line, ' '); while (split[x]) { - map->original[y * map->width + x].x = x - map->width / 2; - map->original[y * map->width + x].y = map->height / 2 - y; - map->original[y * map->width + x].z = ft_atoi(split[x]); - map->original[y * map->width + x].color = 0xFFFFFFFF; + fdf->map->original[y * fdf->map->width + x].x = x - fdf->map->width / 2; + fdf->map->original[y * fdf->map->width + x].y = fdf->map->height / 2 - y; + fdf->map->original[y * fdf->map->width + x].z = ft_atoi(split[x]); + fdf->map->original[y * fdf->map->width + x].color = get_color(split[x]); x++; } free_line_and_split(&line, &split); @@ -92,15 +92,15 @@ int read_map(char *filename, t_map *map) int parse_map(char *filename, t_fdf *fdf) { if (!get_map_sizes(filename, fdf->map)) - return (FAILURE); + handle_error(fdf, "Error: failed to get map sizes"); fdf->map->original = malloc(fdf->map->width * fdf->map->height * sizeof(t_point_3d)); fdf->map->rotated = malloc(fdf->map->width * fdf->map->height * sizeof(t_point_3d)); fdf->map->projected = malloc(fdf->map->width * fdf->map->height * sizeof(t_point_2d)); if (!fdf->map->original || !fdf->map->rotated || !fdf->map->projected) - return (FAILURE); - if (!read_map(filename, fdf->map)) - return (FAILURE); - + handle_error(fdf, MALLOC_ERROR); + if (!read_map(filename, fdf)) + handle_error(fdf, "Error: failed to read map"); + return (SUCCESS); } void fdf_set_background(mlx_image_t *img, int color) @@ -121,24 +121,22 @@ void fdf_set_background(mlx_image_t *img, int color) } } -void fdf_project_isometric(t_map *map) +void fdf_project_isometric(t_fdf *fdf) { int i; double x; double y; - const int scale = fmax(map->height, map->width) * SQRT2; i = 0; - map->projected = malloc(map->width * map->height * sizeof(t_point_2d)); - if (!map->projected) - return ; - while (i < map->width * map->height) + if(fdf->zoom == 0) + fdf->zoom = fmin(fdf->mlx->width / fdf->map->width, fdf->mlx->height / fdf->map->height) / SQRT2; + while (i < fdf->map->width * fdf->map->height) { - x = (map->rotated[i].x - map->rotated[i].y) / SQRT2; - y = (map->rotated[i].x + map->rotated[i].y - 2 * map->rotated[i].z) / SQRT6; - map->projected[i].x = x * WIDTH / scale + WIDTH / 2; - map->projected[i].y = y * HEIGHT / scale + HEIGHT / 2; - map->projected[i].color = map->rotated[i].color; + x = (fdf->map->rotated[i].x - fdf->map->rotated[i].y) / SQRT2; + y = (fdf->map->rotated[i].x + fdf->map->rotated[i].y - 2 * fdf->map->rotated[i].z) / SQRT6; + fdf->map->projected[i].x = x * fdf->zoom + fdf->offset_x; + fdf->map->projected[i].y = y * fdf->zoom + fdf->offset_y; + fdf->map->projected[i].color = fdf->map->rotated[i].color; i++; } } @@ -157,15 +155,13 @@ int init_mlx(t_fdf *fdf) mlx_t *mlx; printf("init_mlx\n"); - mlx = mlx_init(WIDTH, HEIGHT, "FdF", false); + mlx = mlx_init(WIDTH, HEIGHT, "FdF", true); if (!mlx) - return (printf("mlx_init failed\n"), FAILURE); - printf("mlx: %p\n", mlx); + handle_error(fdf, "Error: failed to initialise MLX"); fdf->mlx = mlx; fdf->img = mlx_new_image(fdf->mlx, fdf->mlx->width, fdf->mlx->height); if (!fdf->img || (mlx_image_to_window(fdf->mlx, fdf->img, 0, 0) < 0)) - return (FAILURE); - printf("img: %p\n", fdf->img); + handle_error(fdf, "Error: failed to create image"); fdf_hooks(fdf); return (SUCCESS); } @@ -177,20 +173,22 @@ t_fdf *initialise_fdf() fdf = malloc(sizeof(t_fdf)); if (!fdf) - return (ft_printf(MALLOC_ERROR), NULL); + handle_error(fdf, MALLOC_ERROR); map = malloc(sizeof(t_map)); if (!map) - return (ft_printf(MALLOC_ERROR), NULL); + handle_error(fdf, MALLOC_ERROR); fdf->map = map; fdf->mlx = NULL; fdf->img = NULL; fdf->angle_x = 0; fdf->angle_y = 0; fdf->angle_z = 0; - fdf->zoom = 1; - fdf->offset_x = 0; - fdf->offset_y = 0; - fdf->z_scale = 1; + fdf->zoom = 0; + fdf->offset_x = WIDTH / 2; + fdf->offset_y = HEIGHT / 2; + fdf->z_scale = 0.1; + fdf->last_width = WIDTH; + fdf->last_height = HEIGHT; fdf->map->original = NULL; fdf->map->rotated = NULL; fdf->map->projected = NULL; @@ -198,7 +196,7 @@ t_fdf *initialise_fdf() fdf->map->height = 0; fdf->map->z_max = 0; - + return (fdf); } @@ -211,27 +209,33 @@ bool clean_fdf(t_fdf *fdf) free(fdf->map->projected); free(fdf->map); } + free(fdf); return (true); } +void handle_error(t_fdf *fdf, char *error) +{ + if (errno) + perror(error); + if (mlx_errno) + ft_putendl_fd(mlx_strerror(mlx_errno), 2); + ft_putendl_fd(error , 2); + clean_fdf(fdf); + exit(1); +} + + int main(int argc, char *argv[]) { t_fdf *fdf; fdf = initialise_fdf(); if (argc != 2) - { - ft_printf(USAGE_ERROR, argv[0]); - return (EXIT_FAILURE); - } + handle_error(fdf, "Usage: ./fdf "); if (!parse_map(argv[1], fdf)) - return (EXIT_FAILURE); - + handle_error(fdf, "Error: failed to parse map"); init_mlx(fdf); - printf("fdf: %p\n", fdf); - mlx_loop(fdf->mlx); - - + mlx_loop(fdf->mlx); mlx_terminate(fdf->mlx); clean_fdf(fdf); return (EXIT_SUCCESS); diff --git a/src/fdf_color.c b/src/fdf_color.c new file mode 100644 index 0000000..092427a --- /dev/null +++ b/src/fdf_color.c @@ -0,0 +1,51 @@ +#include "fdf.h" + +int get_color(char *str) +{ + int color; + int i; + + color = 0; + i = 0; + while (str[i] && ft_isdigit(str[i])) + i++; + i++; + if (str[i] == '0' && str[i + 1] == 'x') + i += 2; + while (str[i]) + { + if (ft_isdigit(str[i])) + color = color * 16 + str[i] - '0'; + else if (str[i] >= 'a' && str[i] <= 'f') + color = color * 16 + str[i] - 'a' + 10; + else if (str[i] >= 'A' && str[i] <= 'F') + color = color * 16 + str[i] - 'A' + 10; + else + break ; + i++; + } + if(color == 0) + return (0xFFFFFFFF); + return ((color << 8) + 0xFF); +} +int interpolate_color(t_point_2d start, t_point_2d end, t_point_2d current) +{ + int delta_current; + int delta_total; + int red; + int green; + int blue; + + delta_current = fmax(abs(current.x - start.x), abs(current.y - start.y)); + delta_total = fmax(abs(end.x - start.x), abs(end.y - start.y)); + if (delta_total == 0) + return (start.color); + red = (int) ((1 - (double) delta_current / delta_total) * (start.color >> 24 & 0xFF) + + (double) delta_current / delta_total * (end.color >> 24 & 0xFF)); + green = (int) ((1 - (double) delta_current / delta_total) * (start.color >> 16 & 0xFF) + + (double) delta_current / delta_total * (end.color >> 16 & 0xFF)); + blue = (int) ((1 - (double) delta_current / delta_total) * (start.color >> 8 & 0xFF) + + (double) delta_current / delta_total * (end.color >> 8 & 0xFF)); + return (red << 24 | green << 16 | blue << 8 | 0xFF); +} + diff --git a/src/fdf_draw.c b/src/fdf_draw.c index 62b34e8..28745af 100644 --- a/src/fdf_draw.c +++ b/src/fdf_draw.c @@ -39,6 +39,7 @@ void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end) current = start; while (current.x <= end.x) { + current.color = interpolate_color(start, end, current); fdf_put_pixel(img, current); if (delta > 0) { @@ -69,6 +70,7 @@ void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end) current = start; while (current.y <= end.y) { + current.color = interpolate_color(start, end, current); fdf_put_pixel(img, current); if (delta > 0) { @@ -82,6 +84,11 @@ 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) { + 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)) + return ; if (abs(end.y - start.y) < abs(end.x - start.x)) { if (start.x > end.x) @@ -97,3 +104,5 @@ void fdf_draw_line(mlx_image_t *img, t_point_2d start, t_point_2d end) fdf_draw_line_high(img, start, end); } } + + diff --git a/src/fdf_hooks.c b/src/fdf_hooks.c index 775cde6..bdc3659 100644 --- a/src/fdf_hooks.c +++ b/src/fdf_hooks.c @@ -5,22 +5,43 @@ int fdf_hooks(t_fdf *fdf) { mlx_loop_hook(fdf->mlx, draw_hook, fdf); mlx_key_hook(fdf->mlx, key_hook, fdf); - printf("hooks set\n"); + mlx_resize_hook(fdf->mlx, resize_hook, fdf); return (1); } +void resize_hook(int width, int height, void *param) +{ + t_fdf *fdf; + (void)width; + (void)height; + 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 || (mlx_image_to_window(fdf->mlx, fdf->img, 0, 0) < 0)) + exit(1); + fdf->offset_x += (fdf->mlx->width - fdf->last_width ) / 2 ; + fdf->offset_y += (fdf->mlx->height - fdf->last_height) / 2; + fdf->zoom = 0; + fdf->last_height = fdf->mlx->height; + fdf->last_width = fdf->mlx->width; +} void draw_hook(void *param) { t_fdf *fdf; int i; + fdf = (t_fdf *)param; + if (fdf->last_width != fdf->mlx->width || fdf->last_height != fdf->mlx->height) + { + resize_hook(fdf->mlx->width, fdf->mlx->height, fdf); + return ; + } fdf_set_background(fdf->img, 0x000000FF); - printf("background set\n"); + if (fdf->animate_z) + fdf->angle_z += deg2rad(fdf->animate_z); fdf_apply_rotation(fdf); - printf("rotation applied\n"); - fdf_project_isometric(fdf->map); - printf("projection applied\n"); + fdf_project_isometric(fdf); i = 0; while (i < fdf->map->width * fdf->map->height) { @@ -42,12 +63,36 @@ void key_hook(mlx_key_data_t keydata, void *param) mlx_close_window(((t_fdf *)param)->mlx); exit(0); } - if (keydata.key == MLX_KEY_LEFT && keydata.action == MLX_PRESS) + if (keydata.key == MLX_KEY_A && keydata.action != MLX_RELEASE) fdf->angle_z -= deg2rad(5); - if (keydata.key == MLX_KEY_RIGHT && keydata.action == MLX_PRESS) + if (keydata.key == MLX_KEY_D && keydata.action != MLX_RELEASE) fdf->angle_z += deg2rad(5); - if (keydata.key == MLX_KEY_UP && keydata.action == MLX_PRESS) + if (keydata.key == MLX_KEY_W && keydata.action != MLX_RELEASE) fdf->angle_x -= deg2rad(5); - if (keydata.key == MLX_KEY_DOWN && keydata.action == MLX_PRESS) + if (keydata.key == MLX_KEY_S && keydata.action != MLX_RELEASE) fdf->angle_x += deg2rad(5); + if (keydata.key == MLX_KEY_Q && keydata.action != MLX_RELEASE) + fdf->angle_y -= deg2rad(5); + if (keydata.key == MLX_KEY_E && keydata.action != MLX_RELEASE) + fdf->angle_y += deg2rad(5); + if (keydata.key == MLX_KEY_X && keydata.action != MLX_RELEASE) + fdf->z_scale *= 1.05; + if (keydata.key == MLX_KEY_Z && keydata.action != MLX_RELEASE) + fdf->z_scale /= 1.05; + if (keydata.key == MLX_KEY_UP && keydata.action != MLX_RELEASE) + fdf->offset_y -= 10; + if (keydata.key == MLX_KEY_DOWN && keydata.action != MLX_RELEASE) + fdf->offset_y += 10; + if (keydata.key == MLX_KEY_LEFT && keydata.action != MLX_RELEASE) + fdf->offset_x -= 10; + if (keydata.key == MLX_KEY_RIGHT && keydata.action != MLX_RELEASE) + fdf->offset_x += 10; + if (keydata.key == MLX_KEY_EQUAL && keydata.action != MLX_RELEASE) + fdf->zoom += 1; + if (keydata.key == MLX_KEY_MINUS && keydata.action != MLX_RELEASE) + fdf->zoom *= 1.1; + if (keydata.key == MLX_KEY_LEFT_BRACKET && keydata.action == MLX_PRESS) + fdf->animate_z /= 1.1; + if (keydata.key == MLX_KEY_RIGHT_BRACKET && keydata.action == MLX_PRESS) + fdf->animate_z += 1; } diff --git a/src/fdf_rotations.c b/src/fdf_rotations.c index 6db3e07..3307794 100644 --- a/src/fdf_rotations.c +++ b/src/fdf_rotations.c @@ -1,7 +1,7 @@ #include "fdf.h" void fdf_apply_rotation(t_fdf *fdf) -{ +{ copy_map(fdf); rotate_x(&fdf->map->rotated, fdf->angle_x, fdf->map->width * fdf->map->height); rotate_y(&fdf->map->rotated, fdf->angle_y, fdf->map->width * fdf->map->height); @@ -18,6 +18,7 @@ void copy_map(t_fdf *fdf) fdf->map->rotated[i].x = fdf->map->original[i].x; fdf->map->rotated[i].y = fdf->map->original[i].y; fdf->map->rotated[i].z = fdf->map->original[i].z * fdf->z_scale; + fdf->map->rotated[i].color = fdf->map->original[i].color; i++; } } diff --git a/valgrind-supressions b/valgrind-supressions new file mode 100644 index 0000000..07b24ec --- /dev/null +++ b/valgrind-supressions @@ -0,0 +1,16 @@ +{ + ignore_unversioned_libs + Memcheck:Leak + obj:*.so +} +{ + ignore_versioned_libs + Memcheck:Leak + obj:*.so.* +} +{ + + Memcheck:Leak + match-leak-kinds: possible + obj:/usr/lib/x86_64-linux-gnu/dri/radeonsi_dri.so +}