RavEngine
Loading...
Searching...
No Matches
GuSweepBoxTriangle_SAT.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef GU_SWEEP_BOX_TRIANGLE_SAT_H
30#define GU_SWEEP_BOX_TRIANGLE_SAT_H
31
32#include "geometry/PxTriangle.h"
33
34#include "GuSweepSharedTests.h"
35#include "GuInternal.h"
36
37 #define RetType int
38 #define MTDType bool
39
40namespace physx
41{
42namespace Gu
43{
44
45// We have separation if one of those conditions is true:
46// -BoxExt > TriMax (box strictly to the right of the triangle)
47// BoxExt < TriMin (box strictly to the left of the triangle
48// <=> d0 = -BoxExt - TriMax > 0
49// d1 = BoxExt - TriMin < 0
50// Hence we have overlap if d0 <= 0 and d1 >= 0
51// overlap = (d0<=0.0f && d1>=0.0f)
52#define TEST_OVERLAP \
53 const float d0 = -BoxExt - TriMax; \
54 const float d1 = BoxExt - TriMin; \
55 const bool bIntersect = (d0<=0.0f && d1>=0.0f); \
56 bValidMTD &= bIntersect;
57
58 // PT: inlining this one is important. Returning floats looks bad but is faster on Xbox.
59 static PX_FORCE_INLINE RetType testAxis(const PxTriangle& tri, const PxVec3& extents, const PxVec3& dir, const PxVec3& axis, MTDType& bValidMTD, float& tfirst, float& tlast)
60 {
61 const float d0t = tri.verts[0].dot(axis);
62 const float d1t = tri.verts[1].dot(axis);
63 const float d2t = tri.verts[2].dot(axis);
64
65 float TriMin = PxMin(d0t, d1t);
66 float TriMax = PxMax(d0t, d1t);
67 TriMin = PxMin(TriMin, d2t);
68 TriMax = PxMax(TriMax, d2t);
69
71
72 const float BoxExt = PxAbs(axis.x)*extents.x + PxAbs(axis.y)*extents.y + PxAbs(axis.z)*extents.z;
73 TEST_OVERLAP
74
75 const float v = dir.dot(axis);
76 if(PxAbs(v) < 1.0E-6f)
77 return bIntersect;
78 const float oneOverV = -1.0f / v;
79
80 // float t0 = d0 * oneOverV;
81 // float t1 = d1 * oneOverV;
82 // if(t0 > t1) TSwap(t0, t1);
83 const float t0_ = d0 * oneOverV;
84 const float t1_ = d1 * oneOverV;
85 float t0 = PxMin(t0_, t1_);
86 float t1 = PxMax(t0_, t1_);
87
88 if(t0 > tlast) return false;
89 if(t1 < tfirst) return false;
90
91 // if(t1 < tlast) tlast = t1;
92 tlast = PxMin(t1, tlast);
93
94 // if(t0 > tfirst) tfirst = t0;
95 tfirst = PxMax(t0, tfirst);
96
97 return true;
98 }
99
100 template<const int XYZ>
101 static PX_FORCE_INLINE RetType testAxisXYZ(const PxTriangle& tri, const PxVec3& extents, const PxVec3& dir, float oneOverDir, MTDType& bValidMTD, float& tfirst, float& tlast)
102 {
103 const float d0t = tri.verts[0][XYZ];
104 const float d1t = tri.verts[1][XYZ];
105 const float d2t = tri.verts[2][XYZ];
106
107 float TriMin = PxMin(d0t, d1t);
108 float TriMax = PxMax(d0t, d1t);
109 TriMin = PxMin(TriMin, d2t);
110 TriMax = PxMax(TriMax, d2t);
111
113
114 const float BoxExt = extents[XYZ];
115 TEST_OVERLAP
116
117 const float v = dir[XYZ];
118 if(PxAbs(v) < 1.0E-6f)
119 return bIntersect;
120
121 const float oneOverV = -oneOverDir;
122
123 // float t0 = d0 * oneOverV;
124 // float t1 = d1 * oneOverV;
125 // if(t0 > t1) TSwap(t0, t1);
126 const float t0_ = d0 * oneOverV;
127 const float t1_ = d1 * oneOverV;
128 float t0 = PxMin(t0_, t1_);
129 float t1 = PxMax(t0_, t1_);
130
131 if(t0 > tlast) return false;
132 if(t1 < tfirst) return false;
133
134 // if(t1 < tlast) tlast = t1;
135 tlast = PxMin(t1, tlast);
136
137 // if(t0 > tfirst) tfirst = t0;
138 tfirst = PxMax(t0, tfirst);
139
140 return true;
141 }
142
143 PX_FORCE_INLINE int testSeparationAxes( const PxTriangle& tri, const PxVec3& extents,
144 const PxVec3& normal, const PxVec3& dir, const PxVec3& oneOverDir, float tmax, float& tcoll)
145 {
146 bool bValidMTD = true;
147 float tfirst = -FLT_MAX;
148 float tlast = FLT_MAX;
149
150 // Triangle normal
151 if(!testAxis(tri, extents, dir, normal, bValidMTD, tfirst, tlast))
152 return 0;
153
154 // Box normals
155 if(!testAxisXYZ<0>(tri, extents, dir, oneOverDir.x, bValidMTD, tfirst, tlast))
156 return 0;
157 if(!testAxisXYZ<1>(tri, extents, dir, oneOverDir.y, bValidMTD, tfirst, tlast))
158 return 0;
159 if(!testAxisXYZ<2>(tri, extents, dir, oneOverDir.z, bValidMTD, tfirst, tlast))
160 return 0;
161
162 // Edges
163 for(PxU32 i=0; i<3; i++)
164 {
165 int ip1 = int(i+1);
166 if(i>=2) ip1 = 0;
167 const PxVec3 TriEdge = tri.verts[ip1] - tri.verts[i];
168
169 {
170 const PxVec3 Sep = cross100(TriEdge);
171 if((Sep.dot(Sep))>=1.0E-6f && !testAxis(tri, extents, dir, Sep, bValidMTD, tfirst, tlast))
172 return 0;
173 }
174 {
175 const PxVec3 Sep = cross010(TriEdge);
176 if((Sep.dot(Sep))>=1.0E-6f && !testAxis(tri, extents, dir, Sep, bValidMTD, tfirst, tlast))
177 return 0;
178 }
179 {
180 const PxVec3 Sep = cross001(TriEdge);
181 if((Sep.dot(Sep))>=1.0E-6f && !testAxis(tri, extents, dir, Sep, bValidMTD, tfirst, tlast))
182 return 0;
183 }
184 }
185
186 if(tfirst > tmax || tlast < 0.0f)
187 return 0;
188
189 if(tfirst <= 0.0f)
190 {
191 if(!bValidMTD)
192 return 0;
193 tcoll = 0.0f;
194 }
195 else tcoll = tfirst;
196
197 return 1;
198 }
199
201 PX_FORCE_INLINE int triBoxSweepTestBoxSpace_inlined(const PxTriangle& tri, const PxVec3& extents, const PxVec3& dir, const PxVec3& oneOverDir, float tmax, float& toi, PxU32 doBackfaceCulling)
202 {
203 // Create triangle normal
204 PxVec3 triNormal;
205 tri.denormalizedNormal(triNormal);
206
207 // Backface culling
208 if(doBackfaceCulling && (triNormal.dot(dir)) >= 0.0f) // ">=" is important !
209 return 0;
210
211 // The SAT test will properly detect initial overlaps, no need for extra tests
212 return testSeparationAxes(tri, extents, triNormal, dir, oneOverDir, tmax, toi);
213 }
214
230 int triBoxSweepTestBoxSpace(const PxTriangle& tri, const PxVec3& extents, const PxVec3& dir, const PxVec3& oneOverDir, float tmax, float& toi, bool doBackfaceCulling);
231
232} // namespace Gu
233
234}
235
236#endif
Triangle class.
Definition PxTriangle.h:47
PX_FORCE_INLINE void denormalizedNormal(PxVec3 &_normal) const
Compute the unnormalized normal of the triangle.
Definition PxTriangle.h:111
3 Element vector class.
Definition PxVec3.h:50
PX_CUDA_CALLABLE PX_FORCE_INLINE float dot(const PxVec3 &v) const
returns the scalar product of this and other.
Definition PxVec3.h:276
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
int triBoxSweepTestBoxSpace(const PxTriangle &tri, const PxVec3 &extents, const PxVec3 &dir, const PxVec3 &oneOverDir, float tmax, float &toi, bool doBackfaceCulling)
Definition GuSweepBoxTriangle_SAT.cpp:35
PX_FORCE_INLINE int triBoxSweepTestBoxSpace_inlined(const PxTriangle &tri, const PxVec3 &extents, const PxVec3 &dir, const PxVec3 &oneOverDir, float tmax, float &toi, PxU32 doBackfaceCulling)
Inlined version of triBoxSweepTestBoxSpace. See that other function for comments.
Definition GuSweepBoxTriangle_SAT.h:201
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAbs(float a)
abs returns the absolute value of its argument.
Definition PxMath.h:109
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMax(T a, T b)
The return value is the greater of the two specified values.
Definition PxMath.h:72
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMin(T a, T b)
The return value is the lesser of the two specified values.
Definition PxMath.h:88