25
25
26
26
#include < gz/sim/Util.hh>
27
27
28
- #include < gz/common/graphics.hh>
29
- #include < gz/common/Mesh.hh>
30
28
#include < gz/common/MeshManager.hh>
29
+ #include < gz/common/SubMesh.hh>
31
30
32
31
#include < gz/math/Vector3.hh>
33
32
#include < gz/math/Pose3.hh>
@@ -42,15 +41,15 @@ using namespace sim;
42
41
void MeshInertiaCalculator::GetMeshTriangles (
43
42
std::vector<Triangle> &_triangles,
44
43
const gz::math::Vector3d &_meshScale,
45
- const gz::common::Mesh* _mesh )
44
+ const gz::common::SubMesh* _subMesh )
46
45
{
47
46
// Get the vertices & indices of the mesh
48
47
double * vertArray = nullptr ;
49
48
int * indArray = nullptr ;
50
- _mesh ->FillArrays (&vertArray, &indArray);
49
+ _subMesh ->FillArrays (&vertArray, &indArray);
51
50
52
51
// Add check to see if size of the ind array is divisible by 3
53
- for (unsigned int i = 0 ; i < _mesh ->IndexCount (); i += 3 )
52
+ for (unsigned int i = 0 ; i < _subMesh ->IndexCount (); i += 3 )
54
53
{
55
54
Triangle triangle;
56
55
triangle.v0 .X () = vertArray[static_cast <ptrdiff_t >(3 * indArray[i])];
@@ -187,62 +186,65 @@ void MeshInertiaCalculator::CalculateMassProperties(
187
186
188
187
// ////////////////////////////////////////////////
189
188
std::optional<gz::math::Inertiald> MeshInertiaCalculator::operator ()
190
- (sdf::Errors& _errors,
189
+ (sdf::Errors & _errors,
191
190
const sdf::CustomInertiaCalcProperties& _calculatorParams)
192
191
{
193
- const gz::common::Mesh *mesh = nullptr ;
194
192
const double density = _calculatorParams.Density ();
195
193
196
194
auto sdfMesh = _calculatorParams.Mesh ();
197
195
198
196
if (sdfMesh == std::nullopt)
199
197
{
200
198
gzerr << " Could not calculate inertia for mesh "
201
- " as it std::nullopt" << std::endl;
199
+ " as mesh SDF is std::nullopt" << std::endl;
202
200
_errors.push_back ({sdf::ErrorCode::FATAL_ERROR,
203
- " Could not calculate mesh inertia as mesh object is"
201
+ " Could not calculate mesh inertia as mesh SDF is"
204
202
" std::nullopt" });
205
203
return std::nullopt;
206
204
}
207
205
208
- auto fullPath = asFullPath (sdfMesh->Uri (), sdfMesh->FilePath ());
209
-
210
- if (fullPath.empty ())
206
+ const common::Mesh *mesh = loadMesh (*sdfMesh);
207
+ if (!mesh)
211
208
{
212
- gzerr << " Mesh geometry missing uri " << std::endl;
213
- _errors.push_back ({sdf::ErrorCode::URI_INVALID ,
214
- " Attempting to load the mesh but the URI seems to be incorrect " });
209
+ gzerr << " Failed to load mesh: " << sdfMesh-> Uri () << std::endl;
210
+ _errors.push_back ({sdf::ErrorCode::FATAL_ERROR ,
211
+ " Could not calculate mesh inertia as mesh is not loaded. " });
215
212
return std::nullopt;
216
213
}
217
214
218
- // Load the Mesh
219
- gz::common::MeshManager *meshManager = gz::common::MeshManager::Instance ();
220
- mesh = meshManager-> Load (fullPath) ;
221
- if (! mesh)
215
+ // Compute inertia for each submesh then sum up to get the final inertia
216
+ // values.
217
+ gz::math::Inertiald meshInertial ;
218
+ for ( unsigned int i = 0 ; i < mesh-> SubMeshCount (); ++i )
222
219
{
223
- gzerr << " Failed to load mesh: " << fullPath << std::endl;
224
- return std::nullopt;
225
- }
226
- std::vector<Triangle> meshTriangles;
227
- gz::math::MassMatrix3d meshMassMatrix;
228
- gz::math::Pose3d centreOfMass;
220
+ std::vector<Triangle> meshTriangles;
221
+ gz::math::MassMatrix3d meshMassMatrix;
222
+ gz::math::Pose3d centreOfMass;
229
223
230
- // Create a list of Triangle objects from the mesh vertices and indices
231
- this ->GetMeshTriangles (meshTriangles, sdfMesh->Scale (), mesh);
224
+ // Create a list of Triangle objects from the mesh vertices and indices
225
+ auto submesh = mesh->SubMeshByIndex (i).lock ();
226
+ this ->GetMeshTriangles (meshTriangles, sdfMesh->Scale (), submesh.get ());
232
227
233
- // Calculate mesh mass properties
234
- this ->CalculateMassProperties (meshTriangles, density,
235
- meshMassMatrix, centreOfMass);
228
+ // Calculate mesh mass properties
229
+ this ->CalculateMassProperties (meshTriangles, density,
230
+ meshMassMatrix, centreOfMass);
236
231
237
- gz::math::Inertiald meshInertial;
232
+ if (meshMassMatrix.IsValid ())
233
+ meshInertial += gz::math::Inertiald (meshMassMatrix, centreOfMass);
234
+ }
238
235
239
- if (!meshInertial.SetMassMatrix (meshMassMatrix))
236
+ if (meshInertial.MassMatrix ().Mass () <= 0.0 ||
237
+ !meshInertial.MassMatrix ().IsValid ())
240
238
{
239
+ gzerr << " Failed to computed valid inertia in MeshInertiaCalculator. "
240
+ << " Ensure that the mesh is water tight, or try optimizing the mesh "
241
+ << " by setting the //mesh/@optimization attribute in SDF to "
242
+ << " `convex_hull` or `convex_decomposition`."
243
+ << std::endl;
244
+ _errors.push_back ({sdf::ErrorCode::WARNING,
245
+ " Could not calculate valid mesh inertia" });
241
246
return std::nullopt;
242
247
}
243
- else
244
- {
245
- meshInertial.SetPose (centreOfMass);
246
- return meshInertial;
247
- }
248
+
249
+ return meshInertial;
248
250
}
0 commit comments