1 #define LOCAL_EPSILON 0.000001f
3 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5 * Computes a ray-triangle intersection test.
6 * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection".
7 * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from
8 * ray origin to triangle is negative.
10 * \param vert0 [in] triangle vertex
11 * \param vert1 [in] triangle vertex
12 * \param vert2 [in] triangle vertex
13 * \return true on overlap. mStabbedFace is filled with relevant info.
15 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 inline_ BOOL
RayCollider::RayTriOverlap(const Point
& vert0
, const Point
& vert1
, const Point
& vert2
)
21 // Find vectors for two edges sharing vert0
22 Point edge1
= vert1
- vert0
;
23 Point edge2
= vert2
- vert0
;
25 // Begin calculating determinant - also used to calculate U parameter
26 Point pvec
= mDir
^edge2
;
28 // If determinant is near zero, ray lies in plane of triangle
29 float det
= edge1
|pvec
;
33 if(det
<= LOCAL_EPSILON
* FCMin2(edge1
.SquareMagnitude(), edge2
.SquareMagnitude())) return FALSE
;
34 // From here, det is > 0. So we can use integer cmp.
36 // Calculate distance from vert0 to ray origin
37 Point tvec
= mOrigin
- vert0
;
39 // Calculate U parameter and test bounds
40 mStabbedFace
.mU
= tvec
|pvec
;
41 // if(IR(u)&0x80000000 || u>det) return FALSE;
42 if(IS_NEGATIVE_FLOAT(mStabbedFace
.mU
) || IR(mStabbedFace
.mU
)>IR(det
)) return FALSE
;
44 // Prepare to test V parameter
45 Point qvec
= tvec
^edge1
;
47 // Calculate V parameter and test bounds
48 mStabbedFace
.mV
= mDir
|qvec
;
49 if(IS_NEGATIVE_FLOAT(mStabbedFace
.mV
) || mStabbedFace
.mU
+mStabbedFace
.mV
>det
) return FALSE
;
51 // Calculate t, scale parameters, ray intersects triangle
52 mStabbedFace
.mDistance
= edge2
|qvec
;
53 // Det > 0 so we can early exit here
54 // Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
55 if(IS_NEGATIVE_FLOAT(mStabbedFace
.mDistance
)) return FALSE
;
57 float OneOverDet
= 1.0f
/ det
;
58 mStabbedFace
.mDistance
*= OneOverDet
;
59 mStabbedFace
.mU
*= OneOverDet
;
60 mStabbedFace
.mV
*= OneOverDet
;
64 // the non-culling branch
65 if(FastFabs(det
) <= LOCAL_EPSILON
* FCMin2(edge1
.SquareMagnitude(), edge2
.SquareMagnitude())) return FALSE
;
66 float OneOverDet
= 1.0f
/ det
;
68 // Calculate distance from vert0 to ray origin
69 Point tvec
= mOrigin
- vert0
;
71 // Calculate U parameter and test bounds
72 mStabbedFace
.mU
= (tvec
|pvec
) * OneOverDet
;
73 // if(IR(u)&0x80000000 || u>1.0f) return FALSE;
74 if(IS_NEGATIVE_FLOAT(mStabbedFace
.mU
) || IR(mStabbedFace
.mU
)>IEEE_1_0
) return FALSE
;
76 // prepare to test V parameter
77 Point qvec
= tvec
^edge1
;
79 // Calculate V parameter and test bounds
80 mStabbedFace
.mV
= (mDir
|qvec
) * OneOverDet
;
81 if(IS_NEGATIVE_FLOAT(mStabbedFace
.mV
) || mStabbedFace
.mU
+mStabbedFace
.mV
>1.0f
) return FALSE
;
83 // Calculate t, ray intersects triangle
84 mStabbedFace
.mDistance
= (edge2
|qvec
) * OneOverDet
;
85 // Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
86 if(IS_NEGATIVE_FLOAT(mStabbedFace
.mDistance
)) return FALSE
;