20
픽킹 나철환

픽킹

Embed Size (px)

Citation preview

Page 1: 픽킹

픽킹

나철환

Page 2: 픽킹

Mouse Picking

• 처리 단계

– 스크린 좌표계 마우스 포인터를 얻어 투영좌표

계로 변환한다.

– 변환된 투영좌표를 뷰좌표로 변환하여 카메라

원점을 시작점으로 하는 광선을 계산한다.

– 광선을 피킹 데이터와 동일한 좌표계로 변환한

다.

– 픽킹광선과 교차 판정을 한다.

Page 3: 픽킹

목차

• 삼각형과 반직선 교차

• 원과 반직선 교차

Page 4: 픽킹

삼각형 교차

• 반직선과 삼각형을 포함하고 있는 평면과

의 충돌을 한다

• 그 다음에 P 점이 삼각형 안에 있지는 판별

을 한다.

Page 5: 픽킹

평면 방정식 이용

Page 6: 픽킹

무게 중심 좌표 이용

Page 7: 픽킹
Page 8: 픽킹

삼각형 교차점

a

b

c

tx

o d

a b

c

x = wa + ub + vc

w + u + v = 1

w = 1 - u - v

x(0,0,0)

x(u, v)= (1 – u – v)a + ub + vc

ab = b – a, ac = c – a

x(u, v)= a + u ab + v ac

x(u, v)= o + t d

o + t d = a + u ab + v ac

o – a = oa = -t d + u ab + v ac

무게 중심 좌표x x x x

y y y y

z z z z

t

u

v

d ab ac oa

d ab ac oa

d ab ac oa

( )1

( )( )

( )

t

u

v

ac oa ab

oa d acab d ac

d oa ab

0 u 1

0 v 1

u+v 1

t

u

v

Page 9: 픽킹

최적화

• 다이렉트에서 지원하는 IntersectTriangle()

함수를 따로 보면 위에 것을 요약해 놓아서

조금 다른 수학적 방법이 들어가 있어서 그

것을 설명 하도록 하겠습니다.

Page 10: 픽킹

Triangle Intersection// Calculate U parameter and test bounds

*u = D3DXVec3Dot( &tvec, &pvec );

if( *u < 0.0f || *u > det )

return false;

// Prepare to test V parameter

D3DXVECTOR3 qvec;

D3DXVec3Cross( &qvec, &tvec, &edge1 );

// Calculate V parameter and test bounds

*v = D3DXVec3Dot( &dir, &qvec );

if( *v < 0.0f || *u + *v > det )

return false;

// Calculate t, scale parameters, ray intersects triangle

*t = D3DXVec3Dot( &edge2, &qvec );

FLOAT fInvDet = 1.0f / det;

*t *= fInvDet;

*u *= fInvDet;

*v *= fInvDet;

return true;

IntersectTriangle(const D3DXVECTOR3& orig,

const D3DXVECTOR3& dir,

D3DXVECTOR3& v0,

D3DXVECTOR3& v1,

D3DXVECTOR3& v2,

FLOAT* t, FLOAT* u, FLOAT* v )

// Find vectors for two edges sharing vert0

D3DXVECTOR3 edge1 = v1 - v0;

D3DXVECTOR3 edge2 = v2 - v0;

// Begin calculating determinant

//- also used to calculate U parameter

D3DXVECTOR3 pvec;

D3DXVec3Cross( &pvec, &dir, &edge2 );

// If determinant is near zero, ray lies in plane of triangle

FLOAT det = D3DXVec3Dot( &edge1, &pvec );

D3DXVECTOR3 tvec;

if( det > 0 )

{ tvec = orig - v0; }

else

{ tvec = v0 – orig;

det = -det;

}

if( det < 0.0001f ) return false;

Page 11: 픽킹

삼각형 점 포함 테스트

• 반직선과 삼각형의 교차판정을 하는 방법

은 2차원적으로 해석 될 수 있다.

• OA,OB는 고정된 벡터이고 OP는 임의의

벡터입니다.

OP = u * OA + v * OB ( u,v는 임의의

실수 )

u,v에 어떤 조건을 붙여서 P가 OAB

영역을 표현하기위한 조건은, 삼각형

의 변(①②③)에대해 각각 하나씩 있

습니다.

① : 0 ≤ u

② : 0 ≤ v

③ : u + v ≤ 1

Page 12: 픽킹

Triangle Intersection// Calculate U parameter and test bounds

*u = D3DXVec3Dot( &tvec, &pvec );

if( *u < 0.0f || *u > det )

return false;

// Prepare to test V parameter

D3DXVECTOR3 qvec;

D3DXVec3Cross( &qvec, &tvec, &edge1 );

// Calculate V parameter and test bounds

*v = D3DXVec3Dot( &dir, &qvec );

if( *v < 0.0f || *u + *v > det )

return false;

// Calculate t, scale parameters, ray intersects triangle

*t = D3DXVec3Dot( &edge2, &qvec );

FLOAT fInvDet = 1.0f / det;

*t *= fInvDet;

*u *= fInvDet;

*v *= fInvDet;

return true;

IntersectTriangle(const D3DXVECTOR3& orig,

const D3DXVECTOR3& dir,

D3DXVECTOR3& v0,

D3DXVECTOR3& v1,

D3DXVECTOR3& v2,

FLOAT* t, FLOAT* u, FLOAT* v )

// Find vectors for two edges sharing vert0

D3DXVECTOR3 edge1 = v1 - v0;

D3DXVECTOR3 edge2 = v2 - v0;

// Begin calculating determinant

//- also used to calculate U parameter

D3DXVECTOR3 pvec;

D3DXVec3Cross( &pvec, &dir, &edge2 );

// If determinant is near zero, ray lies in plane of triangle

FLOAT det = D3DXVec3Dot( &edge1, &pvec );

D3DXVECTOR3 tvec;

if( det > 0 )

{ tvec = orig - v0; }

else

{ tvec = v0 – orig;

det = -det;

}

if( det < 0.0001f ) return false;

Page 13: 픽킹

u,v을 어떻게 구하나?

v = |Ob|/|OB| = Ob•nA/OB•nA

Ob•nA = OP•nA

∴v = Ob•nA/OB•nA = OP•nA/OB•nA

u = OP•nB/OA•nB

Page 14: 픽킹

그림에 표시된 법선(N)은 V0,V2를 포함하고 바라보는 방향과 평행한 평면의

법선벡터입니다.

N = dir ⅹ ( V2 - V0 )

이때, 점 P와 orig는 이 벡터(N)에대해 '같은 정사영'을 갖는 점들임을 알수 있습

니다. 즉 다음이 성립한다는 말이죠.

(orig-V0)•N == (P-V0)•N

Page 15: 픽킹

• u = OP•nB/OA•nB

• u = tvec • ( dir ⅹ e2 ) /

• e1 • ( dir ⅹ e2 )

• v = Ob•nA/OB•nA

• v = tvec • ( e1 ⅹ dir ) /

• e2 • ( e1 ⅹ dir )

e1 = V1 - V0

e2 = V2 - V0

tvec = orig - V0

Page 16: 픽킹

(방법1)Triangle Intersection-4-// Calculate U parameter and test bounds

*u = D3DXVec3Dot( &tvec, &pvec );

if( *u < 0.0f || *u > det )

return false;

// Prepare to test V parameter

D3DXVECTOR3 qvec;

D3DXVec3Cross( &qvec, &tvec, &edge1 );

// Calculate V parameter and test bounds

*v = D3DXVec3Dot( &dir, &qvec );

if( *v < 0.0f || *u + *v > det )

return false;

// Calculate t, scale parameters, ray intersects triangle

*t = D3DXVec3Dot( &edge2, &qvec );

FLOAT fInvDet = 1.0f / det;

*t *= fInvDet;

*u *= fInvDet;

*v *= fInvDet;

return true;

IntersectTriangle(const D3DXVECTOR3& orig,

const D3DXVECTOR3& dir,

D3DXVECTOR3& v0,

D3DXVECTOR3& v1,

D3DXVECTOR3& v2,

FLOAT* t, FLOAT* u, FLOAT* v )

// Find vectors for two edges sharing vert0

D3DXVECTOR3 edge1 = v1 - v0;

D3DXVECTOR3 edge2 = v2 - v0;

// Begin calculating determinant

//- also used to calculate U parameter

D3DXVECTOR3 pvec;

D3DXVec3Cross( &pvec, &dir, &edge2 );

// If determinant is near zero, ray lies in plane of triangle

FLOAT det = D3DXVec3Dot( &edge1, &pvec );

D3DXVECTOR3 tvec;

if( det > 0 )

{ tvec = orig - v0; }

else

{ tvec = v0 – orig;

det = -det;

}

if( det < 0.0001f ) return false;

Page 17: 픽킹

구와 선 교차

• //sphere 체크할 구

• //ray 체크할 광선

• //intersection 교차 시 교차 지점.

• //distance 광선의 시작점으로부터 교차 점까지의 거리

• bool intersect_ray_and_sphere( const Sphere& sphere, const Ray& ray, vector3& intersection, double& distance) {

• vector3 l = sphere.center - ray.origin;

• double s = dot( l, ray.direction );

• double l2 = dot( l, l );

• double r2 = pow( sphere.radius, 2 );

• if( s < 0 && l2 > r2 ) {

• return false; // 광선이 구의 반대 방향을 향하거나 구를 지나친 경우

• }

• double m2 = l2 - pow( s, 2 );

• if( m2 > r2 ) {

• return false; // 광선이 구를 비껴가는 경우

• }

• double q = sqrt( r2 - m2 );

• // 두 개의 교차점 중 어느것을 구하는가?

• if( l2 > r2 ) {

• distance = s - q;

• }else {

• distance = s + q;

• }

• intersection = o + distance * ray.direction;

• return true;

}

Page 18: 픽킹

구와 선 교차

• //sphere 체크할 구

• //ray 체크할 광선

• //intersection 교차 시 교차 지점.

• //distance 광선의 시작점으로부터 교차 점까지의 거리

• bool intersect_ray_and_sphere( const Sphere& sphere, const Ray& ray, vector3& intersection, double& distance) {

• vector3 l = sphere.center - ray.origin;

• double s = dot( l, ray.direction );

• double l2 = dot( l, l );

• double r2 = pow( sphere.radius, 2 );

• if( s < 0 && l2 > r2 ) {

• return false; // 광선이 구의 반대 방향을 향하거나 구를 지나친 경우

• }

• double m2 = l2 - pow( s, 2 );

• if( m2 > r2 ) {

• return false; // 광선이 구를 비껴가는 경우

• }

• double q = sqrt( r2 - m2 );

• // 두 개의 교차점 중 어느것을 구하는가?

• if( l2 > r2 ) {

• distance = s - q;

• }else {

• distance = s + q;

• }

• intersection = o + distance * ray.direction;

• return true;

}

Page 19: 픽킹

구와 선 교차

• //sphere 체크할 구

• //ray 체크할 광선

• //intersection 교차 시 교차 지점.

• //distance 광선의 시작점으로부터 교차 점까지의 거리

• bool intersect_ray_and_sphere( const Sphere& sphere, const Ray& ray, vector3& intersection, double& distance) {

• vector3 l = sphere.center - ray.origin;

• double s = dot( l, ray.direction );

• double l2 = dot( l, l );

• double r2 = pow( sphere.radius, 2 );

• if( s < 0 && l2 > r2 ) {

• return false; // 광선이 구의 반대 방향을 향하거나 구를 지나친 경우

• }

• double m2 = l2 - pow( s, 2 );

• if( m2 > r2 ) {

• return false; // 광선이 구를 비껴가는 경우

• }

• double q = sqrt( r2 - m2 );

• // 두 개의 교차점 중 어느것을 구하는가?

• if( l2 > r2 ) {

• distance = s - q;

• }else {

• distance = s + q;

• }

• intersection = o + distance * ray.direction;

• return true;

}

Page 20: 픽킹

참고자료

• C:\Users\cjfghks\Desktop\Pick\IntersectTri

angle 분석.htm

• 리얼-타임 렌더링 (제 2판)

• 3D 게임 프로그래밍 & 컴퓨터 그래픽을 위

한 수학 (제 2판)