• 티스토리 홈
  • 프로필사진
    유니얼
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
유니얼
  • 프로필사진
    유니얼
    • 분류 전체보기 (295)
      • Unity (17)
        • 게임 개발 (5)
      • Unreal (24)
        • 게임 개발 (20)
      • DirectX (36)
      • 코딩테스트 (91)
        • 프로그래머스 (25)
        • 백준 (66)
      • Google Workspace (1)
      • Programing (102)
        • C# (68)
        • C++ (24)
        • JavaScript (10)
      • 게임 서버 프로그래밍 (17)
      • Web (6)
        • 슈퍼코딩 (6)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
    등록된 댓글이 없습니다.
  • 최근 공지
    등록된 공지가 없습니다.
# Home
# 공지사항
#
# 태그
# 검색결과
# 방명록
  • [DirectX11] 기본 게임 도형(Sphere,AABB,OBB등)과 Raycast
    2024년 03월 14일
    • 유니얼
    • 작성자
    • 2024.03.14.:03
    728x90

    DirectX 11로 게임 엔진 아키텍처 만들기

    DirectX11과 게임 엔진 아키텍처 학습 과정에서 3D 그래픽스의 기본 구성 요소와 중요한 개념 중 하나인 레이캐스팅(Raycasting)에 대해 알아보겠습니다. 레이캐스팅은 가상 환경 내에서 레이(광선)를 발사하여 해당 레이가 다른 객체와 충돌하는지를 판별하는 과정입니다. 이 방법은 그래픽스 렌더링, 물리 시뮬레이션, 인공 지능의 시야 판단 등 다양한 분야에서 활용됩니다.

    참고강의 링크:

    https://www.inflearn.com/course/directx11-%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C-%EB%8F%84%EC%95%BD%EB%B0%98/dashboard

     

    [게임 프로그래머 도약반] DirectX11 입문 강의 - 인프런

    게임 프로그래머 공부에 있어서 필수적인 DirectX 11 지식을 초보자들의 눈높이에 맞춰 설명하는 강의입니다., [사진][사진] [사진] 게임 개발자는 Unreal, Unity만 사용할 줄 알면 되는 거 아닌가요? 엔

    www.inflearn.com

    레이와 구(Sphere)의 충돌 검사

    레이와 구의 충돌 검사는 레이의 시작점부터 구의 중심까지의 거리를 계산하고, 이 거리가 구의 반지름보다 짧은지 여부를 통해 충돌을 판단합니다. 코드에서는 e가 레이의 시작점에서 구의 중심까지의 벡터, rSq가 구의 반지름의 제곱, eSq는 e의 길이 제곱, a는 e와 레이의 방향 벡터의 내적, f는 실제 충돌 지점까지의 거리를 나타냅니다.

     

    // 구와 레이의 충돌 검사
    bool MathUtils::Raycast(const Sphere3D& sphere, const Ray3D& ray, OUT float& distance)
    {
    	Vec3 e = sphere.position - ray.origin; // 레이의 시작점에서 구의 중심까지의 벡터
    
    	float rSq = sphere.radius * sphere.radius; // 구의 반지름의 제곱
    	float eSq = e.LengthSquared(); // e 벡터의 길이의 제곱
    
    	float a = e.Dot(ray.direction); // 레이 방향과 e 벡터의 내적
    
    	float bSq = eSq - (a * a); // b의 제곱(삼각형의 한 변의 제곱)
    	float f = sqrt(rSq - bSq); // f는 삼각형의 다른 변(구의 반지름에서 b를 뺀 값)
    
    	// 실제 충돌이 발생하지 않는 경우
    	if (rSq - (eSq - (a * a)) < 0.0f)
    		return false;
    
    	// 레이의 시작점이 구 내부에 있는 경우
    	if (eSq < rSq)
    	{
    		distance = a + f; // 구를 뚫고 나가는 지점까지의 거리
    		return true;
    	}
    	// 구 외부에서 시작하여 구에 닿지 않는 경우
    	distance = a - f; // 구에 가장 가까운 점까지의 거리
    	return false;
    }

    레이와 AABB(Axis-Aligned Bounding Box)의 충돌 검사

    AABB와 레이의 충돌 검사는 AABB를 구성하는 6개의 평면 각각에 대해 레이와의 교차점을 찾아내는 과정을 포함합니다. 이는 Cyrus-Beck 클리핑 알고리즘을 변형한 형태로 수행되며, tmin과 tmax를 통해 충돌이 발생하는지 판별합니다.

     

    // AABB와 레이의 충돌 검사 (Cyrus-Beck clipping algorithm을 사용)
    bool MathUtils::Raycast(const AABB3D& aabb, const Ray3D& ray, OUT float& distance)
    {
    	Vec3 min = AABB3D::GetMin(aabb); // AABB의 최소 좌표
    	Vec3 max = AABB3D::GetMax(aabb); // AABB의 최대 좌표
    
    	// 각 축에 대해 레이가 AABB의 두 평면(최소값, 최대값)과 만나는 t 값을 계산
    	float t1 = (min.x - ray.origin.x) / ray.direction.x;
    	float t2 = (max.x - ray.origin.x) / ray.direction.x;
    
    	float t3 = (min.y - ray.origin.y) / ray.direction.y;
    	float t4 = (max.y - ray.origin.y) / ray.direction.y;
    
    	float t5 = (min.z - ray.origin.z) / ray.direction.z;
    	float t6 = (max.z - ray.origin.z) / ray.direction.z;
    
    	// 가장 큰 최소 t 값(tmin)과 가장 작은 최대 t 값(tmax)을 계산
    	float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
    	float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
    
    	// tmax가 0보다 작으면 레이는 AABB의 뒤쪽을 향함
    	if (tmax < 0)
    		return false;
    
    	// tmin이 tmax보다 크면 레이는 AABB를 교차하지 않음
    	if (tmin > tmax)
    		return false;
    
    	// 실제 충돌 거리 계산
    	distance = (tmin < 0.0f) ? tmax : tmin;
    	return true;
    }

    레이와 평면(Plane)의 충돌 검사

    레이와 평면의 충돌 검사는 레이가 평면에 평행한지, 그리고 평행하지 않다면 레이가 평면을 지나가는 지점을 찾아내는 과정을 포함합니다. 이는 레이의 방향 벡터와 평면의 법선 벡터의 내적, 그리고 레이의 시작점과 평면의 거리를 계산하여 수행됩니다.

     

    // 평면과 레이의 충돌 검사
    bool MathUtils::Raycast(const Plane3D& plane, const Ray3D& ray, OUT float& distance)
    {
    	float nd = ray.direction.Dot(plane.normal); // 레이 방향과 평면의 법선의 내적
    	float pn = ray.origin.Dot(plane.normal); // 레이의 시작점과 평면의 법선의 내적
    
    	// nd가 0보다 크거나 같으면 레이와 평면은 평행하거나 레이가 평면에서 멀어짐
    	if (nd >= 0.0f)
    		return false;
    
    	// 실제 충돌 거리 계산
    	float t = (plane.distance - pn) / nd;
    	if (t >= 0.0f) {
    		distance = t; // 충돌 지점까지의 거리
    		return true;
    	}
    
    	return false;
    }

    결론

    레이캐스팅은 3D 그래픽스 및 게임 엔진에서 광범위하게 사용되는 기술로, 가상 환경 내의 객체 간 상호 작용을 결정하는 데 핵심적인 역할을 합니다. 본문에서 소개된 구체적인 레이캐스팅 방법들—레이와 구의 충돌, 레이와 AABB의 충돌, 그리고 레이와 평면의 충돌 검사—은 개발자가 보다 정확하고 효율적으로 3D 공간에서의 상호 작용을 구현할 수 있게 해줍니다.

    반응형
    다음글
    다음 글이 없습니다.
    이전글
    이전 글이 없습니다.
    댓글
조회된 결과가 없습니다.
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
목차
표시할 목차가 없습니다.
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바