/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* render.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/14 14:55:05 by greg #+# #+# */ /* Updated: 2024/10/15 13:52:35 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" static void calculate_perpwalldist3(int x, double *raydirX, double *raydirY, double *deltadistX, double *deltadistY) { double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1; double dirX; double dirY; double planeX; double planeY; vector_from_rotation(&dirX, &dirY, g_ray.rot, 1); vector_from_rotation(&planeX, &planeY, g_ray.rot + PI / 2, 1); *raydirX = dirX + planeX * ray_direction; *raydirY = dirY + planeY * ray_direction; *deltadistX = (raydirX == 0) ? 1e30 : fabs(1 / *raydirX); *deltadistY = (raydirY == 0) ? 1e30 : fabs(1 / *raydirY); } static void calculate_perpwalldist2(int x, double *sidedistX, double *sidedistY, double *deltadistX, double *deltadistY, int *stepX, int *stepY) { int mapX = (int)g_ray.posX; int mapY = (int)g_ray.posY; double raydirX; double raydirY; calculate_perpwalldist3(x, &raydirX, &raydirY, deltadistX, deltadistY); if (raydirX < 0) { *stepX = -1; *sidedistX = (g_ray.posX - mapX) * *deltadistX; } else { *stepX = 1; *sidedistX = (mapX + 1.0 - g_ray.posX) * *deltadistX; } if (raydirY < 0) { *stepY = -1; *sidedistY = (g_ray.posY - mapY) * *deltadistY; } else { *stepY = 1; *sidedistY = (mapY + 1.0 - g_ray.posY) * *deltadistY; } } /// @brief Calculate the distance of the wall perpendicularly to the camera /// plane. /// /// @param x Ray direction x between 0 and 1. /// @return Result. static double calculate_perpwalldist(int x) { int mapX = (int)g_ray.posX; int mapY = (int)g_ray.posY; bool side; double sidedistX; double sidedistY; double deltadistX; double deltadistY; int stepX; int stepY; calculate_perpwalldist2(x, &sidedistX, &sidedistY, &deltadistX, &deltadistY, &stepX, &stepY); while(worldMap[mapX][mapY] != 1) { // jump to next map square, either in x-direction, or in y-direction if(sidedistX < sidedistY) { sidedistX += deltadistX; mapX += stepX; side = false; } else { sidedistY += deltadistY; mapY += stepY; side = true; } } double perpwalldist; if(!side) perpwalldist = (sidedistX - deltadistX); else perpwalldist = (sidedistY - deltadistY); return (perpwalldist); } /// @brief Draw a vertical line according to the ray direction x. /// /// @param x Ray direction x between 0 and 1. static void draw_vertical_line(int x, u_int32_t *img_data) { double perpwalldist = calculate_perpwalldist(x); int lineHeight = (int)(SCREEN_HEIGHT / perpwalldist); int drawStart = -lineHeight / 2 + SCREEN_HEIGHT / 2; if(drawStart < 0) drawStart = 0; int drawEnd = lineHeight / 2 + SCREEN_HEIGHT / 2; if(drawEnd >= SCREEN_HEIGHT) drawEnd = SCREEN_HEIGHT - 1; int y = 0; while (y < drawStart) { img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING; y++; } while (y < drawEnd) { img_data[y * SCREEN_WIDTH + x] = COLOR_WALL; y++; } while (y < SCREEN_HEIGHT) { img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR; y++; } } int render(u_int32_t *img_data) { int x; // px // clear image data ft_bzero(img_data, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(int)); // TODO why // 1 double dirX, dirY, planeX, planeY; vector_from_rotation(&dirX, &dirY, g_ray.rot, 1); vector_from_rotation(&planeX, &planeY, g_ray.rot + PI/2, FOV); x = 0; while (x < SCREEN_WIDTH) { draw_vertical_line(x, img_data); x++; } return (0); }