| 363 | |
| 364 | template <typename T> |
| 365 | std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<T>& oriA, const Vector3<T>& oriB, const Vector3<T>& oriC, |
| 366 | const IntersectionPrecomputes<T>& prec ) |
| 367 | { |
| 368 | const T& Sx = prec.Sx; |
| 369 | const T& Sy = prec.Sy; |
| 370 | const T& Sz = prec.Sz; |
| 371 | |
| 372 | const T Ax = oriA[prec.idxX] - Sx * oriA[prec.maxDimIdxZ]; |
| 373 | const T Ay = oriA[prec.idxY] - Sy * oriA[prec.maxDimIdxZ]; |
| 374 | const T Bx = oriB[prec.idxX] - Sx * oriB[prec.maxDimIdxZ]; |
| 375 | const T By = oriB[prec.idxY] - Sy * oriB[prec.maxDimIdxZ]; |
| 376 | const T Cx = oriC[prec.idxX] - Sx * oriC[prec.maxDimIdxZ]; |
| 377 | const T Cy = oriC[prec.idxY] - Sy * oriC[prec.maxDimIdxZ]; |
| 378 | |
| 379 | // due to fused multiply-add (FMA): (A*B-A*B) can be different from zero, so we need epsilon |
| 380 | const T eps = std::numeric_limits<T>::epsilon() * std::max( { Ax, Bx, Cx, Ay, By, Cy } ); |
| 381 | T U = Cx * By - Cy * Bx; |
| 382 | T V = Ax * Cy - Ay * Cx; |
| 383 | T W = Bx * Ay - By * Ax; |
| 384 | |
| 385 | if( U < -eps || V < -eps || W < -eps ) |
| 386 | { |
| 387 | if( U > eps || V > eps || W > eps ) |
| 388 | { |
| 389 | // U,V,W have clearly different signs, so the ray misses the triangle |
| 390 | return std::nullopt; |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | T det = U + V + W; |
| 395 | if( det == T( 0 ) ) |
| 396 | return std::nullopt; |
| 397 | const T Az = Sz * oriA[prec.maxDimIdxZ]; |
| 398 | const T Bz = Sz * oriB[prec.maxDimIdxZ]; |
| 399 | const T Cz = Sz * oriC[prec.maxDimIdxZ]; |
| 400 | const T t = U * Az + V * Bz + W * Cz; |
| 401 | |
| 402 | auto invDet = T( 1 ) / det; |
| 403 | return TriIntersectResult( float( V * invDet ), float( W * invDet ), float( t * invDet ) ); |
| 404 | } |
| 405 | |
| 406 | MR_BIND_TEMPLATE( std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<float >& oriA, const Vector3<float >& oriB, const Vector3<float >& oriC, const IntersectionPrecomputes<float >& prec ) ) |
| 407 | MR_BIND_TEMPLATE( std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<double>& oriA, const Vector3<double>& oriB, const Vector3<double>& oriC, const IntersectionPrecomputes<double>& prec ) ) |
no test coverage detected