4) cub3D - Raycaster 구현 (1)

sorikikikim·2021년 6월 6일
1

cub3D

목록 보기
4/6

참고한 링크

map.cub로 부터 map을 불러온 후, 모든 유효성 검사가 완료되면 저장된 map의 정보를 바탕으로 lodev 튜토리얼에 따라 floor, ceiling, wall을 만들고 player의 초기 위치, 키 값에 따른 회전과 움직임을 설정한다.

lodev tutorial - wall

맵의 요소

0 : 비어있는 공간
1: 벽
N,S,W,E: player (초기 설정 방향)
그 외 : error

변수 선언 (t_player)

typedef struct		s_player
{
	double		pos_x;
	double		pos_y;
	double		dir_x;
	double		dir_y;
	double		plane_x;
	double		plane_y;
	t_move_hor_ver	movement; // 이동 설정
	t_move_hor_ver	rotation; // 회전 설정
}			t_player;
t_player	*player;

player->pos_x, player->pos_y
: 플레이어의 초기 위치벡터

player->dir_x, player->dir_y
: 플레이어의 초기 방향벡터

player->plane_x, player->plane_y
: 플레이어의 카메라 평면

- 카메라 평면은 방향벡터와 수직이기만 하면 변수선언시 길이가 다양할 수 있다.
- 이 코드에서는 카메라 평면보다 방향벡터가 약간 더 길어서 FOV가 90°보다 작다. 
(정확히는 FOV = 2 * atan(0.66/1.0)=66.8°로 1인칭 슈팅게임(fps)에 적합) 
- 초기선언 이후에는 입력키로 회전해서 방향벡터 dir과 카메라 평면 plane의 값이 변경되더라도 항상 서로 수직이어야 하고 동일한 길이가 유지되어야 한다.

변수 선언 (t_wall_info)

typedef struct		s_wall_info
{
	double		camera_x;
	double		raydir_x;
	double		raydir_y;
	double		side_dist_x;
	double		side_dist_y;
	double		delta_dist_x;
	double		delta_dist_y;
	double		perp_wall_dist;
	double		wall_x;
	double		step;
	double		tex_pos;
	int		map_x;
	int		map_y;
	int		step_x;
	int		step_y;
	int		hit;
	int		side;
	int		line_height;
	int		draw_start;
	int		draw_end;
	int		tex_num;
	int		tex_x;
	int		tex_y;
	int		color;
	int		x;
	int		y;
}			t_wall_info;
t_wall_info	*wall;

wall->camera_x 
: x값(화면의 수직선)의 위치가 카메라 평면에서 차지하는 x좌표
  (반복문에서 x값이 0[스크린의 왼쪽 끝]이면 wall->camera_x = -1,
  x값이 width/2[스크린의 중앙]이면 wall->camera_x = 0,
  x값이 width[스크린의 오른쪽 끝]이면 wall->camera_x = 1)
  이를 이용해서 광선의 방향을 계산한다.

wall->raydir_x, wall->raydir_y
: 광선의 방향벡터
  광선의 방향은 (플레이어의 방향벡터) + (카메라 평면 * 배수)이다.
  벡터 x, y에 대해 각각 이 계산을 해준다.

wall->map_x, wall->map_y
: 현재 광선의 위치, 광선이 있는 한 칸 (정확한 위치가 아닌 존재하고 있는 그 한칸의 좌표)

DDA 알고리즘 관련 변수 (t_wall_info)

t_wall_info	*wall;

wall->side_dist_x, wall->side_dist_y
: '시작점 ~ 첫번째 x, y면을 만나는 점'까지의 광선의 이동거리 (나중에 의미가 약간 변경된다)

wall->delta_dist_x, wall->delta_dist_y
: '첫번째 x, y면 ~ 바로 다음 x, y면'까지의 광선의 이동거리

wall->perp_wall_dist
: 벽에 부딪힐 때까지의 광선의 이동거리를 계산하는 수직광선의 길이

wall->step_x, wall->step_y
: DDA 알고리즘은 반복문을 실행할 때마다 x 또는 y 방향으로 한 칸씩 점프하는데
  광선의 방향에 따라 어느 방향으로 건너뛰는지를 +1, -1로 저장
  
wall->hit
: 벽과 부딪혔는지 여부 (루프 종료조건)

wall->side
: 벽과 부딪혔을 때, x면에 부딪혔으면 0이고 y면에 부딪혔으면 1.

set_wall()

(1) 변수 초기화

t_wall_info *wall;

wall->camera_x = 2 * wall->x / (double)WIDTH - 1;
wall->raydir_x = player->dir_x + player->plane_x * wall->camera_x;
wall->raydir_y = player->dir_y + player->plane_y * wall->camera_x;
wall->map_x = (int)player->pos_x;
wall->map_y = (int)player->pos_y;
wall->delta_dist_x = fabs(1 / wall->raydir_x);
wall->delta_dist_y = fabs(1 / wall->raydir_y);
wall->hit = 0;

(2) step, side_dist 변수 초기화

if (wall->raydir_x < 0)
{
	wall->step_x = -1;
	wall->side_dist_x = (player->pos_x - wall->map_x) * wall->delta_dist_x;
}
else
{
	wall->step_x = 1;
	wall->side_dist_x = (wall->map_x + 1.0 - player->pos_x) * wall->delta_dist_x;
}
if (wall->raydir_y < 0)
{
	wall->step_y = -1;
	wall->side_dist_y = (player->pos_y - wall->map_y) * wall->delta_dist_y;
}
else
{
	wall->step_y = 1;
	wall->side_dist_y = (wall->map_y + 1.0 - player->pos_y) * wall->delta_dist_y;
}

1) wall->step_x, wall->step_y
  광선의 x방향(raydir_x) > 0, step_x : +1,
  광선의 y방향(raydir_y) > 0, step_y : +1,
  광선의 x방향(raydir_x) < 0, step_x : -1,
  광선의 y방향(raydir_y) < 0, step_y : -1
  광선의 방향(raydir_x, raydir_y) == 0, step은 사용되지 않으므로 어떤 값을 갖든 상관없다. 

2) wall->side_dist_x, wall->side_dist_y
  광선의 x방향(raydir_x) > 0, 
  side_dist_x : 광선의 시작점부터 오른쪽으로 이동하다 처음 만나는 x면까지의 거리
  광선의 x방향(raydir_x) < 0, 
  side_dist_x : 광선의 시작점부터 왼쪽으로 이동하다 처음 만나는 x면까지의 거리
  광선의 y방향(raydir_y) > 0, 
  side_dist_y : 광선의 시작점부터 위쪽으로 이동하다 처음 만나는 y면까지의 거리
  광선의 y방향(raydir_y) < 0, 
  side_dist_y : 광선의 시작점부터 아래쪽으로 이동하다 처음 만나는 y면까지의 거리

초기화 (x, y동일)
 wall->raydir_x > 0,
 wall->side_dist_x = (wall->map_x + 1.0 - player->pos_x) * wall->delta_dist_x;
 		       광선의 위치		     실제 위치
 wall->raydir_x < 0,
 wall->side_dist_x = (wall->pos_x - wall->map_x) * wall->delta_dist_x;
		        실제 위치       광선의 위치

Hits

1개의 댓글

comment-user-thumbnail
2024년 3월 6일

초기화 (x, y동일)
wall->raydir_x > 0,
wall->side_dist_x = (wall->map_x + 1.0 - player->pos_x) wall->delta_dist_x;
광선의 위치 실제 위치
wall->raydir_x < 0,
wall->side_dist_x = (wall->pos_x - wall->map_x)
wall->delta_dist_x;
실제 위치 광선의 위치

여기서 실제위치랑 광선의 위치 개념이 이해가 잘 안되는데 혹시 도와주실수있으실까요?

답글 달기

관련 채용 정보