HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
massProperties.h
Go to the documentation of this file.
1 //
2 // Copyright 2021 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_USD_MASS_PROPERTIES_H
8 #define PXR_USD_USD_MASS_PROPERTIES_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/usd/usdPhysics/api.h"
12 #include "pxr/usd/usd/common.h"
13 
14 #include "pxr/base/gf/vec3f.h"
15 #include "pxr/base/gf/quatf.h"
16 #include "pxr/base/gf/rotation.h"
17 #include "pxr/base/gf/matrix3f.h"
18 #include "pxr/base/gf/matrix4f.h"
19 
21 
22 GfQuatf UsdPhysicsIndexedRotation(uint32_t axis, float s, float c)
23 {
24  float v[3] = { 0, 0, 0 };
25  v[axis] = s;
26  return GfQuatf(c, v[0], v[1], v[2]);
27 }
28 
29 uint32_t UsdPhysicsGetNextIndex3(uint32_t i)
30 {
31  return (i + 1 + (i >> 1)) & 3;
32 }
33 
34 
36 {
37  const uint32_t MAX_ITERS = 24;
38 
39  GfQuatf q = GfQuatf(1.0);
40 
41  GfMatrix3f d;
42  for (uint32_t i = 0; i < MAX_ITERS; i++)
43  {
44  GfMatrix3f axes(q);
45  d = axes * m * axes.GetTranspose();
46 
47  float d0 = fabs(d[1][2]), d1 = fabs(d[0][2]), d2 = fabs(d[0][1]);
48  uint32_t a = uint32_t(d0 > d1 && d0 > d2 ? 0 : d1 > d2 ? 1 : 2); // rotation axis index, from largest
49  // off-diagonal
50  // element
51 
52  uint32_t a1 = UsdPhysicsGetNextIndex3(a), a2 = UsdPhysicsGetNextIndex3(a1);
53  if (d[a1][a2] == 0.0f || fabs(d[a1][a1] - d[a2][a2]) > 2e6 * fabs(2.0 * d[a1][a2]))
54  break;
55 
56  float w = (d[a1][a1] - d[a2][a2]) / (2.0f * d[a1][a2]); // cot(2 * phi), where phi is the rotation angle
57  float absw = fabs(w);
58 
59  GfQuatf r;
60  if (absw > 1000)
61  r = UsdPhysicsIndexedRotation(a, 1 / (4 * w), 1.0f); // h will be very close to 1, so use small angle approx instead
62  else
63  {
64  float t = 1 / (absw + sqrt(w * w + 1)); // absolute value of tan phi
65  float h = 1 / sqrt(t * t + 1); // absolute value of cos phi
66 
67  r = UsdPhysicsIndexedRotation(a, sqrt((1 - h) / 2) * ((w >= 0.0f) ? 1.0f : -1.0f), sqrt((1 + h) / 2));
68  }
69 
70  q = (q * r).GetNormalized();
71  }
72 
73  massFrame = q;
74  return GfVec3f(d.GetColumn(0)[0], d.GetColumn(1)[1], d.GetColumn(2)[2]);
75 }
76 
77 // -------------------------------------------------------------------------- //
78 // MASSPROPERTIES //
79 // -------------------------------------------------------------------------- //
80 
81 /// \class UsdPhysicsMassProperties
82 ///
83 /// Mass properties computation class. Used to combine together individual mass
84 /// properties and produce final one.
85 ///
87 {
88 public:
89 
90  /// Construct a MassProperties
91  USDPHYSICS_API UsdPhysicsMassProperties() : _inertiaTensor(0.0f), _centerOfMass(0.0f), _mass(1.0f)
92  {
93  _inertiaTensor[0][0] = 1.0;
94  _inertiaTensor[1][1] = 1.0;
95  _inertiaTensor[2][2] = 1.0;
96  }
97 
98  /// Construct from individual elements.
99  USDPHYSICS_API UsdPhysicsMassProperties(const float m, const GfMatrix3f& inertiaT, const GfVec3f& com)
100  : _inertiaTensor(inertiaT), _centerOfMass(com), _mass(m)
101  {
102  }
103 
104  /// Scale mass properties.
105  /// \p scale The linear scaling factor to apply to the mass properties.
106  /// \return The scaled mass properties.
108  {
109  return UsdPhysicsMassProperties(_mass * scale, _inertiaTensor * scale, _centerOfMass);
110  }
111 
112  /// Translate the center of mass by a given vector and adjust the inertia tensor accordingly.
113  /// \p t The translation vector for the center of mass.
115  {
116  _inertiaTensor = TranslateInertia(_inertiaTensor, _mass, t);
117  _centerOfMass += t;
118  }
119 
120  /// Get the entries of the diagonalized inertia tensor and the corresponding reference rotation.
121  /// \p inertia The inertia tensor to diagonalize.
122  /// \p massFrame The frame the diagonalized tensor refers to.
123  /// \return The entries of the diagonalized inertia tensor.
124  USDPHYSICS_API static GfVec3f GetMassSpaceInertia(const GfMatrix3f& inertia, GfQuatf& massFrame)
125  {
126 
127  GfVec3f diagT = UsdPhysicsDiagonalize(inertia, massFrame);
128  return diagT;
129  }
130 
131  /// Translate an inertia tensor using the parallel axis theorem
132  /// \p inertia The inertia tensor to translate.
133  /// \p mass The mass of the object.
134  /// \p t The relative frame to translate the inertia tensor to.
135  /// \return The translated inertia tensor.
136  USDPHYSICS_API static GfMatrix3f TranslateInertia(const GfMatrix3f& inertia, const float mass, const GfVec3f& t)
137  {
138  GfMatrix3f s;
139  s.SetColumn(0, GfVec3f(0, t[2], -t[1]));
140  s.SetColumn(1, GfVec3f(-t[2], 0, t[0]));
141  s.SetColumn(2, GfVec3f(t[1], -t[0], 0));
142 
143  GfMatrix3f translatedIT = s * s.GetTranspose() * mass + inertia;
144  return translatedIT;
145  }
146 
147 
148  /// Rotate an inertia tensor around the center of mass
149  /// \p inertia The inertia tensor to rotate.
150  /// \p q The rotation to apply to the inertia tensor.
151  /// \return The rotated inertia tensor.
153  {
154  GfMatrix3f m(q);
155  GfMatrix3f rotatedIT = m.GetTranspose() * inertia * m;
156  return rotatedIT;
157  }
158 
159  /// Sum up individual mass properties.
160  /// \p props Array of mass properties to sum up.
161  /// \p transforms Reference transforms for each mass properties entry.
162  /// \p count The number of mass properties to sum up.
163  /// \return The summed up mass properties.
165  {
166  float combinedMass = 0.0f;
167  GfVec3f combinedCoM(0.0f);
168  GfMatrix3f combinedInertiaT = GfMatrix3f(0.0f);
169 
170  for (uint32_t i = 0; i < count; i++)
171  {
172  combinedMass += props[i]._mass;
173  const GfVec3f comTm = transforms[i].Transform(props[i]._centerOfMass);
174  combinedCoM += comTm * props[i]._mass;
175  }
176 
177  if (combinedMass > 0.f)
178  combinedCoM /= combinedMass;
179 
180  for (uint32_t i = 0; i < count; i++)
181  {
182  const GfVec3f comTm = transforms[i].Transform(props[i]._centerOfMass);
183  combinedInertiaT += TranslateInertia(
184  RotateInertia(props[i]._inertiaTensor, GfQuatf(transforms[i].ExtractRotation().GetQuat())),
185  props[i]._mass, combinedCoM - comTm);
186  }
187 
188  return UsdPhysicsMassProperties(combinedMass, combinedInertiaT, combinedCoM);
189  }
190 
191  /// Get inertia tensor
192  /// \return Inertia tensor
194  {
195  return _inertiaTensor;
196  }
197 
198  /// Set inertia tensor
199  /// \p inTensor New inertia tensor.
200  void SetInertiaTensor(const GfMatrix3f& inTensor)
201  {
202  _inertiaTensor = inTensor;
203  }
204 
205  /// Get center of mass
206  /// \return Center of mass
207  const GfVec3f& GetCenterOfMass() const
208  {
209  return _centerOfMass;
210  }
211 
212  /// Get mass
213  /// \return Mass
214  float GetMass() const
215  {
216  return _mass;
217  }
218 
219  /// Set mass
220  /// \p inMass New mass.
221  void SetMass(float inMass)
222  {
223  _mass = inMass;
224  }
225 
226 private:
227  GfMatrix3f _inertiaTensor; //!< The inertia tensor of the object.
228  GfVec3f _centerOfMass; //!< The center of mass of the object.
229  float _mass; //!< The mass of the object.
230 };
231 
233 
234 #endif
PXR_NAMESPACE_OPEN_SCOPE GfQuatf UsdPhysicsIndexedRotation(uint32_t axis, float s, float c)
const GLdouble * v
Definition: glcorearb.h:837
static USDPHYSICS_API UsdPhysicsMassProperties Sum(const UsdPhysicsMassProperties *props, const GfMatrix4f *transforms, const uint32_t count)
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7694
static USDPHYSICS_API GfMatrix3f RotateInertia(const GfMatrix3f &inertia, const GfQuatf &q)
Definition: vec3f.h:45
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
static USDPHYSICS_API GfVec3f GetMassSpaceInertia(const GfMatrix3f &inertia, GfQuatf &massFrame)
GA_API const UT_StringHolder com
GF_API GfMatrix3f GetTranspose() const
Returns the transpose of the matrix.
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
GfVec3f UsdPhysicsDiagonalize(const GfMatrix3f &m, GfQuatf &massFrame)
Definition: quatf.h:42
GA_API const UT_StringHolder scale
GLfloat f
Definition: glcorearb.h:1926
void SetMass(float inMass)
const GfVec3f & GetCenterOfMass() const
USDPHYSICS_API void Translate(const GfVec3f &t)
GfVec3d Transform(const GfVec3d &vec) const
Definition: matrix4f.h:642
uint32_t UsdPhysicsGetNextIndex3(uint32_t i)
GfVec3f GetColumn(int i) const
Gets a column of the matrix as a Vec3.
Definition: matrix3f.h:160
USDPHYSICS_API UsdPhysicsMassProperties operator*(const float scale) const
GLdouble t
Definition: glad.h:2397
#define USDPHYSICS_API
Definition: api.h:23
USDPHYSICS_API UsdPhysicsMassProperties(const float m, const GfMatrix3f &inertiaT, const GfVec3f &com)
Construct from individual elements.
GA_API const UT_StringHolder mass
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
void SetInertiaTensor(const GfMatrix3f &inTensor)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
const GfMatrix3f & GetInertiaTensor() const
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
static USDPHYSICS_API GfMatrix3f TranslateInertia(const GfMatrix3f &inertia, const float mass, const GfVec3f &t)
void SetColumn(int i, const GfVec3f &v)
Sets a column of the matrix from a Vec3.
Definition: matrix3f.h:148
GLboolean r
Definition: glcorearb.h:1222
USDPHYSICS_API UsdPhysicsMassProperties()
Construct a MassProperties.
GLint GLsizei count
Definition: glcorearb.h:405
GLenum GLuint GLsizei const GLenum * props
Definition: glcorearb.h:2525