Update OpenGL check on macOS
[ode.git] / OPCODE / OPC_RayTriOverlap.h
blob04110a1fb6e295dd7d932485d6481aeeb7a0aa46
1 #define LOCAL_EPSILON 0.000001f
3 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4 /**
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)
18 // Stats
19 mNbRayPrimTests++;
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;
31 if(mCulling)
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;
56 // Else go on
57 float OneOverDet = 1.0f / det;
58 mStabbedFace.mDistance *= OneOverDet;
59 mStabbedFace.mU *= OneOverDet;
60 mStabbedFace.mV *= OneOverDet;
62 else
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;
88 return TRUE;