141 lines
3.7 KiB
C
141 lines
3.7 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* render.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2024/10/14 14:55:05 by greg #+# #+# */
|
|
/* Updated: 2024/10/15 15:59:55 by mcolonna ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "algo.h"
|
|
|
|
static void calculate_perpwalldist3(int x,
|
|
t_point_double *raydir, t_point_double *deltadist)
|
|
{
|
|
const double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1;
|
|
t_point_double plane;
|
|
t_point_double dir;
|
|
|
|
vector_from_rotation(&dir, g_ray.rot, 1);
|
|
vector_from_rotation(&plane, g_ray.rot + PI / 2, 1);
|
|
raydir->x = dir.x + plane.x * ray_direction;
|
|
raydir->y = dir.y + plane.y * ray_direction;
|
|
deltadist->x = 1e30;
|
|
if (raydir->x != 0)
|
|
deltadist->x = fabs(1 / raydir->x);
|
|
deltadist->y = 1e30;
|
|
if (raydir->y != 0)
|
|
deltadist->y = fabs(1 / raydir->y);
|
|
}
|
|
|
|
static void calculate_perpwalldist2(int x,
|
|
t_point_double *sidedist,
|
|
t_point_double *deltadist,
|
|
t_point_int *step)
|
|
{
|
|
const int map_x = (int)g_ray.pos.x;
|
|
const int map_y = (int)g_ray.pos.y;
|
|
t_point_double raydir;
|
|
|
|
calculate_perpwalldist3(x, &raydir, deltadist);
|
|
if (raydir.x < 0)
|
|
{
|
|
step->x = -1;
|
|
sidedist->x = (g_ray.pos.x - map_x) * deltadist->x;
|
|
}
|
|
else
|
|
{
|
|
step->x = 1;
|
|
sidedist->x = (map_x + 1.0 - g_ray.pos.x) * deltadist->x;
|
|
}
|
|
if (raydir.y < 0)
|
|
{
|
|
step->y = -1;
|
|
sidedist->y = (g_ray.pos.y - map_y) * deltadist->y;
|
|
}
|
|
else
|
|
{
|
|
step->y = 1;
|
|
sidedist->y = (map_y + 1.0 - g_ray.pos.y) * deltadist->y;
|
|
}
|
|
}
|
|
|
|
/// @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)
|
|
{
|
|
t_point_int map_pos;
|
|
bool side;
|
|
t_point_double sidedist;
|
|
t_point_double deltadist;
|
|
t_point_int step;
|
|
|
|
map_pos.x = (int)g_ray.pos.x;
|
|
map_pos.y = (int)g_ray.pos.y;
|
|
calculate_perpwalldist2(x, &sidedist, &deltadist, &step);
|
|
while (g_world_map[map_pos.x][map_pos.y] != 1)
|
|
{
|
|
if (sidedist.x < sidedist.y)
|
|
{
|
|
sidedist.x += deltadist.x;
|
|
map_pos.x += step.x;
|
|
side = false;
|
|
continue ;
|
|
}
|
|
sidedist.y += deltadist.y;
|
|
map_pos.y += step.y;
|
|
side = true;
|
|
}
|
|
if (!side)
|
|
return (sidedist.x - deltadist.x);
|
|
return (sidedist.y - deltadist.y);
|
|
}
|
|
|
|
/// @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)
|
|
{
|
|
const double perpwalldist = calculate_perpwalldist(x);
|
|
const int line_height = (int)(SCREEN_HEIGHT / perpwalldist);
|
|
int draw_start;
|
|
int draw_end;
|
|
int y;
|
|
|
|
draw_start = -line_height / 2 + SCREEN_HEIGHT / 2;
|
|
if (draw_start < 0)
|
|
draw_start = 0;
|
|
draw_end = line_height / 2 + SCREEN_HEIGHT / 2;
|
|
if (draw_end >= SCREEN_HEIGHT)
|
|
draw_end = SCREEN_HEIGHT - 1;
|
|
y = 0;
|
|
while (y < SCREEN_HEIGHT)
|
|
{
|
|
if (y < draw_start)
|
|
img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING;
|
|
else if (y < draw_end)
|
|
img_data[y * SCREEN_WIDTH + x] = COLOR_WALL;
|
|
else
|
|
img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR;
|
|
y++;
|
|
}
|
|
}
|
|
|
|
int render(u_int32_t *img_data)
|
|
{
|
|
int x;
|
|
|
|
x = 0;
|
|
while (x < SCREEN_WIDTH)
|
|
{
|
|
draw_vertical_line(x, img_data);
|
|
x++;
|
|
}
|
|
return (0);
|
|
}
|