cub3d/src/render/DDAscratch.c
Willem Haffmans 14094ec232 DDA on a roll
2025-05-02 20:29:20 +02:00

139 lines
3.8 KiB
C

/* ************************************************************************** */
/* */
/* :::::::: */
/* DDAscratch.c :+: :+: */
/* +:+ */
/* By: whaffman <whaffman@student.codam.nl> +#+ */
/* +#+ */
/* Created: 2025/05/02 11:58:09 by whaffman #+# #+# */
/* Updated: 2025/05/02 20:26:34 by whaffman ######## odam.nl */
/* */
/* ************************************************************************** */
#include "cub3d.h"
#include "vec_math.h"
#include <math.h>
t_vec2 get_delta_dist(t_vec2 ray_dir)
{
t_vec2 delta_dist;
delta_dist.x = (ray_dir.x == 0) * 1e30
+ (ray_dir.x != 0) * fabs(1 / ray_dir.x);
delta_dist.y = (ray_dir.y == 0) * 1e30
+ (ray_dir.y != 0) * fabs(1 / ray_dir.y);
return (delta_dist);
}
t_vec2 get_step(t_vec2 ray_dir)
{
t_vec2 step;
step.x = 2 * (ray_dir.x >= 0) - 1;
step.y = 2 * (ray_dir.y >= 0) - 1;
return (step);
}
t_vec2 get_side_dist(t_vec2 ray_dir, t_vec2 pos, t_vec2 delta_dist)
{
const t_vec2 frac_pos = (t_vec2){pos.x - (int)pos.x, pos.y - (int)pos.y};
const int raydir_x_pos = (ray_dir.x >= 0);
const int raydir_y_pos = (ray_dir.y >= 0);
t_vec2 side_dist;
side_dist.x = ((1 - raydir_x_pos) * frac_pos.x
+ raydir_x_pos * (1 - frac_pos.x)) * delta_dist.x;
side_dist.y = ((1 - raydir_y_pos) * frac_pos.y
+ raydir_x_pos * (1 - frac_pos.y)) * delta_dist.y;
return (side_dist);
}
int DDA_main(t_vec2 ray_dir, t_vec2_int map_pos, t_vec2 *side_dist, t_map *map)
{
const t_vec2 delta_dist = get_delta_dist(ray_dir);
const t_vec2 step = get_step(ray_dir);
int side;
int hit;
hit = 0;
while (hit == 0)
{
side = (side_dist->x >= side_dist->y);
side_dist->x += delta_dist.x * (1 - side);
side_dist->y += delta_dist.y * side;
map_pos.x += step.x * (1 - side);
map_pos.y += step.y * side;
hit = (map->grid[map_pos.y][map_pos.x] == TILE_WALL);
}
return (side);
}
// Returns the distance to the wall hit if the wall is hit in y direction the result is
// negative, if the wall is hit in x direction the result is positive
float DDA(t_vec2 ray_dir, t_vec2 pos, t_map *map)
{
const t_vec2 delta_dist = get_delta_dist(ray_dir);
t_vec2 side_dist;
int side;
side_dist = get_side_dist(ray_dir, pos, delta_dist);
side = DDA_main(ray_dir,
(t_vec2_int){(int)pos.x, (int)pos.y},
&side_dist,
map);
return ((1 - side) * (side_dist.x - delta_dist.x)
- side * (side_dist.y - delta_dist.y));
}
t_side get_side(t_vec2 ray_dir, float perp_dist)
{
if(perp_dist > 0)
{
if (ray_dir.x > 0)
return (SIDE_EAST);
else
return (SIDE_WEST);
}
else
{
if (ray_dir.y > 0)
return (SIDE_SOUTH);
else
return (SIDE_NORTH);
}
}
t_render cast_ray(t_game *game, int x)
{
t_vec2 ray_dir;
t_vec2 pos;
t_render render;
float perp_dist;
ray_dir = add(game->player->dir,
mul(game->player->camera,
(2.0f * x / (float)game->screen->width - 1)));
pos = game->player->pos;
perp_dist = DDA(ray_dir, pos, game->map);
render.perp_dist = fabs(perp_dist);
render.side = get_side(ray_dir);
render.wall_x = (perp_dist > 0) * (pos.x + ray_dir.x * perp_dist)
+ (perp_dist <= 0) * (pos.y + ray_dir.y * perp_dist);
render.wall_x -= floor(render.wall_x);
return (render);
}
void cast_rays(t_game *game)
{
int x;
t_render render[WIDTH];
x = 0;
while (x < game->screen->width)
{
render[x] = cast_ray(game, x);
//ETC
x++;
}
}