관리 메뉴

드럼치는 프로그래머

[DirextX] 평면 본문

★─Programing/☆─DirectX

[DirextX] 평면

드럼치는한동이 2010. 2. 17. 14:04

평면의 표현

평면의 내적

평면의 생성

평면의 정규화

평면의 변환

 

평면의 표현

D3DX는 공간상의 평면에 대한 표현 및 함수를 지원한다.

 

공간상의 평면 표현

하나의 노말벡터 n과 한 점 p(0)로 표현된다.

 

임의의 한점 p가 평면상에 있다면 n · ( p - p(0) ) = 0을 만족

따라서 n · p + d = 0 ( d = -n · p ) 로 정리할 수 있다.

n을 단위벡터라고 가정하면 d가 원점에서 최단거리에 해당하고 부호를 가진다.

부호화된 최단거리란,

평면에서 원점으로의 방향이 n과 같은 방향이면 양수이고, n의 반대방향이면 음수이다.

 

평면의 노말을 n = (a, b, c)라고 하면

평면은 하나의 4차원 벡터 (a, b, c, d)로 표현 할 수 있다.

평면의 식은 ax + by + cz + dw = 0이다.

 

평면은 D3DX에서 D3DXPLANE 구조체로 표현한다.

D3DXPLANE은 FLOAT 형의 4차원 벡터를 위한 구조체로 a, b, c, d를 가진다.

D3DXPLANE은 두평면의 덧셈과 뺄셈, 스칼라로 곱셈과 나눗셈 등의 기본 산술 연산자를 재정의

 

한 평면 (n, d)와 한 점 p의 공간 관계를 계산

평면 노말 n은 단위벡터라고 하면,

k = n · p + d 를 부호가 있는 거리(signed distance)라고 한다.

k가 0이면 점 p는 그 평면상에 존재한다.

k가 양수이면 점 p는 평면의 앞쪽 공간(노말 방향)에 존재한다.

k가 음수이면 평면의 뒤쪽 공간에 존재한다.

 

평면상의 최단거리 점

한 점 p와 가장 가까이 있는 한 평면 (n, d)상의 점을 구할 수 있다.

p와 가장 가까이 있는 평면상의 점을 q라고 하고,

p에서 평면과의 부호가 있는 거리를 k = ( n · p + d )라고 하자.

q에서 p로 가는 벡터는 길이가 k이고 방향이 n이므로 kn이다.

즉, p = q + kn 이 된다. 따라서 q = p - kn 이다.

 

평면과 광선의 교점

광선(ray)은 광선의 시작점 p(0)와 광선의 방향 u로 표현된다.

광선 상의 점들은 p(t) = p0 + tu 로 표시된다. ( t는 0이거나 그보다 큰 양수 )

 

평면 n · p + d = 0 와 광선이 교차하는 점을 구하기

n · p(t) + d = 0 을 만족하는 t를 찾으면 된다.

이러한 t는 t = -(d + n · p0) / (n · u) 이다.

t가 음수라면 교차하지 않음을 의미한다.

t가 양수라면 교차점은 p0 + [ -( d + n·p0 ) / ( n · u ) ]u로 주어진다.

 

 

 

평면의 내적

 

D3DXPlaneDotCoord 함수

평면 p = (a, b, c, d)와 비동차좌표 벡터 v = (x, y, z, 1)의 내적을 구한다.

 

즉, ax + by + cz + d 를 계산하여 리턴한다.

이 연산은 평면과 점과의 거리를 계산하는 데 사용될 수 있다.

 

D3DXPLANE p(0.0f, 1.0f, 0.0f, 0.0f);

D3DXVECTOR3 v(3.0f, 5.0f, 2.0f);

float x = D3DXPlaneDotCoord( &p, &v );

if ( fequals(x, 0.0f) ) { /* v가 평면 상에 있음 */ }

if ( x > 0 ) { /* v가 평면의 양의 방향에 있음 */ }

if ( x < 0 ) { /* v가 평면의 음의 방향에 있음 */ }

 

x == 0.0f 대신 함수 fequals(x, 0.0f)를 사용한 이유는 x가 실수이므로 아주 작은 값 때문에,

x가 0.0f 와 다르게 되는 경우를 해결하기 위함이다.

x가 0.0f 와 매우 비슷하다면 같다고 처리하는 것이 바람직하다.

실수 x가 대략적으로 0이라는 것은 아래와 같이 구현하면 된다.

 

const float EPSILON = 0.001f;

boolean equals ( float lhs, float rhs ) {

           return fabs(lhs - rhs) < EPSILON ? true : false

}

 

 

D3DXPlaneDotCoord 와 비슷한 다른 함수들

 

D3DXPlaneDot 함수

평면 p = (a, b, c, d)와 동차좌표로 표현된 D3DXVECTOR4 형 벡터 v = (x, y, z, w)의 내적을 구한다.

즉, ax + by + cz + dw 를 리턴한다.

 

D3DXPlaneDotNormal

평면 p = (a, b, c, d)와 방향을 표시하는 D3DXVECTOR3 형 벡터 v = (x, y, z)의 내적을 구한다.

즉, 벡터 v = (x, y, z)를 방향벡터 v = (x, y, z, 0)으로 취급하여 ax + by + cz를 리턴한다.

(이 함수는 평면의 노말과 다른 방향과의 각도를 계산하는데 쓰인다.)

 

 

 

 

 

평면의 생성

평면 D3DXPLANE을 생성하는 방법은 다음의 세가지로 가능하다.

 

D3DXPLANE p(a, b, c, d);

 - 평면의 노말 n = (a, b, c)와 부호가 있는 거리 d가 주어지면,

   평면 p를 다음과 같이 생성할 수 있다.

 

D3DXPLANE p; // 평면

D3DXVECTOR3 p0; // 평면상의 한점

D3DXVECTOR3 n; // 평면 노말

D3DXPlaneFromPointNormal ( &p, &p0, &n );

 - 평면의 노말 n = (a, b, c)와 평면상의 한 점 p0가 주어지면,

   d = -n · p0로 부호가 있는 거리를 계산한다.

   이후 첫번째 방법으로 평면을 생성하면 된다. D3DX에서 이 과정을 위한 함수를 제공

 

D3DXPLANE p; // 평면

D3DXVECTOR3 p0, p1, p2; // 평면상의 세 점

D3DXPlaneFromPoints ( &p, &p0, &p1, &p2 );

 - 평면상의 세 점 p0, p1, p2가 주어지면

   먼저 평면을 만드는 두 벡터 u = p1 - p0 와 v = p2 - p0를 계산하고

   평면의 노말을 n = u X v 로 계산하고

   부호가 있는 거리를 d = -n · p0 로 계산한다.

   이제 첫번째 방법으로 평면을 생성할 수 있다.

 

평면의 정규화

평면 D3DXPLANE에 포함된 노말 n = (a, b, c)은 항상 단위벡터가 되도록 유지해야 한다.

평면의 정규화란 평면의 노말이 단위벡터가 되도록 해주는 것을 말한다.

평면에 대해 어떤 여산을 적용하여 평면의 노말이 단위벡터 성질을 만족하지 않게 될 경우에,

강제로 정규화를 해서 노말이 단위벡터가 되도록 해야 한다. d는 d = -n · p 이므로 노말에 의존된다.

따라서 노말을 수정하면 d도 동시에 수정해 주어야 한다.

 

( n, d ) -> ( n/∥n∥, d/∥n∥)

D3DX에서 제공되는 평면의 정규화 함수



[출처]
[DirextX] 평면|작성자 yhWoo


Comments