RavEngine
Loading...
Searching...
No Matches
PxMathUtils.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_MATH_UTILS_H
30#define PX_MATH_UTILS_H
31
36#include "foundation/PxFoundationConfig.h"
37#include "foundation/Px.h"
38#include "foundation/PxVec4.h"
39#include "foundation/PxAssert.h"
40#include "foundation/PxPlane.h"
41
42#if !PX_DOXYGEN
43namespace physx
44{
45#endif
46
54PX_FOUNDATION_API PxQuat PxShortestRotation(const PxVec3& from, const PxVec3& target);
55
56/* \brief diagonalizes a 3x3 symmetric matrix y
57
58The returned matrix satisfies M = R * D * R', where R is the rotation matrix for the output quaternion, R' its
59transpose, and D the diagonal matrix
60
61If the matrix is not symmetric, the result is undefined.
62
63\param[in] m the matrix to diagonalize
64\param[out] axes a quaternion rotation which diagonalizes the matrix
65\return the vector diagonal of the diagonalized matrix.
66*/
67PX_FOUNDATION_API PxVec3 PxDiagonalize(const PxMat33& m, PxQuat& axes);
68
76PX_FOUNDATION_API PxTransform PxTransformFromSegment(const PxVec3& p0, const PxVec3& p1, PxReal* halfHeight = NULL);
77
83PX_FOUNDATION_API PxTransform PxTransformFromPlaneEquation(const PxPlane& plane);
84
91{
92 return PxPlane(1.0f, 0.0f, 0.0f, 0.0f).transform(pose);
93}
94
103PX_FOUNDATION_API PxQuat PxSlerp(const PxReal t, const PxQuat& left, const PxQuat& right);
104
113PX_FOUNDATION_API void PxIntegrateTransform(const PxTransform& curTrans, const PxVec3& linvel, const PxVec3& angvel,
114 PxReal timeStep, PxTransform& result);
115
117PX_CUDA_CALLABLE PX_FORCE_INLINE PxQuat PxExp(const PxVec3& v)
118{
119 const PxReal m = v.magnitudeSquared();
120 return m < 1e-24f ? PxQuat(PxIdentity) : PxQuat(PxSqrt(m), v * PxRecipSqrt(m));
121}
122
128PX_FOUNDATION_API PxVec3 PxOptimizeBoundingBox(PxMat33& basis);
129
133PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxLog(const PxQuat& q)
134{
135 const PxReal s = q.getImaginaryPart().magnitude();
136 if (s < 1e-12f)
137 return PxVec3(0.0f);
138 // force the half-angle to have magnitude <= pi/2
139 PxReal halfAngle = q.w < 0 ? PxAtan2(-s, -q.w) : PxAtan2(s, q.w);
140 PX_ASSERT(halfAngle >= -PxPi / 2 && halfAngle <= PxPi / 2);
141
142 return q.getImaginaryPart().getNormalized() * 2.f * halfAngle;
143}
144
148PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxLargestAxis(const PxVec3& v)
149{
150 PxU32 m = PxU32(v.y > v.x ? 1 : 0);
151 return v.z > v[m] ? 2 : m;
152}
153
160PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal PxTanHalf(PxReal sin, PxReal cos)
161{
162 // PT: avoids divide by zero for singularity. We return sqrt(FLT_MAX) instead of FLT_MAX
163 // to make sure the calling code doesn't generate INF values when manipulating the returned value
164 // (some joints multiply it by 4, etc).
165 if (cos == -1.0f)
166 return sin < 0.0f ? -sqrtf(FLT_MAX) : sqrtf(FLT_MAX);
167
168 // PT: half-angle formula: tan(a/2) = sin(a)/(1+cos(a))
169 return sin / (1.0f + cos);
170}
171
178PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxEllipseClamp(const PxVec3& point, const PxVec3& radii)
179{
180 // lagrange multiplier method with Newton/Halley hybrid root-finder.
181 // see http://www.geometrictools.com/Documentation/DistancePointToEllipse2.pdf
182 // for proof of Newton step robustness and initial estimate.
183 // Halley converges much faster but sometimes overshoots - when that happens we take
184 // a newton step instead
185
186 // converges in 1-2 iterations where D&C works well, and it's good with 4 iterations
187 // with any ellipse that isn't completely crazy
188
189 const PxU32 MAX_ITERATIONS = 20;
190 const PxReal convergenceThreshold = 1e-4f;
191
192 // iteration requires first quadrant but we recover generality later
193
194 PxVec3 q(0, PxAbs(point.y), PxAbs(point.z));
195 const PxReal tinyEps = 1e-6f; // very close to minor axis is numerically problematic but trivial
196 if (radii.y >= radii.z)
197 {
198 if (q.z < tinyEps)
199 return PxVec3(0, point.y > 0 ? radii.y : -radii.y, 0);
200 }
201 else
202 {
203 if (q.y < tinyEps)
204 return PxVec3(0, 0, point.z > 0 ? radii.z : -radii.z);
205 }
206
207 PxVec3 denom, e2 = radii.multiply(radii), eq = radii.multiply(q);
208
209 // we can use any initial guess which is > maximum(-e.y^2,-e.z^2) and for which f(t) is > 0.
210 // this guess works well near the axes, but is weak along the diagonals.
211
212 PxReal t = PxMax(eq.y - e2.y, eq.z - e2.z);
213
214 for (PxU32 i = 0; i < MAX_ITERATIONS; i++)
215 {
216 denom = PxVec3(0, 1 / (t + e2.y), 1 / (t + e2.z));
217 PxVec3 denom2 = eq.multiply(denom);
218
219 PxVec3 fv = denom2.multiply(denom2);
220 PxReal f = fv.y + fv.z - 1;
221
222 // although in exact arithmetic we are guaranteed f>0, we can get here
223 // on the first iteration via catastrophic cancellation if the point is
224 // very close to the origin. In that case we just behave as if f=0
225
226 if (f < convergenceThreshold)
227 return e2.multiply(point).multiply(denom);
228
229 PxReal df = fv.dot(denom) * -2.0f;
230 t = t - f / df;
231 }
232
233 // we didn't converge, so clamp what we have
234 PxVec3 r = e2.multiply(point).multiply(denom);
235 return r * PxRecipSqrt(PxSqr(r.y / radii.y) + PxSqr(r.z / radii.z));
236}
237
246PX_CUDA_CALLABLE PX_FORCE_INLINE void PxSeparateSwingTwist(const PxQuat& q, PxQuat& swing, PxQuat& twist)
247{
248 twist = q.x != 0.0f ? PxQuat(q.x, 0, 0, q.w).getNormalized() : PxQuat(PxIdentity);
249 swing = q * twist.getConjugate();
250}
251
258PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 PxComputeAngle(const PxVec3& v0, const PxVec3& v1)
259{
260 const PxF32 cos = v0.dot(v1); // |v0|*|v1|*Cos(Angle)
261 const PxF32 sin = (v0.cross(v1)).magnitude(); // |v0|*|v1|*Sin(Angle)
262 return PxAtan2(sin, cos);
263}
264
272{
273 // Derive two remaining vectors
274 if (PxAbs(dir.y) <= 0.9999f)
275 {
276 right = PxVec3(dir.z, 0.0f, -dir.x);
277 right.normalize();
278
279 // PT: normalize not needed for 'up' because dir & right are unit vectors,
280 // and by construction the angle between them is 90 degrees (i.e. sin(angle)=1)
281 up = PxVec3(dir.y * right.z, dir.z * right.x - dir.x * right.z, -dir.y * right.x);
282 }
283 else
284 {
285 right = PxVec3(1.0f, 0.0f, 0.0f);
286
287 up = PxVec3(0.0f, dir.z, -dir.y);
288 up.normalize();
289 }
290}
291
301PX_INLINE void PxComputeBasisVectors(const PxVec3& p0, const PxVec3& p1, PxVec3& dir, PxVec3& right, PxVec3& up)
302{
303 // Compute the new direction vector
304 dir = p1 - p0;
305 dir.normalize();
306
307 // Derive two remaining vectors
308 PxComputeBasisVectors(dir, right, up);
309}
310
311
316{
317 return (i + 1 + (i >> 1)) & 3;
318}
319
320PX_INLINE PX_CUDA_CALLABLE void computeBarycentric(const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& d, const PxVec3& p, PxVec4& bary)
321{
322 const PxVec3 ba = b - a;
323 const PxVec3 ca = c - a;
324 const PxVec3 da = d - a;
325 const PxVec3 pa = p - a;
326
327 const PxReal detBcd = ba.dot(ca.cross(da));
328 const PxReal detPcd = pa.dot(ca.cross(da));
329
330 bary.y = detPcd / detBcd;
331
332 const PxReal detBpd = ba.dot(pa.cross(da));
333 bary.z = detBpd / detBcd;
334
335 const PxReal detBcp = ba.dot(ca.cross(pa));
336
337 bary.w = detBcp / detBcd;
338 bary.x = 1 - bary.y - bary.z - bary.w;
339}
340
341PX_INLINE PX_CUDA_CALLABLE void computeBarycentric(const PxVec3& a, const PxVec3& b, const PxVec3& c, const PxVec3& p, PxVec4& bary)
342{
343 const PxVec3 v0 = b - a;
344 const PxVec3 v1 = c - a;
345 const PxVec3 v2 = p - a;
346
347 const float d00 = v0.dot(v0);
348 const float d01 = v0.dot(v1);
349 const float d11 = v1.dot(v1);
350 const float d20 = v2.dot(v0);
351 const float d21 = v2.dot(v1);
352
353 const float denom = d00 * d11 - d01 * d01;
354 const float v = (d11 * d20 - d01 * d21) / denom;
355 const float w = (d00 * d21 - d01 * d20) / denom;
356 const float u = 1.f - v - w;
357
358 bary.x = u; bary.y = v; bary.z = w;
359 bary.w = 0.f;
360}
361
362
363// lerp
365{
366 PX_INLINE PX_CUDA_CALLABLE static float PxLerp(float a, float b, float t)
367 {
368 return a + t * (b - a);
369 }
370
371 PX_INLINE PX_CUDA_CALLABLE static PxReal PxBiLerp(
372 const PxReal f00,
373 const PxReal f10,
374 const PxReal f01,
375 const PxReal f11,
376 const PxReal tx, const PxReal ty)
377 {
378 return PxLerp(
379 PxLerp(f00, f10, tx),
380 PxLerp(f01, f11, tx),
381 ty);
382 }
383
384 PX_INLINE PX_CUDA_CALLABLE static PxReal PxTriLerp(
385 const PxReal f000,
386 const PxReal f100,
387 const PxReal f010,
388 const PxReal f110,
389 const PxReal f001,
390 const PxReal f101,
391 const PxReal f011,
392 const PxReal f111,
393 const PxReal tx,
394 const PxReal ty,
395 const PxReal tz)
396 {
397 return PxLerp(
398 PxBiLerp(f000, f100, f010, f110, tx, ty),
399 PxBiLerp(f001, f101, f011, f111, tx, ty),
400 tz);
401 }
402
403 PX_INLINE PX_CUDA_CALLABLE static PxU32 PxSDFIdx(PxU32 i, PxU32 j, PxU32 k, PxU32 nbX, PxU32 nbY)
404 {
405 return i + j * nbX + k * nbX*nbY;
406 }
407
408 PX_INLINE PX_CUDA_CALLABLE static PxReal PxSDFSampleImpl(const PxReal* PX_RESTRICT sdf, const PxVec3& localPos, const PxVec3& sdfBoxLower,
409 const PxVec3& sdfBoxHigher, const PxReal sdfDx, const PxReal invSdfDx, const PxU32 dimX, const PxU32 dimY, const PxU32 dimZ, PxReal tolerance)
410 {
411 PxVec3 clampedGridPt = localPos.maximum(sdfBoxLower).minimum(sdfBoxHigher);
412
413 const PxVec3 diff = (localPos - clampedGridPt);
414
415 if (diff.magnitudeSquared() > tolerance*tolerance)
416 return PX_MAX_F32;
417
418 PxVec3 f = (clampedGridPt - sdfBoxLower) * invSdfDx;
419
420 PxU32 i = PxU32(f.x);
421 PxU32 j = PxU32(f.y);
422 PxU32 k = PxU32(f.z);
423
424 f -= PxVec3(PxReal(i), PxReal(j), PxReal(k));
425
426 if (i >= (dimX - 1))
427 {
428 i = dimX - 2;
429 clampedGridPt.x -= f.x * sdfDx;
430 f.x = 1.f;
431 }
432 if (j >= (dimY - 1))
433 {
434 j = dimY - 2;
435 clampedGridPt.y -= f.y * sdfDx;
436 f.y = 1.f;
437 }
438 if (k >= (dimZ - 1))
439 {
440 k = dimZ - 2;
441 clampedGridPt.z -= f.z * sdfDx;
442 f.z = 1.f;
443 }
444
445 const PxReal s000 = sdf[Interpolation::PxSDFIdx(i, j, k, dimX, dimY)];
446 const PxReal s100 = sdf[Interpolation::PxSDFIdx(i + 1, j, k, dimX, dimY)];
447 const PxReal s010 = sdf[Interpolation::PxSDFIdx(i, j + 1, k, dimX, dimY)];
448 const PxReal s110 = sdf[Interpolation::PxSDFIdx(i + 1, j + 1, k, dimX, dimY)];
449 const PxReal s001 = sdf[Interpolation::PxSDFIdx(i, j, k + 1, dimX, dimY)];
450 const PxReal s101 = sdf[Interpolation::PxSDFIdx(i + 1, j, k + 1, dimX, dimY)];
451 const PxReal s011 = sdf[Interpolation::PxSDFIdx(i, j + 1, k + 1, dimX, dimY)];
452 const PxReal s111 = sdf[Interpolation::PxSDFIdx(i + 1, j + 1, k + 1, dimX, dimY)];
453
454 PxReal dist = PxTriLerp(
455 s000,
456 s100,
457 s010,
458 s110,
459 s001,
460 s101,
461 s011,
462 s111,
463 f.x, f.y, f.z);
464
465 dist += diff.magnitude();
466
467 return dist;
468 }
469
470};
471
472PX_INLINE PX_CUDA_CALLABLE PxReal PxSdfSample(const PxReal* PX_RESTRICT sdf, const PxVec3& localPos, const PxVec3& sdfBoxLower,
473 const PxVec3& sdfBoxHigher, const PxReal sdfDx, const PxReal invSdfDx, const PxU32 dimX, const PxU32 dimY, const PxU32 dimZ, PxVec3& gradient, PxReal tolerance = PX_MAX_F32)
474{
475
476 PxReal dist = Interpolation::PxSDFSampleImpl(sdf, localPos, sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance);
477
478 if (dist < tolerance)
479 {
480
481 PxVec3 grad;
482 grad.x = Interpolation::PxSDFSampleImpl(sdf, localPos + PxVec3(sdfDx, 0.f, 0.f), sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance) -
483 Interpolation::PxSDFSampleImpl(sdf, localPos - PxVec3(sdfDx, 0.f, 0.f), sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance);
484 grad.y = Interpolation::PxSDFSampleImpl(sdf, localPos + PxVec3(0.f, sdfDx, 0.f), sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance) -
485 Interpolation::PxSDFSampleImpl(sdf, localPos - PxVec3(0.f, sdfDx, 0.f), sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance);
486 grad.z = Interpolation::PxSDFSampleImpl(sdf, localPos + PxVec3(0.f, 0.f, sdfDx), sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance) -
487 Interpolation::PxSDFSampleImpl(sdf, localPos - PxVec3(0.f, 0.f, sdfDx), sdfBoxLower, sdfBoxHigher, sdfDx, invSdfDx, dimX, dimY, dimZ, tolerance);
488
489 gradient = grad;
490
491 }
492
493 return dist;
494}
495
496#if !PX_DOXYGEN
497} // namespace physx
498#endif
499
501#endif
Representation of a plane.
Definition PxPlane.h:49
PX_CUDA_CALLABLE PX_FORCE_INLINE PxPlane transform(const PxTransform &pose) const
transform plane
Definition PxPlane.h:137
This is a quaternion class. For more information on quaternion mathematics consult a mathematics sour...
Definition PxQuat.h:50
float x
Definition PxQuat.h:395
class representing a rigid euclidean transform as a quaternion and a vector
Definition PxTransform.h:49
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
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 cross(const PxVec3 &v) const
cross product
Definition PxVec3.h:284
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getNormalized() const
Definition PxVec3.h:291
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 multiply(const PxVec3 &a) const
a[i] * b[i], for all i.
Definition PxVec3.h:336
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 maximum(const PxVec3 &v) const
element-wise maximum
Definition PxVec3.h:360
PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitudeSquared() const
returns the squared magnitude
Definition PxVec3.h:175
PX_CUDA_CALLABLE PX_FORCE_INLINE float normalize()
normalizes the vector in place
Definition PxVec3.h:300
PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitude() const
returns the magnitude
Definition PxVec3.h:183
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 minimum(const PxVec3 &v) const
element-wise minimum
Definition PxVec3.h:344
#define PX_RESTRICT
Definition PxPreprocessor.h:355
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_INLINE
Definition PxPreprocessor.h:320
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 void PxSeparateSwingTwist(const PxQuat &q, PxQuat &swing, PxQuat &twist)
Compute from an input quaternion q a pair of quaternions (swing, twist) such that q = swing * twist w...
Definition PxMathUtils.h:246
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAtan2(float x, float y)
Arctangent of (x/y) with correct sign. Returns angle between -PI and PI in radians Unit: Radians.
Definition PxMath.h:302
PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal PxTanHalf(PxReal sin, PxReal cos)
Compute tan(theta/2) given sin(theta) and cos(theta) as inputs.
Definition PxMathUtils.h:160
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 PxF32 PxSqr(const PxF32 a)
square of the argument
Definition PxMath.h:170
PX_FOUNDATION_API PxQuat PxShortestRotation(const PxVec3 &from, const PxVec3 &target)
finds the shortest rotation between two vectors.
Definition FdMathUtils.cpp:70
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxRecipSqrt(float a)
reciprocal square root.
Definition PxMath.h:158
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 PxEllipseClamp(const PxVec3 &point, const PxVec3 &radii)
Compute the closest point on an 2d ellipse to a given 2d point.
Definition PxMathUtils.h:178
PX_FOUNDATION_API PxTransform PxTransformFromSegment(const PxVec3 &p0, const PxVec3 &p1, PxReal *halfHeight=NULL)
creates a transform from the endpoints of a segment, suitable for an actor transform for a PxCapsuleG...
Definition FdMathUtils.cpp:59
PX_FOUNDATION_API PxQuat PxSlerp(const PxReal t, const PxQuat &left, const PxQuat &right)
Spherical linear interpolation of two quaternions.
Definition FdMathUtils.cpp:178
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxLargestAxis(const PxVec3 &v)
return Returns 0 if v.x is largest element of v, 1 if v.y is largest element, 2 if v....
Definition PxMathUtils.h:148
PX_FOUNDATION_API PxTransform PxTransformFromPlaneEquation(const PxPlane &plane)
creates a transform from a plane equation, suitable for an actor transform for a PxPlaneGeometry
Definition FdMathUtils.cpp:40
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSqrt(float a)
Square root.
Definition PxMath.h:146
PX_INLINE PxPlane PxPlaneEquationFromTransform(const PxTransform &pose)
creates a plane equation from a transform, such as the actor transform for a PxPlaneGeometry
Definition PxMathUtils.h:90
PX_FOUNDATION_API void PxIntegrateTransform(const PxTransform &curTrans, const PxVec3 &linvel, const PxVec3 &angvel, PxReal timeStep, PxTransform &result)
integrate transform.
Definition FdMathUtils.cpp:207
PX_INLINE PxU32 PxGetNextIndex3(PxU32 i)
Compute (i+1)%3.
Definition PxMathUtils.h:315
PX_INLINE void PxComputeBasisVectors(const PxVec3 &dir, PxVec3 &right, PxVec3 &up)
Compute two normalized vectors (right and up) that are perpendicular to an input normalized vector (d...
Definition PxMathUtils.h:271
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_FOUNDATION_API PxVec3 PxOptimizeBoundingBox(PxMat33 &basis)
computes a oriented bounding box around the scaled basis.
Definition FdMathUtils.cpp:140
PX_CUDA_CALLABLE PX_FORCE_INLINE PxF32 PxComputeAngle(const PxVec3 &v0, const PxVec3 &v1)
Compute the angle between two non-unit vectors.
Definition PxMathUtils.h:258
Definition PxMathUtils.h:365