Ray는 시작점과 방향을 가지는 직선이다. 일반적인 선분(Line)과는 달리, Ray는 한 방향으로 무한히 뻗어 나간다. 따라서 Ray의 핵심은:
이다. 이 Ray가 Sphere, AABB, Plane, Triangle 같은 기본 3D 도형과 충돌하는지를 판별하는 것이 Raycasting의 핵심이다.
구(Sphere)와의 충돌 여부는 레이의 시작점에서 구의 중심까지의 거리를 기반으로 계산한다. 그 거리와 구의 반지름을 비교하여, 충돌 여부와 충돌 지점을 판단할 수 있다.
bool Raycast(const Sphere3D& sphere, const Ray3D& ray, OUT float& distance)
e = sphere.position - ray.origin
→ 레이의 시작점에서 구의 중심까지의 벡터.
a = e.Dot(ray.direction)
→ 레이 방향 벡터와 e의 내적 (투영된 거리).
bSq = eSq - a²
→ 피타고라스 정리에 따라 구와의 거리 계산.
f = sqrt(r² - bSq)
→ 충돌 지점까지의 거리.
eSq < r²: 레이 시작점이 구 내부에 있음.r² - bSq < 0: 교차하지 않음.distance)는 내부/외부 여부에 따라 a ± f.AABB는 x, y, z 축에 정렬된 박스 형태의 도형이다. 레이와 AABB의 교차 여부는 각 축에 대해 평면과의 교차 시점을 계산하여 판단한다. 이를 Cyrus-Beck Clipping Algorithm을 응용한 형태로 구현할 수 있다.
bool Raycast(const AABB3D& aabb, const Ray3D& ray, OUT float& distance)
t1 ~ t6 계산.tmin = 가장 큰 최소값, tmax = 가장 작은 최대값tmin > tmax: 충돌 없음tmax < 0: 충돌은 있지만 레이의 뒷부분이므로 무효Ray가 Plane과 만나는지 확인하는 방법은 간단하지만, 조건을 정확히 알아야 한다.
bool Raycast(const Plane3D& plane, const Ray3D& ray, OUT float& distance)
normal(법선 벡터)과 distance로 정의된다.nd = ray.direction.Dot(plane.normal)nd >= 0: 평면과 평행이거나 레이의 뒷면이므로 무시.t = (plane.distance - ray.origin.Dot(plane.normal)) / nd삼각형과의 Raycasting은 Ray가 삼각형의 평면과 교차하는지, 그리고 교차점이 삼각형 안에 존재하는지를 체크해야 한다.
bool Raycast(const Triangle3D& triangle, const Ray3D& ray, float& distance)
FromTriangle)[0, 1] 범위 안이면 내부Vec3 Barycentric(const Point3D& p, const Triangle3D& t)
이 함수는 삼각형의 세 꼭짓점과 점 p 사이의 상대적인 비율을 계산한다.