RavEngine
Loading...
Searching...
No Matches
PxMassProperties.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_MASS_PROPERTIES_H
30#define PX_MASS_PROPERTIES_H
35#include "PxPhysXConfig.h"
36#include "foundation/PxMath.h"
37#include "foundation/PxMathUtils.h"
38#include "foundation/PxVec3.h"
39#include "foundation/PxMat33.h"
40#include "foundation/PxQuat.h"
41#include "foundation/PxTransform.h"
42#include "geometry/PxGeometry.h"
43#include "geometry/PxBoxGeometry.h"
44#include "geometry/PxSphereGeometry.h"
45#include "geometry/PxCapsuleGeometry.h"
46#include "geometry/PxConvexMeshGeometry.h"
47#include "geometry/PxConvexMesh.h"
48#include "geometry/PxCustomGeometry.h"
49#include "geometry/PxTriangleMeshGeometry.h"
50#include "geometry/PxTriangleMesh.h"
51
52#if !PX_DOXYGEN
53namespace physx
54{
55#endif
56
65{
66public:
71
75 PX_FORCE_INLINE PxMassProperties(const PxReal m, const PxMat33& inertiaT, const PxVec3& com) : inertiaTensor(inertiaT), centerOfMass(com), mass(m) {}
76
85 {
86 switch (geometry.getType())
87 {
88 case PxGeometryType::eSPHERE:
89 {
90 const PxSphereGeometry& s = static_cast<const PxSphereGeometry&>(geometry);
91 mass = (4.0f / 3.0f) * PxPi * s.radius * s.radius * s.radius;
92 inertiaTensor = PxMat33::createDiagonal(PxVec3(2.0f / 5.0f * mass * s.radius * s.radius));
93 centerOfMass = PxVec3(0.0f);
94 }
95 break;
96
97 case PxGeometryType::eBOX:
98 {
99 const PxBoxGeometry& b = static_cast<const PxBoxGeometry&>(geometry);
100 mass = b.halfExtents.x * b.halfExtents.y * b.halfExtents.z * 8.0f;
101 PxVec3 d2 = b.halfExtents.multiply(b.halfExtents);
102 inertiaTensor = PxMat33::createDiagonal(PxVec3(d2.y + d2.z, d2.x + d2.z, d2.x + d2.y)) * (mass * 1.0f / 3.0f);
103 centerOfMass = PxVec3(0.0f);
104 }
105 break;
106
107 case PxGeometryType::eCAPSULE:
108 {
109 const PxCapsuleGeometry& c = static_cast<const PxCapsuleGeometry&>(geometry);
110 PxReal r = c.radius, h = c.halfHeight;
111 mass = ((4.0f / 3.0f) * r + 2 * c.halfHeight) * PxPi * r * r;
112
113 PxReal a = r*r*r * (8.0f / 15.0f) + h*r*r * (3.0f / 2.0f) + h*h*r * (4.0f / 3.0f) + h*h*h * (2.0f / 3.0f);
114 PxReal b = r*r*r * (8.0f / 15.0f) + h*r*r;
115 inertiaTensor = PxMat33::createDiagonal(PxVec3(b, a, a) * PxPi * r * r);
116 centerOfMass = PxVec3(0.0f);
117 }
118 break;
119
120 case PxGeometryType::eCONVEXMESH:
121 {
122 const PxConvexMeshGeometry& c = static_cast<const PxConvexMeshGeometry&>(geometry);
123 PxVec3 unscaledCoM;
124 PxMat33 unscaledInertiaTensorNonCOM; // inertia tensor of convex mesh in mesh local space
125 PxMat33 unscaledInertiaTensorCOM;
126 PxReal unscaledMass;
127 c.convexMesh->getMassInformation(unscaledMass, unscaledInertiaTensorNonCOM, unscaledCoM);
128
129 // inertia tensor relative to center of mass
130 unscaledInertiaTensorCOM[0][0] = unscaledInertiaTensorNonCOM[0][0] - unscaledMass*PxReal((unscaledCoM.y*unscaledCoM.y+unscaledCoM.z*unscaledCoM.z));
131 unscaledInertiaTensorCOM[1][1] = unscaledInertiaTensorNonCOM[1][1] - unscaledMass*PxReal((unscaledCoM.z*unscaledCoM.z+unscaledCoM.x*unscaledCoM.x));
132 unscaledInertiaTensorCOM[2][2] = unscaledInertiaTensorNonCOM[2][2] - unscaledMass*PxReal((unscaledCoM.x*unscaledCoM.x+unscaledCoM.y*unscaledCoM.y));
133 unscaledInertiaTensorCOM[0][1] = unscaledInertiaTensorCOM[1][0] = (unscaledInertiaTensorNonCOM[0][1] + unscaledMass*PxReal(unscaledCoM.x*unscaledCoM.y));
134 unscaledInertiaTensorCOM[1][2] = unscaledInertiaTensorCOM[2][1] = (unscaledInertiaTensorNonCOM[1][2] + unscaledMass*PxReal(unscaledCoM.y*unscaledCoM.z));
135 unscaledInertiaTensorCOM[0][2] = unscaledInertiaTensorCOM[2][0] = (unscaledInertiaTensorNonCOM[0][2] + unscaledMass*PxReal(unscaledCoM.z*unscaledCoM.x));
136
137 const PxMeshScale& s = c.scale;
138 mass = unscaledMass * s.scale.x * s.scale.y * s.scale.z;
139 centerOfMass = s.transform(unscaledCoM);
140 inertiaTensor = scaleInertia(unscaledInertiaTensorCOM, s.rotation, s.scale);
141 }
142 break;
143
144 case PxGeometryType::eCUSTOM:
145 {
146 *this = PxMassProperties();
147 static_cast<const PxCustomGeometry&>(geometry).callbacks->computeMassProperties(geometry, *this);
148 }
149 break;
150
151 case PxGeometryType::eTRIANGLEMESH:
152 {
153 const PxTriangleMeshGeometry& g = static_cast<const PxTriangleMeshGeometry&>(geometry);
154
155 PxVec3 unscaledCoM;
156 PxMat33 unscaledInertiaTensorNonCOM; // inertia tensor of convex mesh in mesh local space
157 PxMat33 unscaledInertiaTensorCOM;
158 PxReal unscaledMass;
159 g.triangleMesh->getMassInformation(unscaledMass, unscaledInertiaTensorNonCOM, unscaledCoM);
160
161 // inertia tensor relative to center of mass
162 unscaledInertiaTensorCOM[0][0] = unscaledInertiaTensorNonCOM[0][0] - unscaledMass * PxReal((unscaledCoM.y*unscaledCoM.y + unscaledCoM.z*unscaledCoM.z));
163 unscaledInertiaTensorCOM[1][1] = unscaledInertiaTensorNonCOM[1][1] - unscaledMass * PxReal((unscaledCoM.z*unscaledCoM.z + unscaledCoM.x*unscaledCoM.x));
164 unscaledInertiaTensorCOM[2][2] = unscaledInertiaTensorNonCOM[2][2] - unscaledMass * PxReal((unscaledCoM.x*unscaledCoM.x + unscaledCoM.y*unscaledCoM.y));
165 unscaledInertiaTensorCOM[0][1] = unscaledInertiaTensorCOM[1][0] = (unscaledInertiaTensorNonCOM[0][1] + unscaledMass * PxReal(unscaledCoM.x*unscaledCoM.y));
166 unscaledInertiaTensorCOM[1][2] = unscaledInertiaTensorCOM[2][1] = (unscaledInertiaTensorNonCOM[1][2] + unscaledMass * PxReal(unscaledCoM.y*unscaledCoM.z));
167 unscaledInertiaTensorCOM[0][2] = unscaledInertiaTensorCOM[2][0] = (unscaledInertiaTensorNonCOM[0][2] + unscaledMass * PxReal(unscaledCoM.z*unscaledCoM.x));
168
169 const PxMeshScale& s = g.scale;
170 mass = unscaledMass * s.scale.x * s.scale.y * s.scale.z;
171 centerOfMass = s.transform(unscaledCoM);
172 inertiaTensor = scaleInertia(unscaledInertiaTensorCOM, s.rotation, s.scale);
173 }
174 break;
175
176 default:
177 {
178 *this = PxMassProperties();
179 }
180 }
181
182 PX_ASSERT(inertiaTensor.column0.isFinite() && inertiaTensor.column1.isFinite() && inertiaTensor.column2.isFinite());
183 PX_ASSERT(centerOfMass.isFinite());
184 PX_ASSERT(PxIsFinite(mass));
185 }
186
194 {
195 PX_ASSERT(PxIsFinite(scale));
196
197 return PxMassProperties(mass * scale, inertiaTensor * scale, centerOfMass);
198 }
199
206 {
207 PX_ASSERT(t.isFinite());
208
210 centerOfMass += t;
211
212 PX_ASSERT(inertiaTensor.column0.isFinite() && inertiaTensor.column1.isFinite() && inertiaTensor.column2.isFinite());
213 PX_ASSERT(centerOfMass.isFinite());
214 }
215
223 PX_FORCE_INLINE static PxVec3 getMassSpaceInertia(const PxMat33& inertia, PxQuat& massFrame)
224 {
225 PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite());
226
227 PxVec3 diagT = PxDiagonalize(inertia, massFrame);
228 PX_ASSERT(diagT.isFinite());
229 PX_ASSERT(massFrame.isFinite());
230 return diagT;
231 }
232
241 PX_FORCE_INLINE static PxMat33 translateInertia(const PxMat33& inertia, const PxReal mass, const PxVec3& t)
242 {
243 PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite());
244 PX_ASSERT(PxIsFinite(mass));
245 PX_ASSERT(t.isFinite());
246
247 PxMat33 s( PxVec3(0,t.z,-t.y),
248 PxVec3(-t.z,0,t.x),
249 PxVec3(t.y,-t.x,0) );
250
251 PxMat33 translatedIT = s.getTranspose() * s * mass + inertia;
252 PX_ASSERT(translatedIT.column0.isFinite() && translatedIT.column1.isFinite() && translatedIT.column2.isFinite());
253 return translatedIT;
254 }
255
264 PX_FORCE_INLINE static PxMat33 rotateInertia(const PxMat33& inertia, const PxQuat& q)
265 {
266 PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite());
267 PX_ASSERT(q.isUnit());
268
269 PxMat33 m(q);
270 PxMat33 rotatedIT = m * inertia * m.getTranspose();
271 PX_ASSERT(rotatedIT.column0.isFinite() && rotatedIT.column1.isFinite() && rotatedIT.column2.isFinite());
272 return rotatedIT;
273 }
274
284 static PxMat33 scaleInertia(const PxMat33& inertia, const PxQuat& scaleRotation, const PxVec3& scale)
285 {
286 PX_ASSERT(inertia.column0.isFinite() && inertia.column1.isFinite() && inertia.column2.isFinite());
287 PX_ASSERT(scaleRotation.isUnit());
288 PX_ASSERT(scale.isFinite());
289
290 PxMat33 localInertiaT = rotateInertia(inertia, scaleRotation); // rotate inertia into scaling frame
291 PxVec3 diagonal(localInertiaT[0][0], localInertiaT[1][1], localInertiaT[2][2]);
292
293 PxVec3 xyz2 = PxVec3(diagonal.dot(PxVec3(0.5f))) - diagonal; // original x^2, y^2, z^2
294 PxVec3 scaledxyz2 = xyz2.multiply(scale).multiply(scale);
295
296 PxReal xx = scaledxyz2.y + scaledxyz2.z,
297 yy = scaledxyz2.z + scaledxyz2.x,
298 zz = scaledxyz2.x + scaledxyz2.y;
299
300 PxReal xy = localInertiaT[0][1] * scale.x * scale.y,
301 xz = localInertiaT[0][2] * scale.x * scale.z,
302 yz = localInertiaT[1][2] * scale.y * scale.z;
303
304 PxMat33 scaledInertia( PxVec3(xx, xy, xz),
305 PxVec3(xy, yy, yz),
306 PxVec3(xz, yz, zz));
307
308 PxMat33 scaledIT = rotateInertia(scaledInertia * (scale.x * scale.y * scale.z), scaleRotation.getConjugate());
309 PX_ASSERT(scaledIT.column0.isFinite() && scaledIT.column1.isFinite() && scaledIT.column2.isFinite());
310 return scaledIT;
311 }
312
321 static PxMassProperties sum(const PxMassProperties* props, const PxTransform* transforms, const PxU32 count)
322 {
323 PxReal combinedMass = 0.0f;
324 PxVec3 combinedCoM(0.0f);
325 PxMat33 combinedInertiaT = PxMat33(PxZero);
326
327 for(PxU32 i = 0; i < count; i++)
328 {
329 PX_ASSERT(props[i].inertiaTensor.column0.isFinite() && props[i].inertiaTensor.column1.isFinite() && props[i].inertiaTensor.column2.isFinite());
330 PX_ASSERT(props[i].centerOfMass.isFinite());
331 PX_ASSERT(PxIsFinite(props[i].mass));
332
333 combinedMass += props[i].mass;
334 const PxVec3 comTm = transforms[i].transform(props[i].centerOfMass);
335 combinedCoM += comTm * props[i].mass;
336 }
337
338 if(combinedMass > 0.f)
339 combinedCoM /= combinedMass;
340
341 for(PxU32 i = 0; i < count; i++)
342 {
343 const PxVec3 comTm = transforms[i].transform(props[i].centerOfMass);
344 combinedInertiaT += translateInertia(rotateInertia(props[i].inertiaTensor, transforms[i].q), props[i].mass, combinedCoM - comTm);
345 }
346
347 PX_ASSERT(combinedInertiaT.column0.isFinite() && combinedInertiaT.column1.isFinite() && combinedInertiaT.column2.isFinite());
348 PX_ASSERT(combinedCoM.isFinite());
349 PX_ASSERT(PxIsFinite(combinedMass));
350
351 return PxMassProperties(combinedMass, combinedInertiaT, combinedCoM);
352 }
353
354
357 PxReal mass;
358};
359
360#if !PX_DOXYGEN
361} // namespace physx
362#endif
363
365#endif
Class representing the geometry of a box.
Definition PxBoxGeometry.h:49
Class representing the geometry of a capsule.
Definition PxCapsuleGeometry.h:54
Convex mesh geometry class.
Definition PxConvexMeshGeometry.h:79
Custom geometry class. This class allows user to create custom geometries by providing a set of virtu...
Definition PxCustomGeometry.h:52
A geometry object.
Definition PxGeometry.h:79
Utility class to compute and manipulate mass and inertia tensor properties.
Definition PxMassProperties.h:65
PxVec3 centerOfMass
The center of mass of the object.
Definition PxMassProperties.h:356
static PX_FORCE_INLINE PxMat33 rotateInertia(const PxMat33 &inertia, const PxQuat &q)
Rotate an inertia tensor around the center of mass.
Definition PxMassProperties.h:264
static PX_FORCE_INLINE PxMat33 translateInertia(const PxMat33 &inertia, const PxReal mass, const PxVec3 &t)
Translate an inertia tensor using the parallel axis theorem.
Definition PxMassProperties.h:241
PX_FORCE_INLINE PxMassProperties operator*(const PxReal scale) const
Scale mass properties.
Definition PxMassProperties.h:193
PxReal mass
The mass of the object.
Definition PxMassProperties.h:357
PX_FORCE_INLINE PxMassProperties()
Default constructor.
Definition PxMassProperties.h:70
PxMassProperties(const PxGeometry &geometry)
Compute mass properties based on a provided geometry structure.
Definition PxMassProperties.h:84
static PX_FORCE_INLINE PxVec3 getMassSpaceInertia(const PxMat33 &inertia, PxQuat &massFrame)
Get the entries of the diagonalized inertia tensor and the corresponding reference rotation.
Definition PxMassProperties.h:223
static PxMassProperties sum(const PxMassProperties *props, const PxTransform *transforms, const PxU32 count)
Sum up individual mass properties.
Definition PxMassProperties.h:321
PxMat33 inertiaTensor
The inertia tensor of the object.
Definition PxMassProperties.h:355
PX_FORCE_INLINE void translate(const PxVec3 &t)
Translate the center of mass by a given vector and adjust the inertia tensor accordingly.
Definition PxMassProperties.h:205
PX_FORCE_INLINE PxMassProperties(const PxReal m, const PxMat33 &inertiaT, const PxVec3 &com)
Construct from individual elements.
Definition PxMassProperties.h:75
static PxMat33 scaleInertia(const PxMat33 &inertia, const PxQuat &scaleRotation, const PxVec3 &scale)
Non-uniform scaling of the inertia tensor.
Definition PxMassProperties.h:284
PX_CUDA_CALLABLE static PX_INLINE const PxMat33T createDiagonal(const PxVec3T< float > &d)
Construct from diagonal, off-diagonals are zero.
Definition PxMat33.h:186
3x3 matrix class
Definition PxMat33.h:91
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxMat33 getTranspose() const
Get transposed matrix.
Definition PxMat33.h:190
A class expressing a nonuniform scaling transformation.
Definition PxMeshScale.h:69
This is a quaternion class. For more information on quaternion mathematics consult a mathematics sour...
Definition PxQuat.h:50
PX_CUDA_CALLABLE bool isUnit() const
returns true if finite and magnitude is close to unit
Definition PxQuat.h:132
PX_CUDA_CALLABLE bool isFinite() const
returns true if all elements are finite (not NAN or INF, etc.)
Definition PxQuat.h:124
A class representing the geometry of a sphere.
Definition PxSphereGeometry.h:48
class representing a rigid euclidean transform as a quaternion and a vector
Definition PxTransform.h:49
Triangle mesh geometry class.
Definition PxTriangleMeshGeometry.h:81
PxTriangleMesh * triangleMesh
A reference to the mesh object.
Definition PxTriangleMeshGeometry.h:138
PxMeshScale scale
The scaling transformation.
Definition PxTriangleMeshGeometry.h:135
virtual void getMassInformation(PxReal &mass, PxMat33 &localInertia, PxVec3 &localCenterOfMass) const =0
Returns the mass properties of the mesh assuming unit density.
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 multiply(const PxVec3 &a) const
a[i] * b[i], for all i.
Definition PxVec3.h:336
PX_CUDA_CALLABLE PX_INLINE bool isFinite() const
returns true if all 3 elems of the vector are finite (not NAN or INF, etc.)
Definition PxVec3.h:156
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
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 bool PxIsFinite(float f)
returns true if the passed number is a finite floating point number as opposed to INF,...
Definition PxMath.h:326