Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
RayAABox.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8
11{
12public:
14 inline RayInvDirection() = default;
15 inline explicit RayInvDirection(Vec3Arg inDirection) { Set(inDirection); }
16
18 inline void Set(Vec3Arg inDirection)
19 {
20 // if (abs(inDirection) <= Epsilon) the ray is nearly parallel to the slab.
21 mIsParallel = Vec3::sLessOrEqual(inDirection.Abs(), Vec3::sReplicate(1.0e-20f));
22
23 // Calculate 1 / direction while avoiding division by zero
25 }
26
29};
30
33JPH_INLINE float RayAABox(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec3Arg inBoundsMin, Vec3Arg inBoundsMax)
34{
35 // Constants
36 Vec3 flt_min = Vec3::sReplicate(-FLT_MAX);
37 Vec3 flt_max = Vec3::sReplicate(FLT_MAX);
38
39 // Test against all three axes simultaneously.
40 Vec3 t1 = (inBoundsMin - inOrigin) * inInvDirection.mInvDirection;
41 Vec3 t2 = (inBoundsMax - inOrigin) * inInvDirection.mInvDirection;
42
43 // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
44 // use the results from any directions parallel to the slab.
45 Vec3 t_min = Vec3::sSelect(Vec3::sMin(t1, t2), flt_min, inInvDirection.mIsParallel);
46 Vec3 t_max = Vec3::sSelect(Vec3::sMax(t1, t2), flt_max, inInvDirection.mIsParallel);
47
48 // t_min.xyz = maximum(t_min.x, t_min.y, t_min.z);
49 t_min = Vec3::sMax(t_min, t_min.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>());
50 t_min = Vec3::sMax(t_min, t_min.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y>());
51
52 // t_max.xyz = minimum(t_max.x, t_max.y, t_max.z);
53 t_max = Vec3::sMin(t_max, t_max.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>());
54 t_max = Vec3::sMin(t_max, t_max.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y>());
55
56 // if (t_min > t_max) return FLT_MAX;
57 UVec4 no_intersection = Vec3::sGreater(t_min, t_max);
58
59 // if (t_max < 0.0f) return FLT_MAX;
60 no_intersection = UVec4::sOr(no_intersection, Vec3::sLess(t_max, Vec3::sZero()));
61
62 // if (inInvDirection.mIsParallel && !(Min <= inOrigin && inOrigin <= Max)) return FLT_MAX; else return t_min;
63 UVec4 no_parallel_overlap = UVec4::sOr(Vec3::sLess(inOrigin, inBoundsMin), Vec3::sGreater(inOrigin, inBoundsMax));
64 no_intersection = UVec4::sOr(no_intersection, UVec4::sAnd(inInvDirection.mIsParallel, no_parallel_overlap));
65 no_intersection = UVec4::sOr(no_intersection, no_intersection.SplatY());
66 no_intersection = UVec4::sOr(no_intersection, no_intersection.SplatZ());
67 return Vec3::sSelect(t_min, flt_max, no_intersection).GetX();
68}
69
72JPH_INLINE Vec4 RayAABox4(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ)
73{
74 // Constants
75 Vec4 flt_min = Vec4::sReplicate(-FLT_MAX);
76 Vec4 flt_max = Vec4::sReplicate(FLT_MAX);
77
78 // Origin
79 Vec4 originx = inOrigin.SplatX();
80 Vec4 originy = inOrigin.SplatY();
81 Vec4 originz = inOrigin.SplatZ();
82
83 // Parallel
84 UVec4 parallelx = inInvDirection.mIsParallel.SplatX();
85 UVec4 parallely = inInvDirection.mIsParallel.SplatY();
86 UVec4 parallelz = inInvDirection.mIsParallel.SplatZ();
87
88 // Inverse direction
89 Vec4 invdirx = inInvDirection.mInvDirection.SplatX();
90 Vec4 invdiry = inInvDirection.mInvDirection.SplatY();
91 Vec4 invdirz = inInvDirection.mInvDirection.SplatZ();
92
93 // Test against all three axes simultaneously.
94 Vec4 t1x = (inBoundsMinX - originx) * invdirx;
95 Vec4 t1y = (inBoundsMinY - originy) * invdiry;
96 Vec4 t1z = (inBoundsMinZ - originz) * invdirz;
97 Vec4 t2x = (inBoundsMaxX - originx) * invdirx;
98 Vec4 t2y = (inBoundsMaxY - originy) * invdiry;
99 Vec4 t2z = (inBoundsMaxZ - originz) * invdirz;
100
101 // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
102 // use the results from any directions parallel to the slab.
103 Vec4 t_minx = Vec4::sSelect(Vec4::sMin(t1x, t2x), flt_min, parallelx);
104 Vec4 t_miny = Vec4::sSelect(Vec4::sMin(t1y, t2y), flt_min, parallely);
105 Vec4 t_minz = Vec4::sSelect(Vec4::sMin(t1z, t2z), flt_min, parallelz);
106 Vec4 t_maxx = Vec4::sSelect(Vec4::sMax(t1x, t2x), flt_max, parallelx);
107 Vec4 t_maxy = Vec4::sSelect(Vec4::sMax(t1y, t2y), flt_max, parallely);
108 Vec4 t_maxz = Vec4::sSelect(Vec4::sMax(t1z, t2z), flt_max, parallelz);
109
110 // t_min.xyz = maximum(t_min.x, t_min.y, t_min.z);
111 Vec4 t_min = Vec4::sMax(Vec4::sMax(t_minx, t_miny), t_minz);
112
113 // t_max.xyz = minimum(t_max.x, t_max.y, t_max.z);
114 Vec4 t_max = Vec4::sMin(Vec4::sMin(t_maxx, t_maxy), t_maxz);
115
116 // if (t_min > t_max) return FLT_MAX;
117 UVec4 no_intersection = Vec4::sGreater(t_min, t_max);
118
119 // if (t_max < 0.0f) return FLT_MAX;
120 no_intersection = UVec4::sOr(no_intersection, Vec4::sLess(t_max, Vec4::sZero()));
121
122 // if bounds are invalid return FLOAT_MAX;
123 UVec4 bounds_invalid = UVec4::sOr(UVec4::sOr(Vec4::sGreater(inBoundsMinX, inBoundsMaxX), Vec4::sGreater(inBoundsMinY, inBoundsMaxY)), Vec4::sGreater(inBoundsMinZ, inBoundsMaxZ));
124 no_intersection = UVec4::sOr(no_intersection, bounds_invalid);
125
126 // if (inInvDirection.mIsParallel && !(Min <= inOrigin && inOrigin <= Max)) return FLT_MAX; else return t_min;
127 UVec4 no_parallel_overlapx = UVec4::sAnd(parallelx, UVec4::sOr(Vec4::sLess(originx, inBoundsMinX), Vec4::sGreater(originx, inBoundsMaxX)));
128 UVec4 no_parallel_overlapy = UVec4::sAnd(parallely, UVec4::sOr(Vec4::sLess(originy, inBoundsMinY), Vec4::sGreater(originy, inBoundsMaxY)));
129 UVec4 no_parallel_overlapz = UVec4::sAnd(parallelz, UVec4::sOr(Vec4::sLess(originz, inBoundsMinZ), Vec4::sGreater(originz, inBoundsMaxZ)));
130 no_intersection = UVec4::sOr(no_intersection, UVec4::sOr(UVec4::sOr(no_parallel_overlapx, no_parallel_overlapy), no_parallel_overlapz));
131 return Vec4::sSelect(t_min, flt_max, no_intersection);
132}
133
136JPH_INLINE void RayAABox(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec3Arg inBoundsMin, Vec3Arg inBoundsMax, float &outMin, float &outMax)
137{
138 // Constants
139 Vec3 flt_min = Vec3::sReplicate(-FLT_MAX);
140 Vec3 flt_max = Vec3::sReplicate(FLT_MAX);
141
142 // Test against all three axes simultaneously.
143 Vec3 t1 = (inBoundsMin - inOrigin) * inInvDirection.mInvDirection;
144 Vec3 t2 = (inBoundsMax - inOrigin) * inInvDirection.mInvDirection;
145
146 // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
147 // use the results from any directions parallel to the slab.
148 Vec3 t_min = Vec3::sSelect(Vec3::sMin(t1, t2), flt_min, inInvDirection.mIsParallel);
149 Vec3 t_max = Vec3::sSelect(Vec3::sMax(t1, t2), flt_max, inInvDirection.mIsParallel);
150
151 // t_min.xyz = maximum(t_min.x, t_min.y, t_min.z);
152 t_min = Vec3::sMax(t_min, t_min.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>());
153 t_min = Vec3::sMax(t_min, t_min.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y>());
154
155 // t_max.xyz = minimum(t_max.x, t_max.y, t_max.z);
156 t_max = Vec3::sMin(t_max, t_max.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>());
157 t_max = Vec3::sMin(t_max, t_max.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y>());
158
159 // if (t_min > t_max) return FLT_MAX;
160 UVec4 no_intersection = Vec3::sGreater(t_min, t_max);
161
162 // if (t_max < 0.0f) return FLT_MAX;
163 no_intersection = UVec4::sOr(no_intersection, Vec3::sLess(t_max, Vec3::sZero()));
164
165 // if (inInvDirection.mIsParallel && !(Min <= inOrigin && inOrigin <= Max)) return FLT_MAX; else return t_min;
166 UVec4 no_parallel_overlap = UVec4::sOr(Vec3::sLess(inOrigin, inBoundsMin), Vec3::sGreater(inOrigin, inBoundsMax));
167 no_intersection = UVec4::sOr(no_intersection, UVec4::sAnd(inInvDirection.mIsParallel, no_parallel_overlap));
168 no_intersection = UVec4::sOr(no_intersection, no_intersection.SplatY());
169 no_intersection = UVec4::sOr(no_intersection, no_intersection.SplatZ());
170 outMin = Vec3::sSelect(t_min, flt_max, no_intersection).GetX();
171 outMax = Vec3::sSelect(t_max, flt_min, no_intersection).GetX();
172}
173
175JPH_INLINE bool RayAABoxHits(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec3Arg inBoundsMin, Vec3Arg inBoundsMax, float inClosest)
176{
177 // Constants
178 Vec3 flt_min = Vec3::sReplicate(-FLT_MAX);
179 Vec3 flt_max = Vec3::sReplicate(FLT_MAX);
180
181 // Test against all three axes simultaneously.
182 Vec3 t1 = (inBoundsMin - inOrigin) * inInvDirection.mInvDirection;
183 Vec3 t2 = (inBoundsMax - inOrigin) * inInvDirection.mInvDirection;
184
185 // Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
186 // use the results from any directions parallel to the slab.
187 Vec3 t_min = Vec3::sSelect(Vec3::sMin(t1, t2), flt_min, inInvDirection.mIsParallel);
188 Vec3 t_max = Vec3::sSelect(Vec3::sMax(t1, t2), flt_max, inInvDirection.mIsParallel);
189
190 // t_min.xyz = maximum(t_min.x, t_min.y, t_min.z);
191 t_min = Vec3::sMax(t_min, t_min.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>());
192 t_min = Vec3::sMax(t_min, t_min.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y>());
193
194 // t_max.xyz = minimum(t_max.x, t_max.y, t_max.z);
195 t_max = Vec3::sMin(t_max, t_max.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>());
196 t_max = Vec3::sMin(t_max, t_max.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y>());
197
198 // if (t_min > t_max) return false;
199 UVec4 no_intersection = Vec3::sGreater(t_min, t_max);
200
201 // if (t_max < 0.0f) return false;
202 no_intersection = UVec4::sOr(no_intersection, Vec3::sLess(t_max, Vec3::sZero()));
203
204 // if (t_min > inClosest) return false;
205 no_intersection = UVec4::sOr(no_intersection, Vec3::sGreater(t_min, Vec3::sReplicate(inClosest)));
206
207 // if (inInvDirection.mIsParallel && !(Min <= inOrigin && inOrigin <= Max)) return false; else return true;
208 UVec4 no_parallel_overlap = UVec4::sOr(Vec3::sLess(inOrigin, inBoundsMin), Vec3::sGreater(inOrigin, inBoundsMax));
209 no_intersection = UVec4::sOr(no_intersection, UVec4::sAnd(inInvDirection.mIsParallel, no_parallel_overlap));
210
211 return !no_intersection.TestAnyXYZTrue();
212}
213
216JPH_INLINE bool RayAABoxHits(Vec3Arg inOrigin, Vec3Arg inDirection, Vec3Arg inBoundsMin, Vec3Arg inBoundsMax)
217{
218 Vec3 extents = inBoundsMax - inBoundsMin;
219
220 Vec3 diff = 2.0f * inOrigin - inBoundsMin - inBoundsMax;
221 Vec3 abs_diff = diff.Abs();
222
223 UVec4 no_intersection = UVec4::sAnd(Vec3::sGreater(abs_diff, extents), Vec3::sGreaterOrEqual(diff * inDirection, Vec3::sZero()));
224
225 Vec3 abs_dir = inDirection.Abs();
226 Vec3 abs_dir_yzz = abs_dir.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z>();
227 Vec3 abs_dir_xyx = abs_dir.Swizzle<SWIZZLE_X, SWIZZLE_Y, SWIZZLE_X>();
228
229 Vec3 extents_yzz = extents.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z>();
230 Vec3 extents_xyx = extents.Swizzle<SWIZZLE_X, SWIZZLE_Y, SWIZZLE_X>();
231
232 Vec3 diff_yzx = diff.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>();
233
234 Vec3 dir_yzx = inDirection.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>();
235
236 no_intersection = UVec4::sOr(no_intersection, Vec3::sGreater((inDirection * diff_yzx - dir_yzx * diff).Abs(), extents_xyx * abs_dir_yzz + extents_yzz * abs_dir_xyx));
237
238 return !no_intersection.TestAnyXYZTrue();
239}
240
#define JPH_NAMESPACE_END
Definition Core.h:414
#define JPH_NAMESPACE_BEGIN
Definition Core.h:408
JPH_INLINE Vec4 RayAABox4(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ)
Definition RayAABox.h:72
JPH_INLINE bool RayAABoxHits(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec3Arg inBoundsMin, Vec3Arg inBoundsMax, float inClosest)
Intersect AABB with ray, returns true if there is a hit closer than inClosest.
Definition RayAABox.h:175
JPH_INLINE float RayAABox(Vec3Arg inOrigin, const RayInvDirection &inInvDirection, Vec3Arg inBoundsMin, Vec3Arg inBoundsMax)
Definition RayAABox.h:33
@ SWIZZLE_Z
Use the Z component.
Definition Swizzle.h:14
@ SWIZZLE_X
Use the X component.
Definition Swizzle.h:12
@ SWIZZLE_Y
Use the Y component.
Definition Swizzle.h:13
Helper structure holding the reciprocal of a ray for Ray vs AABox testing.
Definition RayAABox.h:11
UVec4 mIsParallel
for each component if it is parallel to the coordinate axis
Definition RayAABox.h:28
Vec3 mInvDirection
1 / ray direction
Definition RayAABox.h:27
RayInvDirection(Vec3Arg inDirection)
Definition RayAABox.h:15
RayInvDirection()=default
Constructors.
void Set(Vec3Arg inDirection)
Set reciprocal from ray direction.
Definition RayAABox.h:18
Definition UVec4.h:12
JPH_INLINE UVec4 SplatY() const
Replicate the Y component to all components.
Definition UVec4.inl:296
JPH_INLINE UVec4 SplatX() const
Replicate the X component to all components.
Definition UVec4.inl:285
JPH_INLINE bool TestAnyXYZTrue() const
Test if any of X, Y or Z components are true (true is when highest bit of component is set)
Definition UVec4.inl:403
static JPH_INLINE UVec4 sAnd(UVec4Arg inV1, UVec4Arg inV2)
Logical and (component wise)
Definition UVec4.inl:202
static JPH_INLINE UVec4 sOr(UVec4Arg inV1, UVec4Arg inV2)
Logical or (component wise)
Definition UVec4.inl:174
JPH_INLINE UVec4 SplatZ() const
Replicate the Z component to all components.
Definition UVec4.inl:307
Definition Vec3.h:17
static JPH_INLINE Vec3 sMax(Vec3Arg inV1, Vec3Arg inV2)
Return the maximum of each of the components.
Definition Vec3.inl:155
JPH_INLINE Vec4 SplatX() const
Replicate the X component to all components.
Definition Vec3.inl:529
static JPH_INLINE Vec3 sMin(Vec3Arg inV1, Vec3Arg inV2)
Return the minimum value of each of the components.
Definition Vec3.inl:142
JPH_INLINE float GetX() const
Get individual components.
Definition Vec3.h:124
static JPH_INLINE UVec4 sGreaterOrEqual(Vec3Arg inV1, Vec3Arg inV2)
Greater than or equal (component wise)
Definition Vec3.inl:233
static JPH_INLINE UVec4 sLessOrEqual(Vec3Arg inV1, Vec3Arg inV2)
Less than or equal (component wise)
Definition Vec3.inl:203
JPH_INLINE Vec3 Abs() const
Return the absolute value of each of the components.
Definition Vec3.inl:572
JPH_INLINE Vec3 Reciprocal() const
Reciprocal vector (1 / value) for each of the components.
Definition Vec3.inl:585
JPH_INLINE Vec4 SplatZ() const
Replicate the Z component to all components.
Definition Vec3.inl:551
static JPH_INLINE UVec4 sGreater(Vec3Arg inV1, Vec3Arg inV2)
Greater than (component wise)
Definition Vec3.inl:218
JPH_INLINE Vec4 SplatY() const
Replicate the Y component to all components.
Definition Vec3.inl:540
static JPH_INLINE Vec3 sZero()
Vector with all zeros.
Definition Vec3.inl:103
static JPH_INLINE UVec4 sLess(Vec3Arg inV1, Vec3Arg inV2)
Less than (component wise)
Definition Vec3.inl:188
static JPH_INLINE Vec3 sReplicate(float inV)
Replicate inV across all components.
Definition Vec3.inl:114
static JPH_INLINE Vec3 sSelect(Vec3Arg inNotSet, Vec3Arg inSet, UVec4Arg inControl)
Component wise select, returns inNotSet when highest bit of inControl = 0 and inSet when highest bit ...
Definition Vec3.inl:265
JPH_INLINE Vec3 Swizzle() const
Swizzle the elements in inV.
Definition Vec4.h:14
static JPH_INLINE UVec4 sGreater(Vec4Arg inV1, Vec4Arg inV2)
Greater than (component wise)
Definition Vec4.inl:208
static JPH_INLINE UVec4 sLess(Vec4Arg inV1, Vec4Arg inV2)
Less than (component wise)
Definition Vec4.inl:180
static JPH_INLINE Vec4 sMin(Vec4Arg inV1, Vec4Arg inV2)
Return the minimum value of each of the components.
Definition Vec4.inl:138
static JPH_INLINE Vec4 sZero()
Vector with all zeros.
Definition Vec4.inl:63
static JPH_INLINE Vec4 sMax(Vec4Arg inV1, Vec4Arg inV2)
Return the maximum of each of the components.
Definition Vec4.inl:152
static JPH_INLINE Vec4 sSelect(Vec4Arg inNotSet, Vec4Arg inSet, UVec4Arg inControl)
Component wise select, returns inNotSet when highest bit of inControl = 0 and inSet when highest bit ...
Definition Vec4.inl:254
static JPH_INLINE Vec4 sReplicate(float inV)
Replicate inV across all components.
Definition Vec4.inl:74