Compatibility
This page defines the compatibility contract between:
Play (this repo)
forge dist bundles (
mujoco-wasm-forgeoutputs)browsers (module Workers + WASM)
Browsers
Play requires:
ES modules in the main thread
module Workers (
new Worker(url, { type: 'module' }))WebAssembly
Most modern Chromium/Firefox/Safari versions satisfy these requirements.
Forge dist bundle requirements
Play expects a forge dist/<ver>/ directory that contains at least:
mujoco.js(ESM-capable loader)mujoco.wasm
Recommended (optional):
version.json(optional; used for diagnostics in verbose/perf mode)
Viewer ABI extensions
Play validates that the loaded forge module exports a required viewer ABI set. If any export is missing, the Worker throws an error and reports the missing symbols.
The canonical list lives in worker/physics.worker.mjs:
// Scene pipeline (mjv_updateScene -> packed SoA)
'_mjwf_scene_update_and_pack',
'_mjwf_scene_maxgeom_ptr',
'_mjwf_scene_ngeom',
'_mjwf_scene_geomorder_ptr',
'_mjwf_scene_geoms_type_ptr',
'_mjwf_scene_geoms_pos_ptr',
'_mjwf_scene_geoms_mat_ptr',
'_mjwf_scene_geoms_size_ptr',
'_mjwf_scene_geoms_rgba_ptr',
'_mjwf_scene_geoms_matid_ptr',
'_mjwf_scene_geoms_dataid_ptr',
'_mjwf_scene_geoms_objtype_ptr',
'_mjwf_scene_geoms_objid_ptr',
'_mjwf_scene_geoms_category_ptr',
'_mjwf_scene_geoms_segid_ptr',
'_mjwf_scene_geoms_transparent_ptr',
// Viewer options (vopt pointers)
'_mjwf_vopt_flags_ptr',
'_mjwf_vopt_label_ptr',
'_mjwf_vopt_frame_ptr',
'_mjwf_vopt_flex_layer_ptr',
'_mjwf_vopt_bvh_depth_ptr',
'_mjwf_vopt_geomgroup_ptr',
'_mjwf_vopt_sitegroup_ptr',
'_mjwf_vopt_jointgroup_ptr',
'_mjwf_vopt_tendongroup_ptr',
'_mjwf_vopt_actuatorgroup_ptr',
'_mjwf_vopt_flexgroup_ptr',
'_mjwf_vopt_skingroup_ptr',
// Viewer camera pointers (mjvCamera fields)
'_mjwf_cam_type_ptr',
'_mjwf_cam_lookat_ptr',
'_mjwf_cam_distance_ptr',
'_mjwf_cam_azimuth_ptr',
'_mjwf_cam_elevation_ptr',
'_mjwf_cam_fixedcamid_ptr',
'_mjwf_cam_orthographic_ptr',
'_mjwf_cam_trackbodyid_ptr',
// Perturb pointers (mjvPerturb fields)
'_mjwf_pert_select_ptr',
'_mjwf_pert_active_ptr',
'_mjwf_pert_active2_ptr',
'_mjwf_pert_localpos_ptr',
'_mjwf_pert_scale_ptr',
'_mjwf_pert_flexselect_ptr',
'_mjwf_pert_skinselect_ptr',
// mjv helpers for perturb pipeline
'_mjwf_mjv_updateCamera',
'_mjwf_mjv_initPerturb',
'_mjwf_mjv_movePerturb',
'_mjwf_mjv_applyPerturbPose',
'_mjwf_mjv_applyPerturbForce',
// mjv helpers for selection
'_mjwf_mjv_select',
// mjv helpers for camera gestures
'_mjwf_mjv_moveCamera',
];
Notes:
This is a viewer contract (scene packing, vopt/camera/perturb pointers, and mjv helpers).
If you build your own forge bundle, ensure viewer extensions are enabled.
Local dev vs hosted layouts
When forgeBase= is omitted, Play resolves a default forge base template and
propagates it to the Worker:
single entry:
/forge/dist/{ver}/pthreads entry:
/forge/dist/{ver}/pthreads/
The local dev server (tools/dev_server.py) mounts /forge/ to a sibling
../mujoco-wasm-forge checkout if present (otherwise it falls back to the
Play repo root for local-only mirrors).
For explicit control (recommended for published demos), always pass
forgeBase=... and pin it to an immutable forge commit.