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