157 lines
4.1 KiB
C
157 lines
4.1 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* render.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* 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);
|
|
}
|