View
640
Download
5
Category
Preview:
Citation preview
픽킹
나철환
Mouse Picking
• 처리 단계
– 스크린 좌표계 마우스 포인터를 얻어 투영좌표
계로 변환한다.
– 변환된 투영좌표를 뷰좌표로 변환하여 카메라
원점을 시작점으로 하는 광선을 계산한다.
– 광선을 피킹 데이터와 동일한 좌표계로 변환한
다.
– 픽킹광선과 교차 판정을 한다.
목차
• 삼각형과 반직선 교차
• 원과 반직선 교차
삼각형 교차
• 반직선과 삼각형을 포함하고 있는 평면과
의 충돌을 한다
• 그 다음에 P 점이 삼각형 안에 있지는 판별
을 한다.
평면 방정식 이용
무게 중심 좌표 이용
삼각형 교차점
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
최적화
• 다이렉트에서 지원하는 IntersectTriangle()
함수를 따로 보면 위에 것을 요약해 놓아서
조금 다른 수학적 방법이 들어가 있어서 그
것을 설명 하도록 하겠습니다.
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;
삼각형 점 포함 테스트
• 반직선과 삼각형의 교차판정을 하는 방법
은 2차원적으로 해석 될 수 있다.
• OA,OB는 고정된 벡터이고 OP는 임의의
벡터입니다.
OP = u * OA + v * OB ( u,v는 임의의
실수 )
u,v에 어떤 조건을 붙여서 P가 OAB
영역을 표현하기위한 조건은, 삼각형
의 변(①②③)에대해 각각 하나씩 있
습니다.
① : 0 ≤ u
② : 0 ≤ v
③ : u + v ≤ 1
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;
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
그림에 표시된 법선(N)은 V0,V2를 포함하고 바라보는 방향과 평행한 평면의
법선벡터입니다.
N = dir ⅹ ( V2 - V0 )
이때, 점 P와 orig는 이 벡터(N)에대해 '같은 정사영'을 갖는 점들임을 알수 있습
니다. 즉 다음이 성립한다는 말이죠.
(orig-V0)•N == (P-V0)•N
• 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
(방법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;
구와 선 교차
• //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;
•
}
구와 선 교차
• //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;
•
}
구와 선 교차
• //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;
•
}
참고자료
• C:\Users\cjfghks\Desktop\Pick\IntersectTri
angle 분석.htm
• 리얼-타임 렌더링 (제 2판)
• 3D 게임 프로그래밍 & 컴퓨터 그래픽을 위
한 수학 (제 2판)
Recommended