Loading...
Searching...
No Matches
massProperties.h
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"
19
20PXR_NAMESPACE_OPEN_SCOPE
21
22GfQuatf 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
29uint32_t UsdPhysicsGetNextIndex3(uint32_t i)
30{
31 return (i + 1 + (i >> 1)) & 3;
32}
33
34
35GfVec3f UsdPhysicsDiagonalize(const GfMatrix3f& m, GfQuatf& massFrame)
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
87{
88public:
89
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
99 USDPHYSICS_API UsdPhysicsMassProperties(const float m, const GfMatrix3f& inertiaT, const GfVec3f& com)
100 : _inertiaTensor(inertiaT), _centerOfMass(com), _mass(m)
101 {
102 }
103
107 USDPHYSICS_API UsdPhysicsMassProperties operator*(const float scale) const
108 {
109 return UsdPhysicsMassProperties(_mass * scale, _inertiaTensor * scale, _centerOfMass);
110 }
111
114 USDPHYSICS_API void Translate(const GfVec3f& t)
115 {
116 _inertiaTensor = TranslateInertia(_inertiaTensor, _mass, t);
117 _centerOfMass += t;
118 }
119
124 USDPHYSICS_API static GfVec3f GetMassSpaceInertia(const GfMatrix3f& inertia, GfQuatf& massFrame)
125 {
126
127 GfVec3f diagT = UsdPhysicsDiagonalize(inertia, massFrame);
128 return diagT;
129 }
130
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
152 USDPHYSICS_API static GfMatrix3f RotateInertia(const GfMatrix3f& inertia, const GfQuatf& q)
153 {
154 GfMatrix3f m(q);
155 GfMatrix3f rotatedIT = m.GetTranspose() * inertia * m;
156 return rotatedIT;
157 }
158
164 USDPHYSICS_API static UsdPhysicsMassProperties Sum(const UsdPhysicsMassProperties* props, const GfMatrix4f* transforms, const uint32_t count)
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
194 {
195 return _inertiaTensor;
196 }
197
200 void SetInertiaTensor(const GfMatrix3f& inTensor)
201 {
202 _inertiaTensor = inTensor;
203 }
204
208 {
209 return _centerOfMass;
210 }
211
214 float GetMass() const
215 {
216 return _mass;
217 }
218
221 void SetMass(float inMass)
222 {
223 _mass = inMass;
224 }
225
226private:
227 GfMatrix3f _inertiaTensor;
228 GfVec3f _centerOfMass;
229 float _mass;
230};
231
232PXR_NAMESPACE_CLOSE_SCOPE
233
234#endif
Stores a 3x3 matrix of float elements.
Definition: matrix3f.h:65
GfVec3f GetColumn(int i) const
Gets a column of the matrix as a Vec3.
Definition: matrix3f.h:160
GF_API GfMatrix3f GetTranspose() const
Returns the transpose of the matrix.
void SetColumn(int i, const GfVec3f &v)
Sets a column of the matrix from a Vec3.
Definition: matrix3f.h:148
Stores a 4x4 matrix of float elements.
Definition: matrix4f.h:71
GfVec3d Transform(const GfVec3d &vec) const
Transforms the row vector vec by the matrix, returning the result.
Definition: matrix4f.h:642
Basic type: a quaternion, a complex number with a real coefficient and three imaginary coefficients,...
Definition: quatf.h:43
Basic type for a vector of 3 float components.
Definition: vec3f.h:46
Mass properties computation class.
USDPHYSICS_API UsdPhysicsMassProperties operator*(const float scale) const
Scale mass properties.
void SetMass(float inMass)
Set mass inMass New mass.
static USDPHYSICS_API GfMatrix3f RotateInertia(const GfMatrix3f &inertia, const GfQuatf &q)
Rotate an inertia tensor around the center of mass inertia The inertia tensor to rotate.
USDPHYSICS_API void Translate(const GfVec3f &t)
Translate the center of mass by a given vector and adjust the inertia tensor accordingly.
static USDPHYSICS_API GfMatrix3f TranslateInertia(const GfMatrix3f &inertia, const float mass, const GfVec3f &t)
Translate an inertia tensor using the parallel axis theorem inertia The inertia tensor to translate.
float GetMass() const
Get mass.
static USDPHYSICS_API UsdPhysicsMassProperties Sum(const UsdPhysicsMassProperties *props, const GfMatrix4f *transforms, const uint32_t count)
Sum up individual mass properties.
static USDPHYSICS_API GfVec3f GetMassSpaceInertia(const GfMatrix3f &inertia, GfQuatf &massFrame)
Get the entries of the diagonalized inertia tensor and the corresponding reference rotation.
void SetInertiaTensor(const GfMatrix3f &inTensor)
Set inertia tensor inTensor New inertia tensor.
USDPHYSICS_API UsdPhysicsMassProperties()
Construct a MassProperties.
const GfVec3f & GetCenterOfMass() const
Get center of mass.
USDPHYSICS_API UsdPhysicsMassProperties(const float m, const GfMatrix3f &inertiaT, const GfVec3f &com)
Construct from individual elements.
const GfMatrix3f & GetInertiaTensor() const
Get inertia tensor.