/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   render_floor.c                                     :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: qmennen <qmennen@student.codam.nl>         +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2025/05/14 13:06:39 by whaffman          #+#    #+#             */
/*   Updated: 2025/06/04 20:07:21 by qmennen          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "cub3d.h"

static t_vec2	calc_floor_step(t_game *game,
	double row_dist, t_vec2 left_ray, t_vec2 right_ray)
{
	t_vec2	floor_step;

	floor_step = sub(right_ray, left_ray);
	floor_step = mul(floor_step, row_dist);
	floor_step = mul(floor_step, 1.0 / game->screen->width);
	return (floor_step);
}

static void	draw_floor_ceiling_pixel(t_game *game,
	t_vec2_int coord, double row_dist, t_vec2 floor_pos)
{
	const t_vec2_int	tex = vec2_to_int(mul(get_fraction(floor_pos), game->map->texture_floor->width));
	int					color;

	if (game->map->texture_floor == NULL)
		color = game->map->floor_color << 8 | (int)(1.0 / row_dist * 255);
	else
		color = get_texture_color(game->map->texture_floor,
				(t_render){row_dist, 0, 0}, tex);
	mlx_put_pixel(game->screen->img,
		coord.x, coord.y, color);
	if (game->map->texture_ceiling == NULL)
		color = game->map->ceiling_color << 8 | (int)(1.0 / row_dist * 255);
	else
		color = get_texture_color(game->map->texture_ceiling,
				(t_render){row_dist, 0, 0}, tex);
	mlx_put_pixel(game->screen->img,
		coord.x, game->screen->height - coord.y - 1, color);
}

static void	draw_floor_row(t_game *game,
	t_vec2_int coord, t_vec2 left_ray, t_vec2 right_ray)
{
	double	row_dist;
	t_vec2	floor_step;
	t_vec2	floor_pos;

	row_dist = 0.5 * game->screen->height;
	row_dist /= (coord.y - 0.5 * game->screen->height);
	floor_step = calc_floor_step(game, row_dist, left_ray, right_ray);
	floor_pos = add(game->player->pos, mul(left_ray, row_dist));
	if (isinf(floor_pos.x) || isinf(floor_pos.y))
		return ;
	while (coord.x < game->screen->width)
	{
		draw_floor_ceiling_pixel(game, coord, row_dist, floor_pos);
		floor_pos = add(floor_pos, floor_step);
		coord.x++;
	}
}

void	draw_floor(t_game *game)
{
	const t_vec2	left_ray = sub(game->player->dir, game->player->camera);
	const t_vec2	right_ray = add(game->player->dir, game->player->camera);
	t_vec2_int		coord;

	coord.y = game->screen->height / 2;
	coord.x = 0;
	while (coord.y < game->screen->height)
	{
		draw_floor_row(game, coord, left_ray, right_ray);
		coord.y++;
	}
}
