/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* render.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: mcolonna +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/15 12:40:52 by mcolonna #+# #+# */ /* Updated: 2024/10/15 12:51:25 by mcolonna ### ########.fr */ /* */ /* ************************************************************************** */ #include "algo.h" 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) { // case player on map (cases) int mapX = (int)g_ray.posX; // case player on map (cases) int mapY = (int)g_ray.posY; // vector ray direction (1) double raydirX, raydirY; { // ray direction in [-1;+1]. the highter the more to the right (1) double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1; raydirX = dirX + planeX * ray_direction; raydirY = dirY + planeY * ray_direction; } // longueur du rayon dans une même colonne de cases (cases) double deltadistX = (raydirX == 0) ? 1e30 : fabs(1 / raydirX); // longueur du rayon dans une même ligne de cases (cases) double deltadistY = (raydirY == 0) ? 1e30 : fabs(1 / raydirY); // longueur du rayon entre pos actuelle et pos du prochain coté ouest ou est d'une box double sidedistX; // longueur du rayon entre pos actuelle et pos du prochain coté nord ou sub d'une box double sidedistY; // direction du rayon sur x (+1 or -1) int stepX; // direction du rayon sur y (+1 or -1) int stepY; 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; } bool hit = false; bool side; while(!hit) { // 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; } // check if ray has hit a wall if(worldMap[mapX][mapY] == 1) hit = true; } // calcul lenght of ray (shortest perpendicular distance between wall and camera plane) (1) double perpwalldist; if(!side) perpwalldist = (sidedistX - deltadistX); else perpwalldist = (sidedistY - deltadistY); // calculate height of line to draw on screen (px) int lineHeight = (int)(SCREEN_HEIGHT / perpwalldist); // calculate lowest and highest pixel to fill in current stripe 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; // draw vertical line 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++; } x++; } return (0); }