Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Vec3.inl
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#include <Jolt/Math/Vec4.h>
6#include <Jolt/Math/UVec4.h>
8
10#include <random>
12
13// Create a std::hash/JPH::Hash for Vec3
14JPH_MAKE_HASHABLE(JPH::Vec3, t.GetX(), t.GetY(), t.GetZ())
15
17
18void Vec3::CheckW() const
19{
20#ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
21 // Avoid asserts when both components are NaN
22 JPH_ASSERT(reinterpret_cast<const uint32 *>(mF32)[2] == reinterpret_cast<const uint32 *>(mF32)[3]);
23#endif // JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
24}
25
26JPH_INLINE Vec3::Type Vec3::sFixW(Type inValue)
27{
28#ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
29 #if defined(JPH_USE_SSE)
30 return _mm_shuffle_ps(inValue, inValue, _MM_SHUFFLE(2, 2, 1, 0));
31 #elif defined(JPH_USE_NEON)
32 return JPH_NEON_SHUFFLE_F32x4(inValue, inValue, 0, 1, 2, 2);
33 #elif defined(JPH_USE_RVV)
34 Type value;
35 const vfloat32m1_t v = __riscv_vle32_v_f32m1(inValue.mData, 3);
36 __riscv_vse32_v_f32m1(value.mData, v, 3);
37 value.mData[3] = value.mData[2];
38 return value;
39 #else
40 Type value;
41 value.mData[0] = inValue.mData[0];
42 value.mData[1] = inValue.mData[1];
43 value.mData[2] = inValue.mData[2];
44 value.mData[3] = inValue.mData[2];
45 return value;
46 #endif
47#else
48 return inValue;
49#endif // JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
50}
51
53 mValue(sFixW(inRHS.mValue))
54{
55}
56
57Vec3::Vec3(const Float3 &inV)
58{
59#if defined(JPH_USE_SSE)
60 Type x = _mm_load_ss(&inV.x);
61 Type y = _mm_load_ss(&inV.y);
62 Type z = _mm_load_ss(&inV.z);
63 Type xy = _mm_unpacklo_ps(x, y);
64 mValue = _mm_shuffle_ps(xy, z, _MM_SHUFFLE(0, 0, 1, 0)); // Assure Z and W are the same
65#elif defined(JPH_USE_NEON)
66 float32x2_t xy = vld1_f32(&inV.x);
67 float32x2_t zz = vdup_n_f32(inV.z); // Assure Z and W are the same
68 mValue = vcombine_f32(xy, zz);
69#elif defined(JPH_USE_RVV)
70 const vfloat32m1_t v = __riscv_vle32_v_f32m1(&inV.x, 3);
71 __riscv_vse32_v_f32m1(mF32, v, 3);
72 mF32[3] = inV.z;
73#else
74 mF32[0] = inV.x;
75 mF32[1] = inV.y;
76 mF32[2] = inV.z;
77 mF32[3] = inV.z; // Not strictly needed when JPH_FLOATING_POINT_EXCEPTIONS_ENABLED is off but prevents warnings about uninitialized variables
78#endif
79}
80
81Vec3::Vec3(float inX, float inY, float inZ)
82{
83#if defined(JPH_USE_SSE)
84 mValue = _mm_set_ps(inZ, inZ, inY, inX);
85#elif defined(JPH_USE_NEON)
86 uint32x2_t xy = vcreate_u32(static_cast<uint64>(BitCast<uint32>(inX)) | (static_cast<uint64>(BitCast<uint32>(inY)) << 32));
87 uint32x2_t zz = vreinterpret_u32_f32(vdup_n_f32(inZ));
88 mValue = vreinterpretq_f32_u32(vcombine_u32(xy, zz));
89#elif defined(JPH_USE_RVV)
90 const float aggregated[4] = { inX, inY, inZ, inZ };
91 const vfloat32m1_t v = __riscv_vle32_v_f32m1(aggregated, 4);
92 __riscv_vse32_v_f32m1(mF32, v, 4);
93#else
94 mF32[0] = inX;
95 mF32[1] = inY;
96 mF32[2] = inZ;
97 mF32[3] = inZ; // Not strictly needed when JPH_FLOATING_POINT_EXCEPTIONS_ENABLED is off but prevents warnings about uninitialized variables
98#endif
99}
100
101template<uint32 SwizzleX, uint32 SwizzleY, uint32 SwizzleZ>
103{
104 static_assert(SwizzleX <= 3, "SwizzleX template parameter out of range");
105 static_assert(SwizzleY <= 3, "SwizzleY template parameter out of range");
106 static_assert(SwizzleZ <= 3, "SwizzleZ template parameter out of range");
107
108#if defined(JPH_USE_SSE)
109 return _mm_shuffle_ps(mValue, mValue, _MM_SHUFFLE(SwizzleZ, SwizzleZ, SwizzleY, SwizzleX)); // Assure Z and W are the same
110#elif defined(JPH_USE_NEON)
111 return JPH_NEON_SHUFFLE_F32x4(mValue, mValue, SwizzleX, SwizzleY, SwizzleZ, SwizzleZ);
112#elif defined(JPH_USE_RVV)
113 Vec3 v;
114 const vfloat32m1_t data = __riscv_vle32_v_f32m1(mF32, 4);
115 const uint32 stored_indices[4] = { SwizzleX, SwizzleY, SwizzleZ, SwizzleZ };
116 const vuint32m1_t index = __riscv_vle32_v_u32m1(stored_indices, 4);
117 const vfloat32m1_t swizzled = __riscv_vrgather_vv_f32m1(data, index, 4);
118 __riscv_vse32_v_f32m1(v.mF32, swizzled, 4);
119 return v;
120#else
121 return Vec3(mF32[SwizzleX], mF32[SwizzleY], mF32[SwizzleZ]);
122#endif
123}
124
126{
127#if defined(JPH_USE_SSE)
128 return _mm_setzero_ps();
129#elif defined(JPH_USE_NEON)
130 return vdupq_n_f32(0);
131#elif defined(JPH_USE_RVV)
132 Vec3 v;
133 const vfloat32m1_t zero_vec = __riscv_vfmv_v_f_f32m1(0.0f, 3);
134 __riscv_vse32_v_f32m1(v.mF32, zero_vec, 3);
135 return v;
136#else
137 return Vec3(0, 0, 0);
138#endif
139}
140
142{
143#if defined(JPH_USE_SSE)
144 return _mm_set1_ps(inV);
145#elif defined(JPH_USE_NEON)
146 return vdupq_n_f32(inV);
147#elif defined(JPH_USE_RVV)
148 Vec3 vec;
149 const vfloat32m1_t v = __riscv_vfmv_v_f_f32m1(inV, 3);
150 __riscv_vse32_v_f32m1(vec.mF32, v, 3);
151 return vec;
152#else
153 return Vec3(inV, inV, inV);
154#endif
155}
156
158{
159 return sReplicate(1.0f);
160}
161
163{
164 return sReplicate(numeric_limits<float>::quiet_NaN());
165}
166
168{
169#if defined(JPH_USE_SSE)
170 Type v = _mm_loadu_ps(&inV.x);
171#elif defined(JPH_USE_NEON)
172 Type v = vld1q_f32(&inV.x);
173#elif defined(JPH_USE_RVV)
174 Type v;
175 const vfloat32m1_t rvv = __riscv_vle32_v_f32m1(&inV.x, 3);
176 __riscv_vse32_v_f32m1(v.mData, rvv, 3);
177#else
178 Type v = { inV.x, inV.y, inV.z };
179#endif
180 return sFixW(v);
181}
182
184{
185#if defined(JPH_USE_SSE)
186 return _mm_min_ps(inV1.mValue, inV2.mValue);
187#elif defined(JPH_USE_NEON)
188 return vminq_f32(inV1.mValue, inV2.mValue);
189#elif defined(JPH_USE_RVV)
190 Vec3 res;
191 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
192 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
193 const vfloat32m1_t min = __riscv_vfmin_vv_f32m1(v1, v2, 3);
194 __riscv_vse32_v_f32m1(res.mF32, min, 3);
195 return res;
196#else
197 return Vec3(min(inV1.mF32[0], inV2.mF32[0]),
198 min(inV1.mF32[1], inV2.mF32[1]),
199 min(inV1.mF32[2], inV2.mF32[2]));
200#endif
201}
202
204{
205#if defined(JPH_USE_SSE)
206 return _mm_max_ps(inV1.mValue, inV2.mValue);
207#elif defined(JPH_USE_NEON)
208 return vmaxq_f32(inV1.mValue, inV2.mValue);
209#elif defined(JPH_USE_RVV)
210 Vec3 res;
211 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
212 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
213 const vfloat32m1_t max = __riscv_vfmax_vv_f32m1(v1, v2, 3);
214 __riscv_vse32_v_f32m1(res.mF32, max, 3);
215 return res;
216#else
217 return Vec3(max(inV1.mF32[0], inV2.mF32[0]),
218 max(inV1.mF32[1], inV2.mF32[1]),
219 max(inV1.mF32[2], inV2.mF32[2]));
220#endif
221}
222
224{
225 return sMax(sMin(inV, inMax), inMin);
226}
227
229{
230#if defined(JPH_USE_SSE)
231 return _mm_castps_si128(_mm_cmpeq_ps(inV1.mValue, inV2.mValue));
232#elif defined(JPH_USE_NEON)
233 return vceqq_f32(inV1.mValue, inV2.mValue);
234#elif defined(JPH_USE_RVV)
235 UVec4 res;
236 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
237 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
238 const vbool32_t mask = __riscv_vmfeq_vv_f32m1_b32(v1, v2, 3);
239 const vuint32m1_t zeros = __riscv_vmv_v_x_u32m1(0x0, 3);
240 const vuint32m1_t merged = __riscv_vmerge_vxm_u32m1(zeros, 0xFFFFFFFF, mask, 3);
241 __riscv_vse32_v_u32m1(res.mU32, merged, 3);
242 res.mU32[3] = res.mU32[2];
243 return res;
244#else
245 uint32 z = inV1.mF32[2] == inV2.mF32[2]? 0xffffffffu : 0;
246 return UVec4(inV1.mF32[0] == inV2.mF32[0]? 0xffffffffu : 0,
247 inV1.mF32[1] == inV2.mF32[1]? 0xffffffffu : 0,
248 z,
249 z);
250#endif
251}
252
254{
255#if defined(JPH_USE_SSE)
256 return _mm_castps_si128(_mm_cmplt_ps(inV1.mValue, inV2.mValue));
257#elif defined(JPH_USE_NEON)
258 return vcltq_f32(inV1.mValue, inV2.mValue);
259#elif defined(JPH_USE_RVV)
260 UVec4 res;
261 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
262 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
263 const vbool32_t mask = __riscv_vmflt_vv_f32m1_b32(v1, v2, 3);
264 const vuint32m1_t zeros = __riscv_vmv_v_x_u32m1(0x0, 3);
265 const vuint32m1_t merged = __riscv_vmerge_vxm_u32m1(zeros, 0xFFFFFFFF, mask, 3);
266 __riscv_vse32_v_u32m1(res.mU32, merged, 3);
267 res.mU32[3] = res.mU32[2];
268 return res;
269#else
270 uint32 z = inV1.mF32[2] < inV2.mF32[2]? 0xffffffffu : 0;
271 return UVec4(inV1.mF32[0] < inV2.mF32[0]? 0xffffffffu : 0,
272 inV1.mF32[1] < inV2.mF32[1]? 0xffffffffu : 0,
273 z,
274 z);
275#endif
276}
277
279{
280#if defined(JPH_USE_SSE)
281 return _mm_castps_si128(_mm_cmple_ps(inV1.mValue, inV2.mValue));
282#elif defined(JPH_USE_NEON)
283 return vcleq_f32(inV1.mValue, inV2.mValue);
284#elif defined(JPH_USE_RVV)
285 UVec4 res;
286 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
287 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
288 const vbool32_t mask = __riscv_vmfle_vv_f32m1_b32(v1, v2, 3);
289 const vuint32m1_t zeros = __riscv_vmv_v_x_u32m1(0x0, 3);
290 const vuint32m1_t merged = __riscv_vmerge_vxm_u32m1(zeros, 0xFFFFFFFF, mask, 3);
291 __riscv_vse32_v_u32m1(res.mU32, merged, 3);
292 res.mU32[3] = res.mU32[2];
293 return res;
294#else
295 uint32 z = inV1.mF32[2] <= inV2.mF32[2]? 0xffffffffu : 0;
296 return UVec4(inV1.mF32[0] <= inV2.mF32[0]? 0xffffffffu : 0,
297 inV1.mF32[1] <= inV2.mF32[1]? 0xffffffffu : 0,
298 z,
299 z);
300#endif
301}
302
304{
305#if defined(JPH_USE_SSE)
306 return _mm_castps_si128(_mm_cmpgt_ps(inV1.mValue, inV2.mValue));
307#elif defined(JPH_USE_NEON)
308 return vcgtq_f32(inV1.mValue, inV2.mValue);
309#elif defined(JPH_USE_RVV)
310 UVec4 res;
311 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
312 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
313 const vbool32_t mask = __riscv_vmfgt_vv_f32m1_b32(v1, v2, 3);
314 const vuint32m1_t zeros = __riscv_vmv_v_x_u32m1(0x0, 3);
315 const vuint32m1_t merged = __riscv_vmerge_vxm_u32m1(zeros, 0xFFFFFFFF, mask, 3);
316 __riscv_vse32_v_u32m1(res.mU32, merged, 3);
317 res.mU32[3] = res.mU32[2];
318 return res;
319#else
320 uint32 z = inV1.mF32[2] > inV2.mF32[2]? 0xffffffffu : 0;
321 return UVec4(inV1.mF32[0] > inV2.mF32[0]? 0xffffffffu : 0,
322 inV1.mF32[1] > inV2.mF32[1]? 0xffffffffu : 0,
323 z,
324 z);
325#endif
326}
327
329{
330#if defined(JPH_USE_SSE)
331 return _mm_castps_si128(_mm_cmpge_ps(inV1.mValue, inV2.mValue));
332#elif defined(JPH_USE_NEON)
333 return vcgeq_f32(inV1.mValue, inV2.mValue);
334#elif defined(JPH_USE_RVV)
335 UVec4 res;
336 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV1.mF32, 3);
337 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
338 const vbool32_t mask = __riscv_vmfge_vv_f32m1_b32(v1, v2, 3);
339 const vuint32m1_t zeros = __riscv_vmv_v_x_u32m1(0x0, 3);
340 const vuint32m1_t merged = __riscv_vmerge_vxm_u32m1(zeros, 0xFFFFFFFF, mask, 3);
341 __riscv_vse32_v_u32m1(res.mU32, merged, 3);
342 res.mU32[3] = res.mU32[2];
343 return res;
344#else
345 uint32 z = inV1.mF32[2] >= inV2.mF32[2]? 0xffffffffu : 0;
346 return UVec4(inV1.mF32[0] >= inV2.mF32[0]? 0xffffffffu : 0,
347 inV1.mF32[1] >= inV2.mF32[1]? 0xffffffffu : 0,
348 z,
349 z);
350#endif
351}
352
354{
355#if defined(JPH_USE_SSE)
356 #ifdef JPH_USE_FMADD
357 return _mm_fmadd_ps(inMul1.mValue, inMul2.mValue, inAdd.mValue);
358 #else
359 return _mm_add_ps(_mm_mul_ps(inMul1.mValue, inMul2.mValue), inAdd.mValue);
360 #endif
361#elif defined(JPH_USE_NEON)
362 return vmlaq_f32(inAdd.mValue, inMul1.mValue, inMul2.mValue);
363#elif defined(JPH_USE_RVV)
364 Vec3 res;
365 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inMul1.mF32, 3);
366 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inMul2.mF32, 3);
367 const vfloat32m1_t rvv_add = __riscv_vle32_v_f32m1(inAdd.mF32, 3);
368 const vfloat32m1_t fmadd = __riscv_vfmacc_vv_f32m1(rvv_add, v1, v2, 3);
369 __riscv_vse32_v_f32m1(res.mF32, fmadd, 3);
370 return res;
371#else
372 return Vec3(inMul1.mF32[0] * inMul2.mF32[0] + inAdd.mF32[0],
373 inMul1.mF32[1] * inMul2.mF32[1] + inAdd.mF32[1],
374 inMul1.mF32[2] * inMul2.mF32[2] + inAdd.mF32[2]);
375#endif
376}
377
378Vec3 Vec3::sSelect(Vec3Arg inNotSet, Vec3Arg inSet, UVec4Arg inControl)
379{
380#if defined(JPH_USE_SSE4_1) && !defined(JPH_PLATFORM_WASM) // _mm_blendv_ps has problems on FireFox
381 Type v = _mm_blendv_ps(inNotSet.mValue, inSet.mValue, _mm_castsi128_ps(inControl.mValue));
382 return sFixW(v);
383#elif defined(JPH_USE_SSE)
384 __m128 is_set = _mm_castsi128_ps(_mm_srai_epi32(inControl.mValue, 31));
385 Type v = _mm_or_ps(_mm_and_ps(is_set, inSet.mValue), _mm_andnot_ps(is_set, inNotSet.mValue));
386 return sFixW(v);
387#elif defined(JPH_USE_NEON)
388 Type v = vbslq_f32(vreinterpretq_u32_s32(vshrq_n_s32(vreinterpretq_s32_u32(inControl.mValue), 31)), inSet.mValue, inNotSet.mValue);
389 return sFixW(v);
390#elif defined(JPH_USE_RVV)
391 Vec3 masked;
392 const vuint32m1_t control = __riscv_vle32_v_u32m1(inControl.mU32, 3);
393 const vfloat32m1_t not_set = __riscv_vle32_v_f32m1(inNotSet.mF32, 3);
394 const vfloat32m1_t set = __riscv_vle32_v_f32m1(inSet.mF32, 3);
395
396 // Generate RVV bool mask from UVec4
397 const vuint32m1_t r = __riscv_vand_vx_u32m1(control, 0x80000000u, 3);
398 const vbool32_t rvv_mask = __riscv_vmsne_vx_u32m1_b32(r, 0x0, 3);
399 const vfloat32m1_t merged = __riscv_vmerge_vvm_f32m1(not_set, set, rvv_mask, 3);
400 __riscv_vse32_v_f32m1(masked.mF32, merged, 3);
401 return masked;
402#else
403 Vec3 result;
404 for (int i = 0; i < 3; i++)
405 result.mF32[i] = (inControl.mU32[i] & 0x80000000u) ? inSet.mF32[i] : inNotSet.mF32[i];
406#ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
407 result.mF32[3] = result.mF32[2];
408#endif // JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
409 return result;
410#endif
411}
412
414{
415#if defined(JPH_USE_SSE)
416 return _mm_or_ps(inV1.mValue, inV2.mValue);
417#elif defined(JPH_USE_NEON)
418 return vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(inV1.mValue), vreinterpretq_u32_f32(inV2.mValue)));
419#elif defined(JPH_USE_RVV)
420 Vec3 or_result;
421 const vuint32m1_t v1 = __riscv_vle32_v_u32m1(reinterpret_cast<const uint32 *>(inV1.mF32), 3);
422 const vuint32m1_t v2 = __riscv_vle32_v_u32m1(reinterpret_cast<const uint32 *>(inV2.mF32), 3);
423 const vuint32m1_t res = __riscv_vor_vv_u32m1(v1, v2, 3);
424 __riscv_vse32_v_u32m1(reinterpret_cast<uint32 *>(or_result.mF32), res, 3);
425 return or_result;
426#else
428#endif
429}
430
432{
433#if defined(JPH_USE_SSE)
434 return _mm_xor_ps(inV1.mValue, inV2.mValue);
435#elif defined(JPH_USE_NEON)
436 return vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(inV1.mValue), vreinterpretq_u32_f32(inV2.mValue)));
437#elif defined(JPH_USE_RVV)
438 Vec3 xor_result;
439 const vuint32m1_t v1 = __riscv_vle32_v_u32m1(reinterpret_cast<const uint32 *>(inV1.mF32), 3);
440 const vuint32m1_t v2 = __riscv_vle32_v_u32m1(reinterpret_cast<const uint32 *>(inV2.mF32), 3);
441 const vuint32m1_t res = __riscv_vxor_vv_u32m1(v1, v2, 3);
442 __riscv_vse32_v_u32m1(reinterpret_cast<uint32 *>(xor_result.mF32), res, 3);
443 return xor_result;
444#else
446#endif
447}
448
450{
451#if defined(JPH_USE_SSE)
452 return _mm_and_ps(inV1.mValue, inV2.mValue);
453#elif defined(JPH_USE_NEON)
454 return vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(inV1.mValue), vreinterpretq_u32_f32(inV2.mValue)));
455#elif defined(JPH_USE_RVV)
456 Vec3 and_result;
457 const vuint32m1_t v1 = __riscv_vle32_v_u32m1(reinterpret_cast<const uint32 *>(inV1.mF32), 3);
458 const vuint32m1_t v2 = __riscv_vle32_v_u32m1(reinterpret_cast<const uint32 *>(inV2.mF32), 3);
459 const vuint32m1_t res = __riscv_vand_vv_u32m1(v1, v2, 3);
460 __riscv_vse32_v_u32m1(reinterpret_cast<uint32 *>(and_result.mF32), res, 3);
461 return and_result;
462#else
464#endif
465}
466
467Vec3 Vec3::sUnitSpherical(float inTheta, float inPhi)
468{
469 Vec4 s, c;
470 Vec4(inTheta, inPhi, 0, 0).SinCos(s, c);
471 return Vec3(s.GetX() * c.GetY(), s.GetX() * s.GetY(), c.GetX());
472}
473
474template <class Random>
475Vec3 Vec3::sRandom(Random &inRandom)
476{
477 std::uniform_real_distribution<float> zero_to_one(0.0f, 1.0f);
478 float theta = JPH_PI * zero_to_one(inRandom);
479 float phi = 2.0f * JPH_PI * zero_to_one(inRandom);
480 return sUnitSpherical(theta, phi);
481}
482
484{
485 return sEquals(*this, inV2).TestAllXYZTrue();
486}
487
488bool Vec3::IsClose(Vec3Arg inV2, float inMaxDistSq) const
489{
490 return (inV2 - *this).LengthSq() <= inMaxDistSq;
491}
492
493bool Vec3::IsNearZero(float inMaxDistSq) const
494{
495 return LengthSq() <= inMaxDistSq;
496}
497
499{
500#if defined(JPH_USE_SSE)
501 return _mm_mul_ps(mValue, inV2.mValue);
502#elif defined(JPH_USE_NEON)
503 return vmulq_f32(mValue, inV2.mValue);
504#elif defined(JPH_USE_RVV)
505 Vec3 res;
506 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
507 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
508 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v1, v2, 3);
509 __riscv_vse32_v_f32m1(res.mF32, mul, 3);
510 return res;
511#else
512 return Vec3(mF32[0] * inV2.mF32[0], mF32[1] * inV2.mF32[1], mF32[2] * inV2.mF32[2]);
513#endif
514}
515
516Vec3 Vec3::operator * (float inV2) const
517{
518#if defined(JPH_USE_SSE)
519 return _mm_mul_ps(mValue, _mm_set1_ps(inV2));
520#elif defined(JPH_USE_NEON)
521 return vmulq_n_f32(mValue, inV2);
522#elif defined(JPH_USE_RVV)
523 Vec3 res;
524 const vfloat32m1_t src = __riscv_vle32_v_f32m1(mF32, 3);
525 const vfloat32m1_t mul = __riscv_vfmul_vf_f32m1(src, inV2, 3);
526 __riscv_vse32_v_f32m1(res.mF32, mul, 3);
527 return res;
528#else
529 return Vec3(mF32[0] * inV2, mF32[1] * inV2, mF32[2] * inV2);
530#endif
531}
532
533Vec3 operator * (float inV1, Vec3Arg inV2)
534{
535#if defined(JPH_USE_SSE)
536 return _mm_mul_ps(_mm_set1_ps(inV1), inV2.mValue);
537#elif defined(JPH_USE_NEON)
538 return vmulq_n_f32(inV2.mValue, inV1);
539#elif defined(JPH_USE_RVV)
540 Vec3 res;
541 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
542 const vfloat32m1_t mul = __riscv_vfmul_vf_f32m1(v1, inV1, 3);
543 __riscv_vse32_v_f32m1(res.mF32, mul, 3);
544 return res;
545#else
546 return Vec3(inV1 * inV2.mF32[0], inV1 * inV2.mF32[1], inV1 * inV2.mF32[2]);
547#endif
548}
549
550Vec3 Vec3::operator / (float inV2) const
551{
552#if defined(JPH_USE_SSE)
553 return _mm_div_ps(mValue, _mm_set1_ps(inV2));
554#elif defined(JPH_USE_NEON)
555 return vdivq_f32(mValue, vdupq_n_f32(inV2));
556#elif defined(JPH_USE_RVV)
557 Vec3 res;
558 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
559 const vfloat32m1_t div = __riscv_vfdiv_vf_f32m1(v1, inV2, 3);
560 __riscv_vse32_v_f32m1(res.mF32, div, 3);
561 return res;
562#else
563 return Vec3(mF32[0] / inV2, mF32[1] / inV2, mF32[2] / inV2);
564#endif
565}
566
568{
569#if defined(JPH_USE_SSE)
570 mValue = _mm_mul_ps(mValue, _mm_set1_ps(inV2));
571#elif defined(JPH_USE_NEON)
572 mValue = vmulq_n_f32(mValue, inV2);
573#elif defined(JPH_USE_RVV)
574 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
575 const vfloat32m1_t res = __riscv_vfmul_vf_f32m1(v1, inV2, 3);
576 __riscv_vse32_v_f32m1(mF32, res, 3);
577#else
578 for (int i = 0; i < 3; ++i)
579 mF32[i] *= inV2;
580 #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
581 mF32[3] = mF32[2];
582 #endif
583#endif
584 return *this;
585}
586
588{
589#if defined(JPH_USE_SSE)
590 mValue = _mm_mul_ps(mValue, inV2.mValue);
591#elif defined(JPH_USE_NEON)
592 mValue = vmulq_f32(mValue, inV2.mValue);
593#elif defined(JPH_USE_RVV)
594 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
595 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
596 const vfloat32m1_t rvv_res = __riscv_vfmul_vv_f32m1(v1, v2, 3);
597 __riscv_vse32_v_f32m1(mF32, rvv_res, 3);
598#else
599 for (int i = 0; i < 3; ++i)
600 mF32[i] *= inV2.mF32[i];
601 #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
602 mF32[3] = mF32[2];
603 #endif
604#endif
605 return *this;
606}
607
609{
610#if defined(JPH_USE_SSE)
611 mValue = _mm_div_ps(mValue, _mm_set1_ps(inV2));
612#elif defined(JPH_USE_NEON)
613 mValue = vdivq_f32(mValue, vdupq_n_f32(inV2));
614#elif defined(JPH_USE_RVV)
615 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
616 const vfloat32m1_t res = __riscv_vfdiv_vf_f32m1(v, inV2, 3);
617 __riscv_vse32_v_f32m1(mF32, res, 3);
618#else
619 for (int i = 0; i < 3; ++i)
620 mF32[i] /= inV2;
621 #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
622 mF32[3] = mF32[2];
623 #endif
624#endif
625 return *this;
626}
627
629{
630#if defined(JPH_USE_SSE)
631 return _mm_add_ps(mValue, inV2.mValue);
632#elif defined(JPH_USE_NEON)
633 return vaddq_f32(mValue, inV2.mValue);
634#elif defined(JPH_USE_RVV)
635 Vec3 res;
636 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
637 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
638 const vfloat32m1_t rvv_add = __riscv_vfadd_vv_f32m1(v1, v2, 3);
639 __riscv_vse32_v_f32m1(res.mF32, rvv_add, 3);
640 return res;
641#else
642 return Vec3(mF32[0] + inV2.mF32[0], mF32[1] + inV2.mF32[1], mF32[2] + inV2.mF32[2]);
643#endif
644}
645
647{
648#if defined(JPH_USE_SSE)
649 mValue = _mm_add_ps(mValue, inV2.mValue);
650#elif defined(JPH_USE_NEON)
651 mValue = vaddq_f32(mValue, inV2.mValue);
652#elif defined(JPH_USE_RVV)
653 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
654 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
655 const vfloat32m1_t rvv_add = __riscv_vfadd_vv_f32m1(v1, v2, 3);
656 __riscv_vse32_v_f32m1(mF32, rvv_add, 3);
657#else
658 for (int i = 0; i < 3; ++i)
659 mF32[i] += inV2.mF32[i];
660 #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
661 mF32[3] = mF32[2];
662 #endif
663#endif
664 return *this;
665}
666
668{
669#if defined(JPH_USE_SSE)
670 return _mm_sub_ps(_mm_setzero_ps(), mValue);
671#elif defined(JPH_USE_NEON)
672 #ifdef JPH_CROSS_PLATFORM_DETERMINISTIC
673 return vsubq_f32(vdupq_n_f32(0), mValue);
674 #else
675 return vnegq_f32(mValue);
676 #endif
677#elif defined(JPH_USE_RVV)
678 #ifdef JPH_CROSS_PLATFORM_DETERMINISTIC
679 Vec3 res;
680 const vfloat32m1_t rvv_zero = __riscv_vfmv_v_f_f32m1(0.0f, 3);
681 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
682 const vfloat32m1_t rvv_neg = __riscv_vfsub_vv_f32m1(rvv_zero, v, 3);
683 __riscv_vse32_v_f32m1(res.mF32, rvv_neg, 3);
684 return res;
685 #else
686 Vec3 res;
687 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
688 const vfloat32m1_t rvv_neg = __riscv_vfsgnjn_vv_f32m1(v, v, 3);
689 __riscv_vse32_v_f32m1(res.mF32, rvv_neg, 3);
690 return res;
691 #endif
692#else
693 #ifdef JPH_CROSS_PLATFORM_DETERMINISTIC
694 return Vec3(0.0f - mF32[0], 0.0f - mF32[1], 0.0f - mF32[2]);
695 #else
696 return Vec3(-mF32[0], -mF32[1], -mF32[2]);
697 #endif
698#endif
699}
700
702{
703#if defined(JPH_USE_SSE)
704 return _mm_sub_ps(mValue, inV2.mValue);
705#elif defined(JPH_USE_NEON)
706 return vsubq_f32(mValue, inV2.mValue);
707#elif defined(JPH_USE_RVV)
708 Vec3 res;
709 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
710 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
711 const vfloat32m1_t rvv_sub = __riscv_vfsub_vv_f32m1(v1, v2, 3);
712 __riscv_vse32_v_f32m1(res.mF32, rvv_sub, 3);
713 return res;
714#else
715 return Vec3(mF32[0] - inV2.mF32[0], mF32[1] - inV2.mF32[1], mF32[2] - inV2.mF32[2]);
716#endif
717}
718
720{
721#if defined(JPH_USE_SSE)
722 mValue = _mm_sub_ps(mValue, inV2.mValue);
723#elif defined(JPH_USE_NEON)
724 mValue = vsubq_f32(mValue, inV2.mValue);
725#elif defined(JPH_USE_RVV)
726 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
727 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
728 const vfloat32m1_t rvv_sub = __riscv_vfsub_vv_f32m1(v1, v2, 3);
729 __riscv_vse32_v_f32m1(mF32, rvv_sub, 3);
730#else
731 for (int i = 0; i < 3; ++i)
732 mF32[i] -= inV2.mF32[i];
733 #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
734 mF32[3] = mF32[2];
735 #endif
736#endif
737 return *this;
738}
739
741{
742 inV2.CheckW(); // Check W equals Z to avoid div by zero
743#if defined(JPH_USE_SSE)
744 return _mm_div_ps(mValue, inV2.mValue);
745#elif defined(JPH_USE_NEON)
746 return vdivq_f32(mValue, inV2.mValue);
747#elif defined(JPH_USE_RVV)
748 Vec3 res;
749 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
750 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
751 const vfloat32m1_t rvv_div = __riscv_vfdiv_vv_f32m1(v1, v2, 3);
752 __riscv_vse32_v_f32m1(res.mF32, rvv_div, 3);
753 return res;
754#else
755 return Vec3(mF32[0] / inV2.mF32[0], mF32[1] / inV2.mF32[1], mF32[2] / inV2.mF32[2]);
756#endif
757}
758
760{
761#if defined(JPH_USE_SSE)
762 return _mm_shuffle_ps(mValue, mValue, _MM_SHUFFLE(0, 0, 0, 0));
763#elif defined(JPH_USE_NEON)
764 return vdupq_laneq_f32(mValue, 0);
765#elif defined(JPH_USE_RVV)
766 Vec4 vec;
767 const vfloat32m1_t splat = __riscv_vfmv_v_f_f32m1(mF32[0], 4);
768 __riscv_vse32_v_f32m1(vec.mF32, splat, 4);
769 return vec;
770#else
771 return Vec4(mF32[0], mF32[0], mF32[0], mF32[0]);
772#endif
773}
774
776{
777#if defined(JPH_USE_SSE)
778 return _mm_shuffle_ps(mValue, mValue, _MM_SHUFFLE(1, 1, 1, 1));
779#elif defined(JPH_USE_NEON)
780 return vdupq_laneq_f32(mValue, 1);
781#elif defined(JPH_USE_RVV)
782 Vec4 vec;
783 const vfloat32m1_t splat = __riscv_vfmv_v_f_f32m1(mF32[1], 4);
784 __riscv_vse32_v_f32m1(vec.mF32, splat, 4);
785 return vec;
786#else
787 return Vec4(mF32[1], mF32[1], mF32[1], mF32[1]);
788#endif
789}
790
792{
793#if defined(JPH_USE_SSE)
794 return _mm_shuffle_ps(mValue, mValue, _MM_SHUFFLE(2, 2, 2, 2));
795#elif defined(JPH_USE_NEON)
796 return vdupq_laneq_f32(mValue, 2);
797#elif defined(JPH_USE_RVV)
798 Vec4 vec;
799 const vfloat32m1_t splat = __riscv_vfmv_v_f_f32m1(mF32[2], 4);
800 __riscv_vse32_v_f32m1(vec.mF32, splat, 4);
801 return vec;
802#else
803 return Vec4(mF32[2], mF32[2], mF32[2], mF32[2]);
804#endif
805}
806
808{
809 return GetX() < GetY() ? (GetZ() < GetX() ? 2 : 0) : (GetZ() < GetY() ? 2 : 1);
810}
811
813{
814 return GetX() > GetY() ? (GetZ() > GetX() ? 2 : 0) : (GetZ() > GetY() ? 2 : 1);
815}
816
818{
819#if defined(JPH_USE_AVX512)
820 return _mm_range_ps(mValue, mValue, 0b1000);
821#elif defined(JPH_USE_SSE)
822 return _mm_max_ps(_mm_sub_ps(_mm_setzero_ps(), mValue), mValue);
823#elif defined(JPH_USE_NEON)
824 return vabsq_f32(mValue);
825#elif defined(JPH_USE_RVV)
826 Vec3 res;
827 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
828 const vfloat32m1_t rvv_abs = __riscv_vfsgnj_vf_f32m1(v, 1.0, 3);
829 __riscv_vse32_v_f32m1(res.mF32, rvv_abs, 3);
830 return res;
831#else
832 return Vec3(abs(mF32[0]), abs(mF32[1]), abs(mF32[2]));
833#endif
834}
835
837{
838 return sOne() / mValue;
839}
840
842{
843#if defined(JPH_USE_SSE)
844 Type t1 = _mm_shuffle_ps(inV2.mValue, inV2.mValue, _MM_SHUFFLE(0, 0, 2, 1)); // Assure Z and W are the same
845 t1 = _mm_mul_ps(t1, mValue);
846 Type t2 = _mm_shuffle_ps(mValue, mValue, _MM_SHUFFLE(0, 0, 2, 1)); // Assure Z and W are the same
847 t2 = _mm_mul_ps(t2, inV2.mValue);
848 Type t3 = _mm_sub_ps(t1, t2);
849 return _mm_shuffle_ps(t3, t3, _MM_SHUFFLE(0, 0, 2, 1)); // Assure Z and W are the same
850#elif defined(JPH_USE_NEON)
851 Type t1 = JPH_NEON_SHUFFLE_F32x4(inV2.mValue, inV2.mValue, 1, 2, 0, 0); // Assure Z and W are the same
852 t1 = vmulq_f32(t1, mValue);
853 Type t2 = JPH_NEON_SHUFFLE_F32x4(mValue, mValue, 1, 2, 0, 0); // Assure Z and W are the same
854 t2 = vmulq_f32(t2, inV2.mValue);
855 Type t3 = vsubq_f32(t1, t2);
856 return JPH_NEON_SHUFFLE_F32x4(t3, t3, 1, 2, 0, 0); // Assure Z and W are the same
857#elif defined(JPH_USE_RVV)
858 const uint32 indices[3] = { 1, 2, 0 };
859 const vuint32m1_t gather_indices = __riscv_vle32_v_u32m1(indices, 3);
860 const vfloat32m1_t v0 = __riscv_vle32_v_f32m1(mF32, 3);
861 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
862 vfloat32m1_t t0 = __riscv_vrgather_vv_f32m1(v1, gather_indices, 3);
863 t0 = __riscv_vfmul_vv_f32m1(t0, v0, 3);
864 vfloat32m1_t t1 = __riscv_vrgather_vv_f32m1(v0, gather_indices, 3);
865 t1 = __riscv_vfmul_vv_f32m1(t1, v1, 3);
866 const vfloat32m1_t sub = __riscv_vfsub_vv_f32m1(t0, t1, 3);
867 const vfloat32m1_t cross = __riscv_vrgather_vv_f32m1(sub, gather_indices, 3);
868
869 Vec3 cross_result;
870 __riscv_vse32_v_f32m1(cross_result.mF32, cross, 3);
871 return cross_result;
872#else
873 return Vec3(mF32[1] * inV2.mF32[2] - mF32[2] * inV2.mF32[1],
874 mF32[2] * inV2.mF32[0] - mF32[0] * inV2.mF32[2],
875 mF32[0] * inV2.mF32[1] - mF32[1] * inV2.mF32[0]);
876#endif
877}
878
880{
881#if defined(JPH_USE_SSE4_1)
882 __m128 mul = _mm_mul_ps(mValue, inV2.mValue);
883 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
884 __m128 shuf = _mm_movehdup_ps(mul);
885 __m128 sums = _mm_add_ps(mul, shuf);
886 shuf = _mm_movehl_ps(shuf, sums);
887 sums = _mm_add_ss(sums, shuf);
888 return _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(0, 0, 0, 0));
889#elif defined(JPH_USE_NEON)
890 float32x4_t mul = vmulq_f32(mValue, inV2.mValue);
891 mul = vsetq_lane_f32(0, mul, 3);
892 return vdupq_n_f32(vaddvq_f32(mul));
893#elif defined(JPH_USE_RVV)
894 Vec3 res;
895 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
896 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
897 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
898 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v1, v2, 3);
899 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
900 const float dot = __riscv_vfmv_f_s_f32m1_f32(sum);
901 const vfloat32m1_t splat = __riscv_vfmv_v_f_f32m1(dot, 3);
902 __riscv_vse32_v_f32m1(res.mF32, splat, 3);
903 return res;
904#else
905 float dot = 0.0f;
906 for (int i = 0; i < 3; i++)
907 dot += mF32[i] * inV2.mF32[i];
908 return Vec3::sReplicate(dot);
909#endif
910}
911
913{
914#if defined(JPH_USE_SSE4_1)
915 __m128 mul = _mm_mul_ps(mValue, inV2.mValue);
916 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
917 __m128 shuf = _mm_movehdup_ps(mul);
918 __m128 sums = _mm_add_ps(mul, shuf);
919 shuf = _mm_movehl_ps(shuf, sums);
920 sums = _mm_add_ss(sums, shuf);
921 return _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(0, 0, 0, 0));
922#elif defined(JPH_USE_NEON)
923 float32x4_t mul = vmulq_f32(mValue, inV2.mValue);
924 mul = vsetq_lane_f32(0, mul, 3);
925 return vdupq_n_f32(vaddvq_f32(mul));
926#elif defined(JPH_USE_RVV)
927 Vec4 res;
928 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
929 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
930 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
931 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v1, v2, 3);
932 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
933 const float dot = __riscv_vfmv_f_s_f32m1_f32(sum);
934 const vfloat32m1_t splat = __riscv_vfmv_v_f_f32m1(dot, 4);
935 __riscv_vse32_v_f32m1(res.mF32, splat, 4);
936 return res;
937#else
938 float dot = 0.0f;
939 for (int i = 0; i < 3; i++)
940 dot += mF32[i] * inV2.mF32[i];
941 return Vec4::sReplicate(dot);
942#endif
943}
944
945float Vec3::Dot(Vec3Arg inV2) const
946{
947#if defined(JPH_USE_SSE4_1)
948 __m128 mul = _mm_mul_ps(mValue, inV2.mValue);
949 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
950 __m128 shuf = _mm_movehdup_ps(mul);
951 __m128 sums = _mm_add_ps(mul, shuf);
952 shuf = _mm_movehl_ps(shuf, sums);
953 sums = _mm_add_ss(sums, shuf);
954 return _mm_cvtss_f32(sums);
955#elif defined(JPH_USE_NEON)
956 float32x4_t mul = vmulq_f32(mValue, inV2.mValue);
957 mul = vsetq_lane_f32(0, mul, 3);
958 return vaddvq_f32(mul);
959#elif defined(JPH_USE_RVV)
960 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
961 const vfloat32m1_t v1 = __riscv_vle32_v_f32m1(mF32, 3);
962 const vfloat32m1_t v2 = __riscv_vle32_v_f32m1(inV2.mF32, 3);
963 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v1, v2, 3);
964 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
965 return __riscv_vfmv_f_s_f32m1_f32(sum);
966#else
967 float dot = 0.0f;
968 for (int i = 0; i < 3; i++)
969 dot += mF32[i] * inV2.mF32[i];
970 return dot;
971#endif
972}
973
974float Vec3::LengthSq() const
975{
976#if defined(JPH_USE_SSE4_1)
977 __m128 mul = _mm_mul_ps(mValue, mValue);
978 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
979 __m128 shuf = _mm_movehdup_ps(mul);
980 __m128 sums = _mm_add_ps(mul, shuf);
981 shuf = _mm_movehl_ps(shuf, sums);
982 sums = _mm_add_ss(sums, shuf);
983 return _mm_cvtss_f32(sums);
984#elif defined(JPH_USE_NEON)
985 float32x4_t mul = vmulq_f32(mValue, mValue);
986 mul = vsetq_lane_f32(0, mul, 3);
987 return vaddvq_f32(mul);
988#elif defined(JPH_USE_RVV)
989 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
990 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
991 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v, v, 3);
992 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
993 return __riscv_vfmv_f_s_f32m1_f32(sum);
994#else
995 float len_sq = 0.0f;
996 for (int i = 0; i < 3; i++)
997 len_sq += mF32[i] * mF32[i];
998 return len_sq;
999#endif
1000}
1001
1002float Vec3::Length() const
1003{
1004#if defined(JPH_USE_SSE4_1)
1005 __m128 mul = _mm_mul_ps(mValue, mValue);
1006 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
1007 __m128 shuf = _mm_movehdup_ps(mul);
1008 __m128 sums = _mm_add_ps(mul, shuf);
1009 shuf = _mm_movehl_ps(shuf, sums);
1010 sums = _mm_add_ss(sums, shuf);
1011 return _mm_cvtss_f32(_mm_sqrt_ss(sums));
1012#elif defined(JPH_USE_NEON)
1013 float32x4_t mul = vmulq_f32(mValue, mValue);
1014 mul = vsetq_lane_f32(0, mul, 3);
1015 float32x2_t sum = vdup_n_f32(vaddvq_f32(mul));
1016 return vget_lane_f32(vsqrt_f32(sum), 0);
1017#elif defined(JPH_USE_RVV)
1018 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
1019 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
1020 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v, v, 3);
1021 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
1022 const float dot = __riscv_vfmv_f_s_f32m1_f32(sum);
1023 return sqrt(dot);
1024#else
1025 return sqrt(LengthSq());
1026#endif
1027}
1028
1030{
1031#if defined(JPH_USE_SSE)
1032 return _mm_sqrt_ps(mValue);
1033#elif defined(JPH_USE_NEON)
1034 return vsqrtq_f32(mValue);
1035#elif defined(JPH_USE_RVV)
1036 Vec3 res;
1037 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
1038 const vfloat32m1_t rvv_sqrt = __riscv_vfsqrt_v_f32m1(v, 3);
1039 __riscv_vse32_v_f32m1(res.mF32, rvv_sqrt, 3);
1040 return res;
1041#else
1042 return Vec3(sqrt(mF32[0]), sqrt(mF32[1]), sqrt(mF32[2]));
1043#endif
1044}
1045
1047{
1048#if defined(JPH_USE_SSE4_1)
1049 __m128 mul = _mm_mul_ps(mValue, mValue);
1050 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
1051 __m128 shuf = _mm_movehdup_ps(mul);
1052 __m128 sums = _mm_add_ps(mul, shuf);
1053 shuf = _mm_movehl_ps(shuf, sums);
1054 sums = _mm_add_ss(sums, shuf);
1055 return _mm_div_ps(mValue, _mm_sqrt_ps(_mm_shuffle_ps(sums, sums, _MM_SHUFFLE(0, 0, 0, 0))));
1056#elif defined(JPH_USE_NEON)
1057 float32x4_t mul = vmulq_f32(mValue, mValue);
1058 mul = vsetq_lane_f32(0, mul, 3);
1059 float32x4_t sum = vdupq_n_f32(vaddvq_f32(mul));
1060 return vdivq_f32(mValue, vsqrtq_f32(sum));
1061#elif defined(JPH_USE_RVV)
1062 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
1063 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
1064 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(v, v, 3);
1065 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
1066 const float dot = __riscv_vfmv_f_s_f32m1_f32(sum);
1067 const float magnitude = sqrt(dot);
1068 const vfloat32m1_t norm_v = __riscv_vfdiv_vf_f32m1(v, magnitude, 3);
1069
1070 Vec3 res;
1071 __riscv_vse32_v_f32m1(res.mF32, norm_v, 3);
1072 return res;
1073#else
1074 return *this / Length();
1075#endif
1076}
1077
1079{
1080#if defined(JPH_USE_SSE4_1) && !defined(JPH_PLATFORM_WASM) // _mm_blendv_ps has problems on FireFox
1081 __m128 mul = _mm_mul_ps(mValue, mValue);
1082 mul = _mm_blend_ps(mul, _mm_setzero_ps(), 0x8);
1083 __m128 shuf = _mm_movehdup_ps(mul);
1084 __m128 sums = _mm_add_ps(mul, shuf);
1085 shuf = _mm_movehl_ps(shuf, sums);
1086 sums = _mm_add_ss(sums, shuf);
1087 Type len_sq = _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(0, 0, 0, 0));
1088 // clang with '-ffast-math' (which you should not use!) can generate _mm_rsqrt_ps
1089 // instructions which produce INFs/NaNs when they get a denormal float as input.
1090 // We therefore treat denormals as zero here.
1091 Type is_zero = _mm_cmple_ps(len_sq, _mm_set1_ps(FLT_MIN));
1092#ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
1093 if (_mm_movemask_ps(is_zero) == 0xf)
1094 return inZeroValue;
1095 else
1096 return _mm_div_ps(mValue, _mm_sqrt_ps(len_sq));
1097#else
1098 return _mm_blendv_ps(_mm_div_ps(mValue, _mm_sqrt_ps(len_sq)), inZeroValue.mValue, is_zero);
1099#endif // JPH_FLOATING_POINT_EXCEPTIONS_ENABLED
1100#elif defined(JPH_USE_NEON)
1101 float32x4_t mul = vmulq_f32(mValue, mValue);
1102 mul = vsetq_lane_f32(0, mul, 3);
1103 float32x4_t len_sq = vdupq_n_f32(vaddvq_f32(mul));
1104 uint32x4_t is_zero = vcleq_f32(len_sq, vdupq_n_f32(FLT_MIN));
1105 return vbslq_f32(is_zero, inZeroValue.mValue, vdivq_f32(mValue, vsqrtq_f32(len_sq)));
1106#elif defined(JPH_USE_RVV)
1107 const vfloat32m1_t src = __riscv_vle32_v_f32m1(mF32, 3);
1108 const vfloat32m1_t zeros = __riscv_vfmv_v_f_f32m1(0.0f, 3);
1109 const vfloat32m1_t mul = __riscv_vfmul_vv_f32m1(src, src, 3);
1110 const vfloat32m1_t sum = __riscv_vfredosum_vs_f32m1_f32m1(mul, zeros, 3);
1111 const float dot = __riscv_vfmv_f_s_f32m1_f32(sum);
1112 if (dot <= FLT_MIN)
1113 return inZeroValue;
1114
1115 const float length = sqrt(dot);
1116
1117 Vec3 v;
1118 const vfloat32m1_t norm = __riscv_vfdiv_vf_f32m1(src, length, 3);
1119 __riscv_vse32_v_f32m1(v.mF32, norm, 3);
1120 return v;
1121#else
1122 float len_sq = LengthSq();
1123 if (len_sq <= FLT_MIN)
1124 return inZeroValue;
1125 else
1126 return *this / sqrt(len_sq);
1127#endif
1128}
1129
1130bool Vec3::IsNormalized(float inTolerance) const
1131{
1132 return abs(LengthSq() - 1.0f) <= inTolerance;
1133}
1134
1135bool Vec3::IsNaN() const
1136{
1137#if defined(JPH_USE_AVX512)
1138 return (_mm_fpclass_ps_mask(mValue, 0b10000001) & 0x7) != 0;
1139#elif defined(JPH_USE_SSE)
1140 return (_mm_movemask_ps(_mm_cmpunord_ps(mValue, mValue)) & 0x7) != 0;
1141#elif defined(JPH_USE_NEON)
1142 uint32x4_t mask = JPH_NEON_UINT32x4(1, 1, 1, 0);
1143 uint32x4_t is_equal = vceqq_f32(mValue, mValue); // If a number is not equal to itself it's a NaN
1144 return vaddvq_u32(vandq_u32(is_equal, mask)) != 3;
1145#elif defined(JPH_USE_RVV)
1146 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
1147 const vbool32_t mask = __riscv_vmfeq_vv_f32m1_b32(v, v, 3);
1148 const uint32 eq = __riscv_vcpop_m_b32(mask, 3);
1149 return eq != 3;
1150#else
1151 return isnan(mF32[0]) || isnan(mF32[1]) || isnan(mF32[2]);
1152#endif
1153}
1154
1155void Vec3::StoreFloat3(Float3 *outV) const
1156{
1157#if defined(JPH_USE_SSE)
1158 _mm_store_ss(&outV->x, mValue);
1160 _mm_store_ss(&outV->y, t.mValue);
1162 _mm_store_ss(&outV->z, t.mValue);
1163#elif defined(JPH_USE_NEON)
1164 float32x2_t xy = vget_low_f32(mValue);
1165 vst1_f32(&outV->x, xy);
1166 vst1q_lane_f32(&outV->z, mValue, 2);
1167#elif defined(JPH_USE_RVV)
1168 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 3);
1169 __riscv_vse32_v_f32m1(&outV->x, v, 3);
1170#else
1171 outV->x = mF32[0];
1172 outV->y = mF32[1];
1173 outV->z = mF32[2];
1174#endif
1175}
1176
1178{
1179#if defined(JPH_USE_SSE)
1180 return _mm_cvttps_epi32(mValue);
1181#elif defined(JPH_USE_NEON)
1182 return vcvtq_u32_f32(mValue);
1183#elif defined(JPH_USE_RVV)
1184 UVec4 res;
1185 const vfloat32m1_t v = __riscv_vle32_v_f32m1(mF32, 4);
1186 const vuint32m1_t cast = __riscv_vfcvt_rtz_xu_f_v_u32m1(v, 4);
1187 __riscv_vse32_v_u32m1(res.mU32, cast, 4);
1188 return res;
1189#else
1190 return UVec4(uint32(mF32[0]), uint32(mF32[1]), uint32(mF32[2]), uint32(mF32[3]));
1191#endif
1192}
1193
1195{
1196#if defined(JPH_USE_SSE)
1197 return UVec4(_mm_castps_si128(mValue));
1198#elif defined(JPH_USE_NEON)
1199 return vreinterpretq_u32_f32(mValue);
1200#else
1201 return *reinterpret_cast<const UVec4 *>(this);
1202#endif
1203}
1204
1205float Vec3::ReduceMin() const
1206{
1209 return v.GetX();
1210}
1211
1212float Vec3::ReduceMax() const
1213{
1216 return v.GetX();
1217}
1218
1220{
1221 if (abs(mF32[0]) > abs(mF32[1]))
1222 {
1223 float len = sqrt(mF32[0] * mF32[0] + mF32[2] * mF32[2]);
1224 return Vec3(mF32[2], 0.0f, -mF32[0]) / len;
1225 }
1226 else
1227 {
1228 float len = sqrt(mF32[1] * mF32[1] + mF32[2] * mF32[2]);
1229 return Vec3(0.0f, mF32[2], -mF32[1]) / len;
1230 }
1231}
1232
1234{
1235#if defined(JPH_USE_AVX512)
1236 return _mm_fixupimm_ps(mValue, mValue, _mm_set1_epi32(0xA9A90A00), 0);
1237#elif defined(JPH_USE_SSE)
1238 Type minus_one = _mm_set1_ps(-1.0f);
1239 Type one = _mm_set1_ps(1.0f);
1240 return _mm_or_ps(_mm_and_ps(mValue, minus_one), one);
1241#elif defined(JPH_USE_NEON)
1242 Type minus_one = vdupq_n_f32(-1.0f);
1243 Type one = vdupq_n_f32(1.0f);
1244 return vreinterpretq_f32_u32(vorrq_u32(vandq_u32(vreinterpretq_u32_f32(mValue), vreinterpretq_u32_f32(minus_one)), vreinterpretq_u32_f32(one)));
1245#elif defined(JPH_USE_RVV)
1246 Vec3 res;
1247 const vfloat32m1_t rvv_in = __riscv_vle32_v_f32m1(mF32, 3);
1248 const vfloat32m1_t rvv_one = __riscv_vfmv_v_f_f32m1(1.0, 3);
1249 const vfloat32m1_t rvv_signs = __riscv_vfsgnj_vv_f32m1(rvv_one, rvv_in, 3);
1250 __riscv_vse32_v_f32m1(res.mF32, rvv_signs, 3);
1251 return res;
1252#else
1253 return Vec3(std::signbit(mF32[0])? -1.0f : 1.0f,
1254 std::signbit(mF32[1])? -1.0f : 1.0f,
1255 std::signbit(mF32[2])? -1.0f : 1.0f);
1256#endif
1257}
1258
1259template <int X, int Y, int Z>
1260JPH_INLINE Vec3 Vec3::FlipSign() const
1261{
1262 static_assert(X == 1 || X == -1, "X must be 1 or -1");
1263 static_assert(Y == 1 || Y == -1, "Y must be 1 or -1");
1264 static_assert(Z == 1 || Z == -1, "Z must be 1 or -1");
1265 return Vec3::sXor(*this, Vec3(X > 0? 0.0f : -0.0f, Y > 0? 0.0f : -0.0f, Z > 0? 0.0f : -0.0f));
1266}
1267
1269{
1270 constexpr float cOneOverSqrt2 = 0.70710678f;
1271 constexpr uint cNumBits = 14;
1272 constexpr uint cMask = (1 << cNumBits) - 1;
1273 constexpr uint cMaxValue = cMask - 1; // Need odd number of buckets to quantize to or else we can't encode 0
1274 constexpr float cScale = float(cMaxValue) / (2.0f * cOneOverSqrt2);
1275
1276 // Store sign bit
1277 Vec3 v = *this;
1278 uint32 max_element = v.Abs().GetHighestComponentIndex();
1279 uint32 value = 0;
1280 if (v[max_element] < 0.0f)
1281 {
1282 value = 0x80000000u;
1283 v = -v;
1284 }
1285
1286 // Store highest component
1287 value |= max_element << 29;
1288
1289 // Store the other two components in a compressed format
1290 UVec4 compressed = Vec3::sClamp((v + Vec3::sReplicate(cOneOverSqrt2)) * cScale + Vec3::sReplicate(0.5f), Vec3::sZero(), Vec3::sReplicate(cMaxValue)).ToInt();
1291 switch (max_element)
1292 {
1293 case 0:
1294 compressed = compressed.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_UNUSED, SWIZZLE_UNUSED>();
1295 break;
1296
1297 case 1:
1298 compressed = compressed.Swizzle<SWIZZLE_X, SWIZZLE_Z, SWIZZLE_UNUSED, SWIZZLE_UNUSED>();
1299 break;
1300 }
1301
1302 value |= compressed.GetX();
1303 value |= compressed.GetY() << cNumBits;
1304 return value;
1305}
1306
1308{
1309 constexpr float cOneOverSqrt2 = 0.70710678f;
1310 constexpr uint cNumBits = 14;
1311 constexpr uint cMask = (1u << cNumBits) - 1;
1312 constexpr uint cMaxValue = cMask - 1; // Need odd number of buckets to quantize to or else we can't encode 0
1313 constexpr float cScale = 2.0f * cOneOverSqrt2 / float(cMaxValue);
1314
1315 // Restore two components
1316 Vec3 v = Vec3(UVec4(inValue & cMask, (inValue >> cNumBits) & cMask, 0, 0).ToFloat()) * cScale - Vec3(cOneOverSqrt2, cOneOverSqrt2, 0.0f);
1317 JPH_ASSERT(v.GetZ() == 0.0f);
1318
1319 // Restore the highest component
1320 v.SetZ(sqrt(max(1.0f - v.LengthSq(), 0.0f)));
1321
1322 // Extract sign
1323 if ((inValue & 0x80000000u) != 0)
1324 v = -v;
1325
1326 // Swizzle the components in place
1327 switch ((inValue >> 29) & 3)
1328 {
1329 case 0:
1331 break;
1332
1333 case 1:
1335 break;
1336 }
1337
1338 return v;
1339}
1340
#define JPH_SUPPRESS_WARNINGS_STD_BEGIN
Definition Core.h:433
#define JPH_SUPPRESS_WARNINGS_STD_END
Definition Core.h:446
std::uint64_t uint64
Definition Core.h:510
unsigned int uint
Definition Core.h:505
#define JPH_NAMESPACE_END
Definition Core.h:428
std::uint32_t uint32
Definition Core.h:508
#define JPH_NAMESPACE_BEGIN
Definition Core.h:422
#define xy
Definition HLSLToCPP.h:511
#define JPH_MAKE_HASHABLE(type,...)
Definition HashCombine.h:223
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
JPH_INLINE To BitCast(const From &inValue)
Definition Math.h:192
@ SWIZZLE_Z
Use the Z component.
Definition Swizzle.h:14
@ SWIZZLE_X
Use the X component.
Definition Swizzle.h:12
@ SWIZZLE_UNUSED
We always use the Z component when we don't specifically want to initialize a value,...
Definition Swizzle.h:16
@ SWIZZLE_Y
Use the Y component.
Definition Swizzle.h:13
Vec3 operator*(float inV1, Vec3Arg inV2)
Definition Vec3.inl:533
Class that holds 3 floats. Used as a storage class. Convert to Vec3 for calculations.
Definition Float3.h:13
float y
Definition Float3.h:39
float z
Definition Float3.h:40
float x
Definition Float3.h:38
Definition UVec4.h:12
JPH_INLINE UVec4 Swizzle() const
Swizzle the elements in inV.
JPH_INLINE uint32 GetY() const
Definition UVec4.h:103
static JPH_INLINE UVec4 sAnd(UVec4Arg inV1, UVec4Arg inV2)
Logical and (component wise)
Definition UVec4.inl:292
static JPH_INLINE UVec4 sOr(UVec4Arg inV1, UVec4Arg inV2)
Logical or (component wise)
Definition UVec4.inl:250
JPH_INLINE bool TestAllXYZTrue() const
Test if X, Y and Z components are true (true is when highest bit of component is set)
Definition UVec4.inl:664
Type mValue
Definition UVec4.h:223
JPH_INLINE uint32 GetX() const
Get individual components.
Definition UVec4.h:102
static JPH_INLINE UVec4 sXor(UVec4Arg inV1, UVec4Arg inV2)
Logical xor (component wise)
Definition UVec4.inl:271
JPH_INLINE Vec4 ReinterpretAsFloat() const
Reinterpret UVec4 as a Vec4 (doesn't change the bits)
Definition UVec4.inl:527
uint32 mU32[4]
Definition UVec4.h:224
Definition Vec3.h:17
JPH_INLINE bool IsClose(Vec3Arg inV2, float inMaxDistSq=1.0e-12f) const
Test if two vectors are close.
Definition Vec3.inl:488
static JPH_INLINE Vec3 sMax(Vec3Arg inV1, Vec3Arg inV2)
Return the maximum of each of the components.
Definition Vec3.inl:203
JPH_INLINE float Dot(Vec3Arg inV2) const
Dot product.
Definition Vec3.inl:945
JPH_INLINE Vec3 Normalized() const
Normalize vector.
Definition Vec3.inl:1046
static JPH_INLINE Type sFixW(Type inValue)
Internal helper function that ensures that the Z component is replicated to the W component to preven...
Vec4::Type Type
Definition Vec3.h:27
JPH_INLINE bool operator==(Vec3Arg inV2) const
Comparison.
Definition Vec3.inl:483
JPH_INLINE Vec4 SplatX() const
Replicate the X component to all components.
Definition Vec3.inl:759
static JPH_INLINE Vec3 sMin(Vec3Arg inV1, Vec3Arg inV2)
Return the minimum value of each of the components.
Definition Vec3.inl:183
JPH_INLINE Vec3 Cross(Vec3Arg inV2) const
Cross product.
Definition Vec3.inl:841
JPH_INLINE Vec3 GetNormalizedPerpendicular() const
Get normalized vector that is perpendicular to this vector.
Definition Vec3.inl:1219
static Vec3 sRandom(Random &inRandom)
Get random unit vector.
Definition Vec3.inl:475
JPH_INLINE float GetX() const
Get individual components.
Definition Vec3.h:127
JPH_INLINE bool IsNormalized(float inTolerance=1.0e-6f) const
Test if vector is normalized.
Definition Vec3.inl:1130
static JPH_INLINE Vec3 sXor(Vec3Arg inV1, Vec3Arg inV2)
Logical xor (component wise)
Definition Vec3.inl:431
static JPH_INLINE Vec3 sDecompressUnitVector(uint32 inValue)
Decompress a unit vector from a 32 bit value.
Definition Vec3.inl:1307
JPH_INLINE float Length() const
Length of vector.
Definition Vec3.inl:1002
static JPH_INLINE UVec4 sGreaterOrEqual(Vec3Arg inV1, Vec3Arg inV2)
Greater than or equal (component wise)
Definition Vec3.inl:328
JPH_INLINE float ReduceMin() const
Get the minimum of X, Y and Z.
Definition Vec3.inl:1205
JPH_INLINE Vec3 & operator-=(Vec3Arg inV2)
Subtract two float vectors (component wise)
Definition Vec3.inl:719
JPH_INLINE float ReduceMax() const
Get the maximum of X, Y and Z.
Definition Vec3.inl:1212
static JPH_INLINE UVec4 sLessOrEqual(Vec3Arg inV1, Vec3Arg inV2)
Less than or equal (component wise)
Definition Vec3.inl:278
JPH_INLINE Vec3 operator/(float inV2) const
Divide vector by float.
Definition Vec3.inl:550
friend JPH_INLINE Vec3 operator*(float inV1, Vec3Arg inV2)
Multiply vector with float.
Definition Vec3.inl:533
JPH_INLINE int GetLowestComponentIndex() const
Get index of component with lowest value.
Definition Vec3.inl:807
JPH_INLINE Vec3 & operator/=(float inV2)
Divide vector by float.
Definition Vec3.inl:608
JPH_INLINE Vec4 DotV4(Vec3Arg inV2) const
Dot product, returns the dot product in X, Y, Z and W components.
Definition Vec3.inl:912
JPH_INLINE Vec3 Abs() const
Return the absolute value of each of the components.
Definition Vec3.inl:817
static JPH_INLINE Vec3 sOne()
Vector with all ones.
Definition Vec3.inl:157
JPH_INLINE Vec3 Reciprocal() const
Reciprocal vector (1 / value) for each of the components.
Definition Vec3.inl:836
JPH_INLINE Vec3 NormalizedOr(Vec3Arg inZeroValue) const
Normalize vector or return inZeroValue if the length of the vector is zero.
Definition Vec3.inl:1078
JPH_INLINE Vec3 FlipSign() const
Flips the signs of the components, e.g. FlipSign<-1, 1, -1>() will flip the signs of the X and Z comp...
Definition Vec3.inl:1260
JPH_INLINE Vec3 operator+(Vec3Arg inV2) const
Add two float vectors (component wise)
Definition Vec3.inl:628
JPH_INLINE uint32 CompressUnitVector() const
Compress a unit vector to a 32 bit value, precision is around 10^-4.
Definition Vec3.inl:1268
JPH_INLINE Vec4 SplatZ() const
Replicate the Z component to all components.
Definition Vec3.inl:791
static JPH_INLINE Vec3 sOr(Vec3Arg inV1, Vec3Arg inV2)
Logical or (component wise)
Definition Vec3.inl:413
static JPH_INLINE UVec4 sGreater(Vec3Arg inV1, Vec3Arg inV2)
Greater than (component wise)
Definition Vec3.inl:303
JPH_INLINE void SetZ(float inZ)
Definition Vec3.h:135
static JPH_INLINE Vec3 sAnd(Vec3Arg inV1, Vec3Arg inV2)
Logical and (component wise)
Definition Vec3.inl:449
JPH_INLINE void CheckW() const
Internal helper function that checks that W is equal to Z, so e.g. dividing by it should not generate...
static JPH_INLINE Vec3 sUnitSpherical(float inTheta, float inPhi)
Definition Vec3.inl:467
JPH_INLINE UVec4 ToInt() const
Convert each component from a float to an int.
Definition Vec3.inl:1177
Type mValue
Definition Vec3.h:299
JPH_INLINE float GetY() const
Definition Vec3.h:128
JPH_INLINE Vec4 SplatY() const
Replicate the Y component to all components.
Definition Vec3.inl:775
JPH_INLINE Vec3 operator-() const
Negate.
Definition Vec3.inl:667
JPH_INLINE void StoreFloat3(Float3 *outV) const
Store 3 floats to memory.
Definition Vec3.inl:1155
JPH_INLINE float LengthSq() const
Squared length of vector.
Definition Vec3.inl:974
float mF32[4]
Definition Vec3.h:300
static JPH_INLINE UVec4 sEquals(Vec3Arg inV1, Vec3Arg inV2)
Equals (component wise)
Definition Vec3.inl:228
JPH_INLINE bool IsNearZero(float inMaxDistSq=1.0e-12f) const
Test if vector is near zero.
Definition Vec3.inl:493
static JPH_INLINE Vec3 sZero()
Vector with all zeros.
Definition Vec3.inl:125
static JPH_INLINE UVec4 sLess(Vec3Arg inV1, Vec3Arg inV2)
Less than (component wise)
Definition Vec3.inl:253
static JPH_INLINE Vec3 sReplicate(float inV)
Replicate inV across all components.
Definition Vec3.inl:141
static JPH_INLINE Vec3 sClamp(Vec3Arg inV, Vec3Arg inMin, Vec3Arg inMax)
Clamp a vector between min and max (component wise)
Definition Vec3.inl:223
JPH_INLINE Vec3 & operator*=(float inV2)
Multiply vector with float.
Definition Vec3.inl:567
JPH_INLINE Vec3 & operator+=(Vec3Arg inV2)
Add two float vectors (component wise)
Definition Vec3.inl:646
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:378
JPH_INLINE bool IsNaN() const
Test if vector contains NaN elements.
Definition Vec3.inl:1135
JPH_INLINE Vec3 Sqrt() const
Component wise square root.
Definition Vec3.inl:1029
JPH_INLINE UVec4 ReinterpretAsInt() const
Reinterpret Vec3 as a UVec4 (doesn't change the bits)
Definition Vec3.inl:1194
JPH_INLINE Vec3 DotV(Vec3Arg inV2) const
Dot product, returns the dot product in X, Y and Z components.
Definition Vec3.inl:879
static JPH_INLINE Vec3 sLoadFloat3Unsafe(const Float3 &inV)
Load 3 floats from memory (reads 32 bits extra which it doesn't use)
Definition Vec3.inl:167
JPH_INLINE float GetZ() const
Definition Vec3.h:129
JPH_INLINE Vec3 GetSign() const
Get vector that contains the sign of each element (returns 1.0f if positive, -1.0f if negative)
Definition Vec3.inl:1233
static JPH_INLINE Vec3 sNaN()
Vector with all NaN's.
Definition Vec3.inl:162
Vec3()=default
Constructor.
JPH_INLINE int GetHighestComponentIndex() const
Get index of component with highest value.
Definition Vec3.inl:812
static JPH_INLINE Vec3 sFusedMultiplyAdd(Vec3Arg inMul1, Vec3Arg inMul2, Vec3Arg inAdd)
Calculates inMul1 * inMul2 + inAdd.
Definition Vec3.inl:353
JPH_INLINE Vec3 Swizzle() const
Swizzle the elements in inV.
Definition Vec4.h:14
float mF32[4]
Definition Vec4.h:312
JPH_INLINE float GetX() const
Get individual components.
Definition Vec4.h:119
JPH_INLINE float GetY() const
Definition Vec4.h:120
static JPH_INLINE Vec4 sReplicate(float inV)
Replicate inV across all components.
Definition Vec4.inl:97
void SinCos(Vec4 &outSin, Vec4 &outCos) const
Calculate the sine and cosine for each element of this vector (input in radians)
Definition Vec4.inl:1208