42_cub3d/src/render.c
mcolonna 26621c72c6 docs, clean, several things... *
- add docs
- remove unused things
- redo modifications i accidentally erased from spacetime
2024-11-07 01:03:05 +01:00

153 lines
4.2 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mc <mc@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/10/14 14:55:05 by greg #+# #+# */
/* Updated: 2024/11/07 00:54:17 by mc ### ########.fr */
/* */
/* ************************************************************************** */
#include "render.h"
#include "render_utils.h"
static void calculate_perpwalldist3(int x,
t_point_double *deltadist,
t_ray *ray)
{
const double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1;
t_point_double plane;
t_point_double dir;
vector_from_rotation(&dir, g_map.player.rot, 1);
vector_from_rotation(&plane, g_map.player.rot + PI / 2, 1);
ray->dir.x = dir.x + plane.x * ray_direction;
ray->dir.y = dir.y + plane.y * ray_direction;
deltadist->x = 1e30;
if (ray->dir.x != 0)
deltadist->x = fabs(1 / ray->dir.x);
deltadist->y = 1e30;
if (ray->dir.y != 0)
deltadist->y = fabs(1 / ray->dir.y);
}
static void calculate_perpwalldist2(int x,
t_point_double *sidedist,
t_point_double *deltadist,
t_point_int *step,
t_ray *ray)
{
const int map_x = (int)g_map.player.pos.x;
const int map_y = (int)g_map.player.pos.y;
calculate_perpwalldist3(x, deltadist, ray);
if (ray->dir.x < 0)
{
step->x = -1;
sidedist->x = (g_map.player.pos.x - map_x) * deltadist->x;
}
else
{
step->x = 1;
sidedist->x = (map_x + 1.0 - g_map.player.pos.x) * deltadist->x;
}
if (ray->dir.y < 0)
{
step->y = -1;
sidedist->y = (g_map.player.pos.y - map_y) * deltadist->y;
}
else
{
step->y = 1;
sidedist->y = (map_y + 1.0 - g_map.player.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_ray *ray)
{
t_point_int map_pos;
t_point_double sidedist;
t_point_double deltadist;
t_point_int step;
map_pos.x = (int)g_map.player.pos.x;
map_pos.y = (int)g_map.player.pos.y;
calculate_perpwalldist2(x, &sidedist, &deltadist, &step, ray);
while (map_get_case(&g_map, map_pos.x, map_pos.y)->wall == EMPTY)
{
if (sidedist.x < sidedist.y)
{
sidedist.x += deltadist.x;
map_pos.x += step.x;
ray->side = false;
continue ;
}
sidedist.y += deltadist.y;
map_pos.y += step.y;
ray->side = true;
}
if (!ray->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,
t_ray *ray, t_tex *tex)
{
const double perpwalldist = calculate_perpwalldist(x, ray);
const int line_height = (int)(SCREEN_HEIGHT / perpwalldist);
int draw_start;
int draw_end;
int y;
ft_init_texture(perpwalldist, ray, tex);
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)
{
draw_wall(tex, ray, line_height, x, y, img_data);
}
else
img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR;
}
}
int render(u_int32_t *img_data)
{
int x;
t_ray ray;
t_tex tex;
tex.tex_width = 64; // TODO fix
tex.tex_height = 64; // TODO fix
tex.textures[NORTH] = g_map.textures[NORTH].image;
tex.textures[SOUTH] = g_map.textures[SOUTH].image;
tex.textures[WEST] = g_map.textures[WEST].image;
tex.textures[EAST] = g_map.textures[EAST].image;
x = 0;
while (x < SCREEN_WIDTH)
{
draw_vertical_line(x, img_data, &ray, &tex);
x++;
}
return (0);
}