2011년 12월 7일 수요일

AABB와 RAY 교차 ( Intersecting AABB and ray )


Slab:
Kay  Kajiya 제안
개의 평행한 평면 사이의 무한한 공간

Slab  Ray 교차를 이용하여 AABB 교차를 판단


광선(Ray): r(t) = o + td
o: 원점
t: 광선상의 정점들을 생성하는데 사용되는 변수
d: 방향 벡터 ( 일반적으로 편의 위해 정규화 , ||d|| = 1 )

광선이 Slab 평면과 교차하는 t 값을 구하여 사용
평면:  n + D = 0
평면 위의 x 경우 다음을 만족함
n • x + D = 0

그러므로 t 값을 구하기 위해 x t값을 가지는 광선의 한점으로 대치함
n • (r(t)) + D = 0
n • ( o + td ) + D = 0
(n • o) + t(nd) + D = 0
t = ( -(n • o)  - D ) /  (n • d)

여기서  AABB 특징들을 이용하면 t 대한 식이 간단히

1. AABB 표준 기저와 축이 같아서
평면 n 값이 축마다 2 요소씩 0
) x축의 경우: nx  = (1, 0, 0)

그래서 nx • o = (1, 0, 0) • (ox, oy, oz) = ox
 i   { x, y, z } 이면 위의 t 관한 식은 정리 되어서

t = ( -oi  - D ) /  di

2. 추가로 평면이 표준 기저 축과 평행하므로 평면의 D 값은
AABB min[i], max[i]값을 사용할 있음 ( i   { x, y, z } ) 

또한, di 절대값이 아주 작을 경우 해당되는 축과 평행하게
이때는 해당되는 축의 원점 oi 값이 AABB min, max 
벗어나면 교차 상태가 아니게

광선과 Slab 평면들과의 교차점을 찾아 tmin, tmax값을 찾는다.
예를 들어 현재 축에 해당되는 Slab 평면과 교차점 찾는 경우
tmin: 광선의 시작점으로 부터 처음 만나는 Slab 평면의 교차점
tmax: 두번째 Slab 평면과 교차점 

이렇게 축마다  t값을 구하면서 tmin, tmax 서로 가까운 거리가 
유지 되도록 한다.

작업 중간에 tmin > tmax 이렇게 값이 서로 바뀌는 경우가 발생하면
AABB 서로 교차하지 않는 것이 된다.

  




 //o: 광선의 원점
//d: 광선의 방향벡터
//p: 첫번째 교차점
bool AABBtoRay(AABB a, Vector3 o, Vector3 d, Vector3& p)
{
        float t_min = 0;
        float t_max = MAX_FLOAT;

for(int i=0; i<3; i++)
{
if(abs(d[i]) < EPSILON)
{
if( o[i] < a.min[i] ||
  o[i] > a.max[i] )
return false;
}
else 
{
float denom = 1.0f / d[i];
float t1 = (-o[i] - a.min[i]) * denom;
float t2 = (-o[i] - a.max[i]) * denom;
if(t1 > t2)
{
swap(t1, t2);
}
t_min = max(t_min, t1);
t_max = min(t_max, t2);
if(t_min > t_max)
return false;
}
}
p = o + t_min * d;
return true;
}

참고자료:
Real - Time Rendering 2판
Real - Time Collision Detection




댓글 2개:

  1. 죄송하지만 이 내용은 AABB와 ray가 아닌 OBB와 ray 교차 같습니다.

    답글삭제
  2. 좋은 글 감사합니다. 질문이 있는데 AABB의 min/max는 각각 cube의 좌하단 우상단 좌표인가요?

    답글삭제