MathJax

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(n • d) + 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의 좌하단 우상단 좌표인가요?

    답글삭제