RavEngine
Loading...
Searching...
No Matches
PxVecQuat.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 PX_VEC_QUAT_H
30#define PX_VEC_QUAT_H
31
32#if !PX_DOXYGEN
33namespace physx
34{
35#endif
36namespace aos
37{
38
39#ifndef PX_PIDIV2
40#define PX_PIDIV2 1.570796327f
41#endif
42
44// QuatV
46PX_FORCE_INLINE QuatV QuatVLoadXYZW(const PxF32 x, const PxF32 y, const PxF32 z, const PxF32 w)
47{
48 return V4LoadXYZW(x, y, z, w);
49}
50
51PX_FORCE_INLINE QuatV QuatVLoadU(const PxF32* v)
52{
53 return V4LoadU(v);
54}
55
56PX_FORCE_INLINE QuatV QuatVLoadA(const PxF32* v)
57{
58 return V4LoadA(v);
59}
60
61PX_FORCE_INLINE QuatV QuatV_From_RotationAxisAngle(const Vec3V u, const FloatV a)
62{
63 // q = cos(a/2) + u*sin(a/2)
64 const FloatV half = FLoad(0.5f);
65 const FloatV hangle = FMul(a, half);
66 const FloatV piByTwo(FLoad(PX_PIDIV2));
67 const FloatV PiByTwoMinHangle(FSub(piByTwo, hangle));
68 const Vec4V hangle2(Vec4V_From_Vec3V(V3Merge(hangle, PiByTwoMinHangle, hangle)));
69
70 /*const FloatV sina = FSin(hangle);
71 const FloatV cosa = FCos(hangle);*/
72
73 const Vec4V _sina = V4Sin(hangle2);
74 const FloatV sina = V4GetX(_sina);
75 const FloatV cosa = V4GetY(_sina);
76
77 const Vec3V v = V3Scale(u, sina);
78 // return V4Sel(BTTTF(), Vec4V_From_Vec3V(v), V4Splat(cosa));
79 return V4SetW(Vec4V_From_Vec3V(v), cosa);
80}
81
82// Normalize
83PX_FORCE_INLINE QuatV QuatNormalize(const QuatV q)
84{
85 return V4Normalize(q);
86}
87
88PX_FORCE_INLINE FloatV QuatLength(const QuatV q)
89{
90 return V4Length(q);
91}
92
93PX_FORCE_INLINE FloatV QuatLengthSq(const QuatV q)
94{
95 return V4LengthSq(q);
96}
97
98PX_FORCE_INLINE FloatV QuatDot(const QuatV a, const QuatV b) // convert this PxQuat to a unit quaternion
99{
100 return V4Dot(a, b);
101}
102
103PX_FORCE_INLINE QuatV QuatConjugate(const QuatV q)
104{
105 return V4SetW(V4Neg(q), V4GetW(q));
106}
107
108PX_FORCE_INLINE Vec3V QuatGetImaginaryPart(const QuatV q)
109{
110 return Vec3V_From_Vec4V(q);
111}
112
114PX_FORCE_INLINE Vec3V QuatGetBasisVector0(const QuatV q)
115{
116 /*const PxF32 x2 = x*2.0f;
117 const PxF32 w2 = w*2.0f;
118 return PxVec3( (w * w2) - 1.0f + x*x2,
119 (z * w2) + y*x2,
120 (-y * w2) + z*x2);*/
121
122 const FloatV two = FLoad(2.f);
123 const FloatV w = V4GetW(q);
124 const Vec3V u = Vec3V_From_Vec4V(q);
125
126 const FloatV x2 = FMul(V3GetX(u), two);
127 const FloatV w2 = FMul(w, two);
128
129 const Vec3V a = V3Scale(u, x2);
130 const Vec3V tmp = V3Merge(w, V3GetZ(u), FNeg(V3GetY(u)));
131 // const Vec3V b = V3Scale(tmp, w2);
132 // const Vec3V ab = V3Add(a, b);
133 const Vec3V ab = V3ScaleAdd(tmp, w2, a);
134 return V3SetX(ab, FSub(V3GetX(ab), FOne()));
135}
136
138PX_FORCE_INLINE Vec3V QuatGetBasisVector1(const QuatV q)
139{
140 /*const PxF32 y2 = y*2.0f;
141 const PxF32 w2 = w*2.0f;
142 return PxVec3( (-z * w2) + x*y2,
143 (w * w2) - 1.0f + y*y2,
144 (x * w2) + z*y2);*/
145
146 const FloatV two = FLoad(2.f);
147 const FloatV w = V4GetW(q);
148 const Vec3V u = Vec3V_From_Vec4V(q);
149
150 const FloatV y2 = FMul(V3GetY(u), two);
151 const FloatV w2 = FMul(w, two);
152
153 const Vec3V a = V3Scale(u, y2);
154 const Vec3V tmp = V3Merge(FNeg(V3GetZ(u)), w, V3GetX(u));
155 // const Vec3V b = V3Scale(tmp, w2);
156 // const Vec3V ab = V3Add(a, b);
157 const Vec3V ab = V3ScaleAdd(tmp, w2, a);
158 return V3SetY(ab, FSub(V3GetY(ab), FOne()));
159}
160
162PX_FORCE_INLINE Vec3V QuatGetBasisVector2(const QuatV q)
163{
164 /*const PxF32 z2 = z*2.0f;
165 const PxF32 w2 = w*2.0f;
166 return PxVec3( (y * w2) + x*z2,
167 (-x * w2) + y*z2,
168 (w * w2) - 1.0f + z*z2);*/
169
170 const FloatV two = FLoad(2.f);
171 const FloatV w = V4GetW(q);
172 const Vec3V u = Vec3V_From_Vec4V(q);
173
174 const FloatV z2 = FMul(V3GetZ(u), two);
175 const FloatV w2 = FMul(w, two);
176
177 const Vec3V a = V3Scale(u, z2);
178 const Vec3V tmp = V3Merge(V3GetY(u), FNeg(V3GetX(u)), w);
179 /*const Vec3V b = V3Scale(tmp, w2);
180 const Vec3V ab = V3Add(a, b);*/
181 const Vec3V ab = V3ScaleAdd(tmp, w2, a);
182 return V3SetZ(ab, FSub(V3GetZ(ab), FOne()));
183}
184
185PX_FORCE_INLINE Vec3V QuatRotate(const QuatV q, const Vec3V v)
186{
187 /*
188 const PxVec3 qv(x,y,z);
189 return (v*(w*w-0.5f) + (qv.cross(v))*w + qv*(qv.dot(v)))*2;
190 */
191
192 const FloatV two = FLoad(2.f);
193 // const FloatV half = FloatV_From_F32(0.5f);
194 const FloatV nhalf = FLoad(-0.5f);
195 const Vec3V u = Vec3V_From_Vec4V(q);
196 const FloatV w = V4GetW(q);
197 // const FloatV w2 = FSub(FMul(w, w), half);
198 const FloatV w2 = FScaleAdd(w, w, nhalf);
199 const Vec3V a = V3Scale(v, w2);
200 // const Vec3V b = V3Scale(V3Cross(u, v), w);
201 // const Vec3V c = V3Scale(u, V3Dot(u, v));
202 // return V3Scale(V3Add(V3Add(a, b), c), two);
203 const Vec3V temp = V3ScaleAdd(V3Cross(u, v), w, a);
204 return V3Scale(V3ScaleAdd(u, V3Dot(u, v), temp), two);
205}
206
207PX_FORCE_INLINE Vec3V QuatTransform(const QuatV q, const Vec3V p, const Vec3V v)
208{
209 // p + q.rotate(v)
210 const FloatV two = FLoad(2.f);
211 // const FloatV half = FloatV_From_F32(0.5f);
212 const FloatV nhalf = FLoad(-0.5f);
213 const Vec3V u = Vec3V_From_Vec4V(q);
214 const FloatV w = V4GetW(q);
215 // const FloatV w2 = FSub(FMul(w, w), half);
216 const FloatV w2 = FScaleAdd(w, w, nhalf);
217 const Vec3V a = V3Scale(v, w2);
218 /*const Vec3V b = V3Scale(V3Cross(u, v), w);
219 const Vec3V c = V3Scale(u, V3Dot(u, v));
220 return V3ScaleAdd(V3Add(V3Add(a, b), c), two, p);*/
221 const Vec3V temp = V3ScaleAdd(V3Cross(u, v), w, a);
222 const Vec3V z = V3ScaleAdd(u, V3Dot(u, v), temp);
223 return V3ScaleAdd(z, two, p);
224}
225
226PX_FORCE_INLINE Vec3V QuatRotateInv(const QuatV q, const Vec3V v)
227{
228
229 // const PxVec3 qv(x,y,z);
230 // return (v*(w*w-0.5f) - (qv.cross(v))*w + qv*(qv.dot(v)))*2;
231
232 const FloatV two = FLoad(2.f);
233 const FloatV nhalf = FLoad(-0.5f);
234 const Vec3V u = Vec3V_From_Vec4V(q);
235 const FloatV w = V4GetW(q);
236 const FloatV w2 = FScaleAdd(w, w, nhalf);
237 const Vec3V a = V3Scale(v, w2);
238 /*const Vec3V b = V3Scale(V3Cross(u, v), w);
239 const Vec3V c = V3Scale(u, V3Dot(u, v));
240 return V3Scale(V3Add(V3Sub(a, b), c), two);*/
241 const Vec3V temp = V3NegScaleSub(V3Cross(u, v), w, a);
242 return V3Scale(V3ScaleAdd(u, V3Dot(u, v), temp), two);
243}
244
245PX_FORCE_INLINE QuatV QuatMul(const QuatV a, const QuatV b)
246{
247 const Vec3V imagA = Vec3V_From_Vec4V(a);
248 const Vec3V imagB = Vec3V_From_Vec4V(b);
249 const FloatV rA = V4GetW(a);
250 const FloatV rB = V4GetW(b);
251
252 const FloatV real = FSub(FMul(rA, rB), V3Dot(imagA, imagB));
253 const Vec3V v0 = V3Scale(imagA, rB);
254 const Vec3V v1 = V3Scale(imagB, rA);
255 const Vec3V v2 = V3Cross(imagA, imagB);
256 const Vec3V imag = V3Add(V3Add(v0, v1), v2);
257
258 return V4SetW(Vec4V_From_Vec3V(imag), real);
259}
260
261PX_FORCE_INLINE QuatV QuatAdd(const QuatV a, const QuatV b)
262{
263 return V4Add(a, b);
264}
265
266PX_FORCE_INLINE QuatV QuatNeg(const QuatV q)
267{
268 return V4Neg(q);
269}
270
271PX_FORCE_INLINE QuatV QuatSub(const QuatV a, const QuatV b)
272{
273 return V4Sub(a, b);
274}
275
276PX_FORCE_INLINE QuatV QuatScale(const QuatV a, const FloatV b)
277{
278 return V4Scale(a, b);
279}
280
281PX_FORCE_INLINE QuatV QuatMerge(const FloatV* const floatVArray)
282{
283 return V4Merge(floatVArray);
284}
285
286PX_FORCE_INLINE QuatV QuatMerge(const FloatVArg x, const FloatVArg y, const FloatVArg z, const FloatVArg w)
287{
288 return V4Merge(x, y, z, w);
289}
290
291PX_FORCE_INLINE QuatV QuatIdentity()
292{
293 return V4SetW(V4Zero(), FOne());
294}
295
296PX_FORCE_INLINE bool isFiniteQuatV(const QuatV q)
297{
298 return isFiniteVec4V(q);
299}
300
301#if PX_LINUX && PX_CLANG
302#pragma clang diagnostic push
303#pragma clang diagnostic ignored "-Wbitwise-instead-of-logical" // bitwise intentionally chosen for performance
304#endif
305
306PX_FORCE_INLINE bool isValidQuatV(const QuatV q)
307{
308 const FloatV unitTolerance = FLoad(1e-4f);
309 const FloatV tmp = FAbs(FSub(QuatLength(q), FOne()));
310 const BoolV con = FIsGrtr(unitTolerance, tmp);
311 return isFiniteVec4V(q) & (BAllEqTTTT(con) == 1);
312}
313
314PX_FORCE_INLINE bool isSaneQuatV(const QuatV q)
315{
316 const FloatV unitTolerance = FLoad(1e-2f);
317 const FloatV tmp = FAbs(FSub(QuatLength(q), FOne()));
318 const BoolV con = FIsGrtr(unitTolerance, tmp);
319 return isFiniteVec4V(q) & (BAllEqTTTT(con) == 1);
320}
321
322#if PX_LINUX && PX_CLANG
323#pragma clang diagnostic pop
324#endif
325
326PX_FORCE_INLINE Mat33V QuatGetMat33V(const QuatVArg q)
327{
328 // const FloatV two = FloatV_From_F32(2.f);
329 // const FloatV one = FOne();
330
331 // const FloatV x = V4GetX(q);
332 // const FloatV y = V4GetY(q);
333 // const FloatV z = V4GetZ(q);
334 // const Vec4V _q = V4Mul(q, two);
335 //
337
338 // const Vec4V t0 = V4Mul(_q, x); // 2xx, 2xy, 2xz, 2xw
339 // const Vec4V t1 = V4Mul(_q, y); // 2xy, 2yy, 2yz, 2yw
340 // const Vec4V t2 = V4Mul(_q, z); // 2xz, 2yz, 2zz, 2zw
342
343 // const FloatV xx2 = V4GetX(t0);
344 // const FloatV xy2 = V4GetY(t0);
345 // const FloatV xz2 = V4GetZ(t0);
346 // const FloatV xw2 = V4GetW(t0);
347
348 // const FloatV yy2 = V4GetY(t1);
349 // const FloatV yz2 = V4GetZ(t1);
350 // const FloatV yw2 = V4GetW(t1);
351
352 // const FloatV zz2 = V4GetZ(t2);
353 // const FloatV zw2 = V4GetW(t2);
354
356
357 // const FloatV c00 = FSub(one, FAdd(yy2, zz2));
358 // const FloatV c01 = FSub(xy2, zw2);
359 // const FloatV c02 = FAdd(xz2, yw2);
360
361 // const FloatV c10 = FAdd(xy2, zw2);
362 // const FloatV c11 = FSub(one, FAdd(xx2, zz2));
363 // const FloatV c12 = FSub(yz2, xw2);
364
365 // const FloatV c20 = FSub(xz2, yw2);
366 // const FloatV c21 = FAdd(yz2, xw2);
367 // const FloatV c22 = FSub(one, FAdd(xx2, yy2));
368
369 // const Vec3V c0 = V3Merge(c00, c10, c20);
370 // const Vec3V c1 = V3Merge(c01, c11, c21);
371 // const Vec3V c2 = V3Merge(c02, c12, c22);
372
373 // return Mat33V(c0, c1, c2);
374
375 const FloatV one = FOne();
376 const FloatV x = V4GetX(q);
377 const FloatV y = V4GetY(q);
378 const FloatV z = V4GetZ(q);
379 const FloatV w = V4GetW(q);
380
381 const FloatV x2 = FAdd(x, x);
382 const FloatV y2 = FAdd(y, y);
383 const FloatV z2 = FAdd(z, z);
384
385 const FloatV xx = FMul(x2, x);
386 const FloatV yy = FMul(y2, y);
387 const FloatV zz = FMul(z2, z);
388
389 const FloatV xy = FMul(x2, y);
390 const FloatV xz = FMul(x2, z);
391 const FloatV xw = FMul(x2, w);
392
393 const FloatV yz = FMul(y2, z);
394 const FloatV yw = FMul(y2, w);
395 const FloatV zw = FMul(z2, w);
396
397 const FloatV v = FSub(one, xx);
398
399 const Vec3V column0 = V3Merge(FSub(FSub(one, yy), zz), FAdd(xy, zw), FSub(xz, yw));
400 const Vec3V column1 = V3Merge(FSub(xy, zw), FSub(v, zz), FAdd(yz, xw));
401 const Vec3V column2 = V3Merge(FAdd(xz, yw), FSub(yz, xw), FSub(v, yy));
402 return Mat33V(column0, column1, column2);
403}
404
405PX_FORCE_INLINE QuatV Mat33GetQuatV(const Mat33V& a)
406{
407 const FloatV one = FOne();
408 const FloatV zero = FZero();
409 const FloatV half = FLoad(0.5f);
410 const FloatV two = FLoad(2.f);
411 const FloatV scale = FLoad(0.25f);
412 const FloatV a00 = V3GetX(a.col0);
413 const FloatV a11 = V3GetY(a.col1);
414 const FloatV a22 = V3GetZ(a.col2);
415
416 const FloatV a21 = V3GetZ(a.col1); // row=2, col=1;
417 const FloatV a12 = V3GetY(a.col2); // row=1, col=2;
418 const FloatV a02 = V3GetX(a.col2); // row=0, col=2;
419 const FloatV a20 = V3GetZ(a.col0); // row=2, col=0;
420 const FloatV a10 = V3GetY(a.col0); // row=1, col=0;
421 const FloatV a01 = V3GetX(a.col1); // row=0, col=1;
422
423 const Vec3V vec0 = V3Merge(a21, a02, a10);
424 const Vec3V vec1 = V3Merge(a12, a20, a01);
425 const Vec3V v = V3Sub(vec0, vec1);
426 const Vec3V g = V3Add(vec0, vec1);
427
428 const FloatV trace = FAdd(a00, FAdd(a11, a22));
429
430 if(FAllGrtrOrEq(trace, zero))
431 {
432 const FloatV h = FSqrt(FAdd(trace, one));
433 const FloatV w = FMul(half, h);
434 const FloatV s = FMul(half, FRecip(h));
435 const Vec3V u = V3Scale(v, s);
436 return V4SetW(Vec4V_From_Vec3V(u), w);
437 }
438 else
439 {
440 const FloatV ntrace = FNeg(trace);
441 const Vec3V d = V3Merge(a00, a11, a22);
442 const BoolV con0 = BAllTrue3(V3IsGrtrOrEq(V3Splat(a00), d));
443 const BoolV con1 = BAllTrue3(V3IsGrtrOrEq(V3Splat(a11), d));
444
445 const FloatV t0 = FAdd(one, FScaleAdd(a00, two, ntrace));
446 const FloatV t1 = FAdd(one, FScaleAdd(a11, two, ntrace));
447 const FloatV t2 = FAdd(one, FScaleAdd(a22, two, ntrace));
448
449 const FloatV t = FSel(con0, t0, FSel(con1, t1, t2));
450
451 const FloatV h = FMul(two, FSqrt(t));
452 const FloatV s = FRecip(h);
453 const FloatV g0 = FMul(scale, h);
454 const Vec3V vs = V3Scale(v, s);
455 const Vec3V gs = V3Scale(g, s);
456 const FloatV gsx = V3GetX(gs);
457 const FloatV gsy = V3GetY(gs);
458 const FloatV gsz = V3GetZ(gs);
459 // vs.x= (a21 - a12)*s; vs.y=(a02 - a20)*s; vs.z=(a10 - a01)*s;
460 // gs.x= (a21 + a12)*s; gs.y=(a02 + a20)*s; gs.z=(a10 + a01)*s;
461 const Vec4V v0 = V4Merge(g0, gsz, gsy, V3GetX(vs));
462 const Vec4V v1 = V4Merge(gsz, g0, gsx, V3GetY(vs));
463 const Vec4V v2 = V4Merge(gsy, gsx, g0, V3GetZ(vs));
464 return V4Sel(con0, v0, V4Sel(con1, v1, v2));
465 }
466}
467
468} // namespace aos
469#if !PX_DOXYGEN
470} // namespace physx
471#endif
472
473#endif
vec< 1, float, defaultp > vec1
1 components vector of single-precision floating-point numbers.
Definition vector_float1.hpp:28
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
GLM_FUNC_DECL GLM_CONSTEXPR genType zero()
Definition constants.inl:6
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39