243 lines
5.5 KiB
C
243 lines
5.5 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: o_ :::::: ::: */
|
|
/* fdf.c :+: / :+::+: :+: */
|
|
/* +:+ > +:++:+ +:+ */
|
|
/* By: whaffman <whaffman@student.codam.nl> +#+ +:+ +#++#++:++#++ */
|
|
/* +#+ +#+#+ +#++#+ +#+ \o/ */
|
|
/* Created: 2024/12/06 11:07:30 by whaffman #+#+# #+#+# #+# #+# | */
|
|
/* Updated: 2024/12/06 11:19:30 by whaffman ### ### ### ### / \ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "fdf.h"
|
|
|
|
int get_map_sizes(char *filename, t_map *map)
|
|
{
|
|
const int fd = open(filename, O_RDONLY);
|
|
char *line;
|
|
int width;
|
|
|
|
if (fd < 0)
|
|
return (ft_printf(FILE_ERROR, filename), 0);
|
|
width = 0;
|
|
while (true)
|
|
{
|
|
line = get_next_line(fd);
|
|
if (!line)
|
|
break ;
|
|
width = ft_count_words(line, ' ');
|
|
free(line);
|
|
if (map->width != 0 && map->width != width)
|
|
return (ft_printf(WRONG_LINE_LENGTH, map->width, width, map->height), 0);
|
|
else if (map->width == 0)
|
|
map->width = width;
|
|
map->height++;
|
|
}
|
|
return (close(fd), 1);
|
|
}
|
|
|
|
void free_line_and_split(char **line, char ***split)
|
|
{
|
|
char **split_start;
|
|
|
|
split_start = *split;
|
|
free(*line);
|
|
*line = NULL;
|
|
while (**split)
|
|
{
|
|
free(**split);
|
|
**split = NULL;
|
|
(*split)++;
|
|
}
|
|
free(split_start);
|
|
*split = NULL;
|
|
}
|
|
|
|
int read_map(char *filename, t_fdf *fdf)
|
|
{
|
|
int fd;
|
|
char *line;
|
|
int y;
|
|
int x;
|
|
char **split;
|
|
|
|
|
|
fd = open(filename, O_RDONLY);
|
|
if (fd < 0)
|
|
handle_error(NULL, FILE_ERROR);
|
|
y = fdf->map->height - 1;
|
|
while (true)
|
|
{
|
|
x = 0;
|
|
line = get_next_line(fd);
|
|
if (!line)
|
|
break ;
|
|
split = ft_split(line, ' ');
|
|
while (split[x])
|
|
{
|
|
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);
|
|
y--;
|
|
}
|
|
close(fd);
|
|
return (1);
|
|
}
|
|
|
|
int parse_map(char *filename, t_fdf *fdf)
|
|
{
|
|
if (!get_map_sizes(filename, fdf->map))
|
|
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)
|
|
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)
|
|
{
|
|
int x;
|
|
int y;
|
|
|
|
y = 0;
|
|
while (y < (int) img->height)
|
|
{
|
|
x = 0;
|
|
while (x < (int) img->width)
|
|
{
|
|
mlx_put_pixel(img, x, y, color);
|
|
x++;
|
|
}
|
|
y++;
|
|
}
|
|
}
|
|
|
|
void fdf_project_isometric(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) / SQRT2;
|
|
while (i < fdf->map->width * fdf->map->height)
|
|
{
|
|
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++;
|
|
}
|
|
}
|
|
|
|
|
|
double deg2rad(double deg)
|
|
{
|
|
return (deg / 180.0 * M_PI);
|
|
}
|
|
|
|
|
|
|
|
|
|
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");
|
|
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))
|
|
handle_error(fdf, "Error: failed to create image");
|
|
fdf_hooks(fdf);
|
|
return (SUCCESS);
|
|
}
|
|
|
|
t_fdf *initialise_fdf()
|
|
{
|
|
t_map *map;
|
|
t_fdf *fdf;
|
|
|
|
fdf = malloc(sizeof(t_fdf));
|
|
if (!fdf)
|
|
handle_error(fdf, MALLOC_ERROR);
|
|
map = malloc(sizeof(t_map));
|
|
if (!map)
|
|
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 = 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;
|
|
fdf->map->width = 0;
|
|
fdf->map->height = 0;
|
|
fdf->map->z_max = 0;
|
|
|
|
|
|
return (fdf);
|
|
}
|
|
|
|
bool clean_fdf(t_fdf *fdf)
|
|
{
|
|
if (fdf->map)
|
|
{
|
|
free(fdf->map->original);
|
|
free(fdf->map->rotated);
|
|
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)
|
|
handle_error(fdf, "Usage: ./fdf <filename>");
|
|
if (!parse_map(argv[1], fdf))
|
|
handle_error(fdf, "Error: failed to parse map");
|
|
init_mlx(fdf);
|
|
mlx_loop(fdf->mlx);
|
|
mlx_terminate(fdf->mlx);
|
|
clean_fdf(fdf);
|
|
return (EXIT_SUCCESS);
|
|
}
|