MCPcopy Create free account
hub / github.com/URLab-Sim/UnrealRoboticsLab / materialize_inline_meshes

Function materialize_inline_meshes

Scripts/clean_meshes.py:220–290  ·  view source on GitHub ↗

Rewrite `` `` (MuJoCo's inline-data form) to `` `` by emitting an OBJ next to the rest of the mesh assets. Returns the number of inline meshes materialized. MuJoCo accepts meshes declared inline via ``vertex`` (flat list of 3-tuple floats

(root, mesh_base: Path)

Source from the content-addressed store, hash-verified

218 elif elem.tag == "compiler":
219 # Paths are now baked into each file=, so clear the dir prefixes.
220 for attr in ("meshdir", "texturedir", "assetdir"):
221 new_elem.attrib.pop(attr, None)
222
223 for child in list(elem):
224 _append_expanded(new_elem, child, src_dir, root_dir,
225 meshdir, texturedir, assetdir, visited)
226
227
228def flatten_includes(root, root_dir: Path):
229 """Resolve every <include> into a single self-contained <mujoco> tree.
230
231 gym-aloha (and many MJCF models) split a robot across <include> fragments
232 rooted in <mujocoinclude>, including files referenced from inside <worldbody>.
233 Unreal&#x27;s importer must see one flat document so all <asset>/<compiler>/body
234 content is visible and there is exactly one worldbody. Returns the new root
235 element (a <mujoco>). No-op-equivalent for files without includes.
236 """
237 md, txd, ad = _compiler_dirs(root)
238 visited = set()
239 new_root = ET.Element("mujoco", dict(root.attrib))
240 for child in list(root):
241 _append_expanded(new_root, child, root_dir, root_dir, md, txd, ad, visited)
242 return new_root
243
244
245def materialize_inline_meshes(root, mesh_base: Path) -> int:
246 """Rewrite ``<mesh vertex="..." face="...">`` (MuJoCo&#x27;s inline-data form)
247 to ``<mesh file="...">`` by emitting an OBJ next to the rest of the
248 mesh assets. Returns the number of inline meshes materialized.
249
250 MuJoCo accepts meshes declared inline via ``vertex`` (flat list of
251 3-tuple floats) and ``face`` (flat list of 3-tuple ints) attributes
252 instead of an external ``file``. Unreal's importer can't follow the
253 inline form, so we synthesize a real OBJ on disk and rewrite the
254 ``<mesh>`` element to point at it. The downstream conversion phase
255 then produces a GLB companion just like any other ``file=`` mesh.
256 """
257 materialized = 0
258 mesh_base.mkdir(parents=True, exist_ok=True)
259 for mesh_el in list(root.iter("mesh")):
260 if mesh_el.get("file"):
261 continue
262 vertex_attr = mesh_el.get("vertex")
263 face_attr = mesh_el.get("face")
264 if not vertex_attr or not face_attr:
265 continue
266
267 name = mesh_el.get("name")
268 if not name:
269 print(f" x Inline mesh has no name; skipping (cannot synthesize filename)")
270 continue
271
272 try:
273 verts = _parse_floats(vertex_attr)
274 faces = [int(t) for t in face_attr.replace(",", " ").split() if t]
275 except ValueError as e:
276 print(f" x Failed to parse vertex/face for '{name}': {e}")
277 continue

Callers 1

process_xmlFunction · 0.85

Calls 1

_parse_floatsFunction · 0.85

Tested by

no test coverage detected