8. 삼각형 교차점 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 = -td + uab + vac d c o a x t t b 무게 중심 좌표 v u c 0 u 1 0 v 1 u+v 1 (0,0,0) x a b x = wa + ub + vc w + u + v = 1 w = 1 - u - v
9. 최적화 다이렉트에서 지원하는 IntersectTriangle()함수를 따로 보면 위에 것을 요약해 놓아서 조금 다른 수학적 방법이 들어가 있어서 그것을 설명 하도록 하겠습니다.
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;
11. 삼각형 점 포함 테스트 반직선과 삼각형의 교차판정을 하는 방법은 2차원적으로 해석 될 수 있다. OA,OB는 고정된 벡터이고 OP는 임의의 벡터입니다. OP = u * OA + v * OB ( u,v는 임의의 실수 ) u,v에 어떤 조건을 붙여서 P가 OAB영역을 표현하기위한 조건은, 삼각형의 변(①②③)에대해 각각 하나씩 있습니다.① : 0 ≤ u② : 0 ≤ v③ : u + v ≤ 1
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;
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
14. 그림에 표시된 법선(N)은 V0,V2를 포함하고 바라보는 방향과 평행한 평면의 법선벡터입니다. N = dir ⅹ ( V2 - V0 )이때, 점 P와 orig는 이 벡터(N)에대해'같은 정사영'을 갖는 점들임을 알수 있습니다. 즉 다음이 성립한다는 말이죠.(orig-V0)•N == (P-V0)•N
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 - V0e2 = V2 - V0tvec = orig - V0
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;
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; }
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; }
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; }