Don't produce mesh polygon data unless graph data is present. This fixes some nondeterminism in the compiler.

Repro instructions (note compiler cache and threading must be enabled):

Assume we have a cube.stl mesh containing face data and the following XML:

<mujoco>
  <asset>
    <mesh name="cube" file="cube.stl"/>
    <mesh name="unused" file="cube.stl"/>
  </asset>
  <worldbody>
    <geom type="mesh" mesh="cube"/>
  </worldbody>
</mujoco>

Suppose Thread A processes "cube" and Thread B processes "unused". Thread A will generate the mesh hull and will generate polygon data from faces from qhull. Thread B will NOT generate the mesh hull and will generate polygon data from faces coming from mesh file. Thread A beats Thread B to caching the mesh.

When "unused" is later pulled from the cache it gets the polygon data that was generated from "cube" which is not the same that was generated from "unused".

PiperOrigin-RevId: 878336494
Change-Id: I275b09b44490c54b2a5f09d91d0cc047026090f2
This commit is contained in:
Kyle Bayes
2026-03-04 00:36:22 -08:00
committed by Copybara-Service
parent a8d6b0c848
commit 8ab791fdf7
2 changed files with 39 additions and 26 deletions
+9
View File
@@ -2062,6 +2062,15 @@ static inline int simplexDim(int* v1i, int* v2i, int* v3i, mjtNum** v1, mjtNum**
// recover multiple contacts from EPA polytope
static void multicontact(Polytope* pt, Face* face, mjCCDStatus* status,
mjCCDObj* obj1, mjCCDObj* obj2) {
const int* polynum = obj1->model->mesh_polynum;
const int* geom_dataid = obj1->model->geom_dataid;
if (obj1->geom_type == mjGEOM_MESH && !polynum[geom_dataid[obj1->geom]]) {
return;
}
if (obj2->geom_type == mjGEOM_MESH && !polynum[geom_dataid[obj2->geom]]) {
return;
}
mjtNum face1[mjMAX_POLYVERT * 3], face2[mjMAX_POLYVERT * 3], endverts[mjMAX_POLYVERT * 3];
// get vertices of faces from EPA
int v11i = pt->verts[face->verts[0]].index1;