241 lines
6.5 KiB
C
241 lines
6.5 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* cast_ray.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2022/06/15 23:56:03 by apommier #+# #+# */
|
|
/* Updated: 2022/06/15 23:56:06 by apommier ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "../../includes/Cub3D.h"
|
|
|
|
void draw_ray3d(t_data *img, t_ray ray)
|
|
{
|
|
double line_height;
|
|
double line_offset;
|
|
int x;
|
|
double y;
|
|
int mx;
|
|
int my;
|
|
int color;
|
|
double gap;
|
|
double myy;
|
|
|
|
line_height = 64 * 960 / ray.dist;
|
|
line_offset = 256 - ((int)line_height) / 2;
|
|
x = 0;
|
|
y = 0;
|
|
my = 0;
|
|
myy = 0;
|
|
gap = (64 / line_height);
|
|
mx = ((int)ray.mp) % 64;
|
|
if (line_height > 512)
|
|
{
|
|
line_offset = 0;
|
|
myy = gap * ((line_height - 512) / 2);
|
|
}
|
|
while (y < line_height - 8 && y < 512)
|
|
{
|
|
myy += gap;
|
|
my = (int)myy;
|
|
ray.pixel = ((my) * 64 + mx) * 3 + 1;
|
|
x = -1;
|
|
if (ray.pixel >= 12290 || ray.pixel < 0)
|
|
return ;
|
|
else if (ray.pixel > 0)
|
|
{
|
|
if (ray.texture_type == 'N' && img->map.texture.north)
|
|
color = get_color(img->map.texture.north[ray.pixel], img->map.texture.north[ray.pixel + 1], img->map.texture.north[ray.pixel + 2]);
|
|
else if (ray.texture_type == 'S' && img->map.texture.south)
|
|
color = get_color(img->map.texture.south[ray.pixel], img->map.texture.south[ray.pixel + 1], img->map.texture.south[ray.pixel + 2]);
|
|
else if (ray.texture_type == 'W' && img->map.texture.west)
|
|
color = get_color(img->map.texture.west[ray.pixel], img->map.texture.west[ray.pixel + 1], img->map.texture.west[ray.pixel + 2]);
|
|
else if (ray.texture_type == 'E' && img->map.texture.east)
|
|
color = get_color(img->map.texture.east[ray.pixel], img->map.texture.east[ray.pixel + 1], img->map.texture.east[ray.pixel + 2]);
|
|
}
|
|
else
|
|
color = 0;
|
|
while (++x < 4)
|
|
{
|
|
set_pixel(img, color, ray.index * 4 + x, y + line_offset);
|
|
}
|
|
y++;
|
|
}
|
|
x++;
|
|
}
|
|
|
|
void draw_ray(t_data *img)
|
|
{
|
|
double ray_angle = 0;
|
|
double ray_y = 0;
|
|
double ray_x = 0;
|
|
double next_x = 0;
|
|
double next_y = 0;
|
|
double dist_v;
|
|
double dist_h;
|
|
double dist_f;
|
|
double vx = 0;
|
|
double vy = 0;
|
|
int count = 0;
|
|
double aTan = 0;
|
|
int nb_ray = -1;
|
|
int my = 0;
|
|
int mx = 0;
|
|
int mp = 0;
|
|
char vertical_type;
|
|
char horizontal_type;
|
|
|
|
void *new_img;
|
|
int bits_per_pixel = 0;
|
|
int size_line = 0;
|
|
int endian = 0;
|
|
|
|
new_img = mlx_new_image(img->mlx, 960, 512);
|
|
if (!new_img)
|
|
ft_exit("Error\nmlx_new_image failed\n", img);
|
|
img->buffer = mlx_get_data_addr(new_img, &bits_per_pixel, &size_line, &endian);
|
|
img->bits_per_pixel = bits_per_pixel;
|
|
img->size_line = size_line;
|
|
img->endian = endian;
|
|
set_back(img);
|
|
|
|
|
|
(void)dist_f;
|
|
count = 0;
|
|
ray_angle = reset_angle(img->player.angle + 30);
|
|
while (++nb_ray < 240)
|
|
{
|
|
count = 0;
|
|
dist_v = -1;
|
|
dist_h = -1;
|
|
//----------start vertical ray----------
|
|
aTan = tan(deg_to_rad(ray_angle));
|
|
if (cos(deg_to_rad(ray_angle)) > 0.001)//looking left
|
|
{
|
|
ray_x = (((int)img->player.x>>6)<<6) + 64;
|
|
ray_y = (img->player.x - ray_x) * aTan + img->player.y;
|
|
next_x = 64;
|
|
next_y = -next_x * aTan;
|
|
vertical_type = 'E';
|
|
}
|
|
else if (cos(deg_to_rad(ray_angle)) < -0.001)//looking right
|
|
{
|
|
ray_x = (((int)img->player.x>>6)<<6) - 0.0001;
|
|
ray_y = (img->player.x - ray_x) * aTan + img->player.y;
|
|
next_x = -64;
|
|
next_y = -next_x * aTan;
|
|
vertical_type = 'W';
|
|
}
|
|
else
|
|
{
|
|
ray_x = img->player.x;
|
|
ray_y = img->player.y;
|
|
count = img->map.max;
|
|
}
|
|
while (count < img->map.max)
|
|
{
|
|
mx = (int)(ray_x)>>6;
|
|
my = (int)(ray_y)>>6;
|
|
mp = my * img->map.x + mx;
|
|
if (mp > 0 && mp < img->map.size && img->map.simple_map[mp] == '1')//hit wall
|
|
{
|
|
count = img->map.max;
|
|
//printf("vertical wall\n");
|
|
dist_v = cos(deg_to_rad(ray_angle)) * (ray_x-img->player.x) - sin(deg_to_rad(ray_angle)) * (ray_y-img->player.y);
|
|
}
|
|
else
|
|
{
|
|
ray_x += next_x;
|
|
ray_y += next_y;
|
|
count += 1;
|
|
}
|
|
}
|
|
vx = ray_x;
|
|
vy = ray_y;
|
|
//-------start horizontal ray---------
|
|
count = 0;
|
|
aTan = 1.0 / aTan;
|
|
if (sin(deg_to_rad(ray_angle)) > 0.001)//looking up
|
|
{
|
|
ray_y = (((int)img->player.y>>6)<<6) - 0.0001;
|
|
ray_x = (img->player.y - ray_y) * aTan + img->player.x;
|
|
next_y = -64;
|
|
next_x = -next_y * aTan;
|
|
horizontal_type = 'N';
|
|
}
|
|
else if (sin(deg_to_rad(ray_angle))<-0.001)//looking down
|
|
{
|
|
ray_y = (((int)img->player.y>>6)<<6) + 64;
|
|
ray_x = (img->player.y - ray_y) * aTan + img->player.x;
|
|
next_y = 64;
|
|
next_x = -next_y * aTan;
|
|
horizontal_type = 'S';
|
|
}
|
|
else
|
|
{
|
|
ray_x = img->player.x;
|
|
ray_y = img->player.y;
|
|
count = img->map.max;
|
|
}//looking straight left or right
|
|
|
|
while (count < img->map.max)
|
|
{
|
|
mx = (int)(ray_x)>>6;
|
|
my = (int)(ray_y)>>6;
|
|
mp = my * img->map.x + mx;
|
|
if (mp > 0 && mp < img->map.size && img->map.simple_map[mp] == '1')//hit
|
|
{
|
|
count = img->map.max;
|
|
dist_h = cos(deg_to_rad(ray_angle)) * (ray_x - img->player.x) - sin(deg_to_rad(ray_angle)) * (ray_y - img->player.y);
|
|
}
|
|
else
|
|
{
|
|
ray_x += next_x;
|
|
ray_y += next_y;
|
|
count += 1;
|
|
} //check next horizontal
|
|
}
|
|
int wall_type;
|
|
t_ray ray_info;
|
|
|
|
wall_type = 0;
|
|
ray_info.texture_type = 0;
|
|
if (dist_h != -1 && (dist_h < dist_v || dist_v == -1))
|
|
{
|
|
dist_f = dist_h;
|
|
ray_info.mp = ray_x;
|
|
wall_type = 0;
|
|
ray_info.texture_type = horizontal_type;
|
|
}
|
|
else if (dist_v != -1)
|
|
{
|
|
dist_f = dist_v;
|
|
ray_x = vx;
|
|
ray_y = vy;
|
|
ray_info.mp = vy;
|
|
wall_type = 1;
|
|
ray_info.texture_type = vertical_type;
|
|
}
|
|
else
|
|
{
|
|
ray_info.mp = 0;
|
|
dist_f = 0;
|
|
}
|
|
ray_info.ty = ray_y;
|
|
ray_info.pixel = 0;
|
|
ray_info.tx = ray_x;
|
|
ray_info.index = nb_ray;
|
|
ray_info.wall_type = wall_type;
|
|
int ca = reset_angle(img->player.angle - ray_angle); //fisheye
|
|
dist_f = dist_f * cos(deg_to_rad(ca)); //fisheye
|
|
ray_info.dist = dist_f;
|
|
if (dist_f > 0)
|
|
draw_ray3d(img, ray_info);
|
|
ray_angle = reset_angle(ray_angle - 0.25);
|
|
}
|
|
mlx_put_image_to_window(img->mlx, img->mlx_win, new_img, 0, 0);
|
|
mlx_destroy_image(img->mlx, new_img);
|
|
} |