cub3d/src/render/render_walls.c

121 lines
3.6 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* render_walls.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: qmennen <qmennen@student.codam.nl> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/05/14 13:05:28 by whaffman #+# #+# */
/* Updated: 2025/06/10 14:45:19 by qmennen ### ########.fr */
/* */
/* ************************************************************************** */
#include "cub3d.h"
t_side get_side(t_render *render, t_vec2 ray_dir, double perp_dist)
{
if (render->door)
return (SIDE_DOOR);
if (perp_dist > 0)
{
if (ray_dir.x > 0)
return (SIDE_WEST);
else
return (SIDE_EAST);
}
else
{
if (ray_dir.y > 0)
return (SIDE_NORTH);
else
return (SIDE_SOUTH);
}
}
t_render cast_ray(t_game *game, int x)
{
t_vec2 ray_dir;
t_vec2 pos;
t_render render;
double perp_dist;
render.door = 0;
render.sign = 1;
ray_dir = add(game->player->dir,
mul(game->player->camera,
(2.0f * x / (double)game->screen->width - 1)));
pos = game->player->pos;
perp_dist = dda(&render, ray_dir, pos, game->map);
render.perp_dist = fabs(perp_dist);
render.side = get_side(&render, ray_dir, perp_dist);
if (perp_dist < 0)
render.wall_x = pos.x + ray_dir.x * render.perp_dist;
else
render.wall_x = pos.y + ray_dir.y * render.perp_dist;
render.wall_x -= floor(render.wall_x);
return (render);
}
unsigned int get_texture_color(mlx_texture_t *texture,
t_render render, t_vec2_int tex)
{
int index;
double dist;
if (tex.x < 0)
tex.x = 0;
if (tex.y < 0)
tex.y = 0;
index = (tex.x + tex.y * texture->height) * texture->bytes_per_pixel;
dist = (render.perp_dist == 0) * 1e30
+ (render.perp_dist > 1) * render.perp_dist
+ (render.perp_dist <= 1) * 1;
return ((unsigned int)texture->pixels[index] << 24
| (unsigned int)texture->pixels[index + 1] << 16
| (unsigned int)texture->pixels[index + 2] << 8
| (int)(1.0 / dist * 255));
}
static int set_range(t_game *game, t_render render, t_range *range, int height)
{
int tex_start;
height = game->screen->height / render.perp_dist;
range->start = game->screen->height / 2 - height / 2;
tex_start = range->start;
range->start = (range->start > 0) * range->start;
range->end = height / 2 + game->screen->height / 2;
if (range->end >= (int) game->screen->height)
range->end = game->screen->height - 1;
return (tex_start);
}
void draw_line(t_game *game, t_render render, int x)
{
int color;
int height;
int tex_start;
t_vec2_int tex;
t_range range;
height = game->screen->height / render.perp_dist;
tex_start = set_range(game, render, &range, height);
tex.x = render.wall_x * game->map->textures[render.side]->width;
if (render.side == SIDE_NORTH || render.side == SIDE_EAST)
tex.x = game->map->textures[render.side]->width - tex.x - 1;
while (range.start < range.end)
{
tex.y = (range.start - tex_start);
tex.y *= ((double)game->map->textures[render.side]->height / height);
color = get_texture_color(game->map->textures[render.side],
render, tex);
if (x < 0
|| x >= (int) game->screen->width
|| range.start < 0
|| range.start >= (int) game->screen->height)
break ;
mlx_put_pixel(game->screen->img, x, range.start, color);
range.start++;
}
}