C++#
Build & Launch#
The native C++ Studio application lives in studio/ and ships prebuilt in MuJoCo binary releases (see
Standalone Application). To build and launch mujoco_studio from the
repository root, use the build_studio_cpp_viewer step in .github/workflows/build_steps.sh (see the workflows README for prerequisites), or run
studio/build.sh (which also supports Git Bash
on Windows, debug/configure/build arguments, and CMAKE_ARGS):
bash .github/workflows/build_steps.sh build_studio_cpp_viewer
./build_host/bin/mujoco_studio model/humanoid/humanoid.xml
To configure an isolated CMake build tree manually without helper scripts:
cmake -B build-studio \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_STATIC_LIBCXX=OFF \
-DBUILD_SHARED_LIB=OFF \
-DMUJOCO_USE_FILAMENT=ON \
-DMUJOCO_BUILD_EXAMPLES=OFF \
-DMUJOCO_BUILD_SIMULATE=OFF \
-DMUJOCO_BUILD_TESTS=OFF \
-DMUJOCO_TEST_PYTHON_UTIL=OFF \
-DMUJOCO_WITH_USD=OFF \
-DMUJOCO_BUILD_STUDIO=ON \
-DFILAMENT_SKIP_SAMPLES=ON \
-DCMAKE_CXX_FLAGS=-Wno-error=deprecated-declarations \
-DFILAMENT_SHORTEN_MSVC_COMPILATION=OFF
cmake --build build-studio --config Release --target mujoco_studio --parallel
./build-studio/bin/mujoco_studio model/humanoid/humanoid.xml
mujoco_studio resolves its staged font and Filament assets relative to the executable directory, and supports the
following --gfx graphics modes (graphics_mode.h):
opengl/opengl_headless/opengl_software: Filament OpenGL desktop window, offscreen headless context (blitted to a software SDL2 window in the C++ app), or software rasterizer.vulkan/vulkan_software: Filament Vulkan desktop window or software rasterizer.
On Linux, direct window rendering expects X11 (--gfx=opengl is rejected under Wayland). In a Wayland session,
omitting --gfx falls back to opengl_headless; for direct GPU presentation, use an X11 session.
Custom C++ executables can embed and launch Studio via mujoco::studio::LaunchStudio declared in launcher.h after calling absl::ParseCommandLine.
LaunchStudio accepts a LauncherConfig and manages resource provider registration, mujoco::studio::App
(app.h) initialization, the background physics
thread on desktop builds, and the main UI/render loop.
C++ Plugins#
Note
C++ plugins currently use a POD callback-struct interface distinct from the message-handler API used by Python plugins; future work will unify the two plugin systems.
In C++, Studio plugins are plain-old-data (POD) structs with function pointers defined in ux/plugin.h. Plugins are copied by value into a global
registry via mujoco::studio::RegisterPlugin(plugin). Do not subclass them; store custom state in the void* data
field:
Struct ( |
Callbacks |
Purpose |
|---|---|---|
|
|
Registers a toggleable window in the Plugins main menu and builds custom |
|
|
Appends custom mjvGeom objects to the mjvScene before rendering. |
|
|
Supplies models from custom sources and hooks into physics updates and mj_step calls. |
|
|
Invokes a callback when the configured ImGui |
|
|
Mutates mjSpec before compilation; returning |
Plugin Registration#
C++ plugins can self-register inside a linked library or translation unit using mjPLUGIN_LIB_INIT, which runs
before main() without modifying the launcher, or register explicitly in main() before calling
LaunchStudio:
#include "absl/flags/parse.h"
#include <imgui.h>
#include <mujoco/mujoco.h>
#include "studio/launcher.h"
#include "studio/ux/plugin.h"
struct TelemetryState {
float gain = 1.0f;
};
void RegisterTelemetryPlugin() {
static TelemetryState state;
mujoco::studio::GuiPlugin gui_plugin;
gui_plugin.name = "Telemetry";
gui_plugin.active = true;
gui_plugin.data = &state;
gui_plugin.update = [](mujoco::studio::GuiPlugin* self) {
auto* s = static_cast<TelemetryState*>(self->data);
ImGui::SliderFloat("Gain", &s->gain, 0.0f, 10.0f);
};
mujoco::studio::RegisterPlugin(gui_plugin);
}
// Option A: Register automatically when linked or loaded as a plugin library.
mjPLUGIN_LIB_INIT(telemetry_plugin) {
RegisterTelemetryPlugin();
}
// Option B: Register explicitly in a custom executable before LaunchStudio.
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
RegisterTelemetryPlugin();
mujoco::studio::LauncherConfig config;
config.title = "Custom Studio";
config.model_file = "path/to/robot.xml";
return mujoco::studio::LaunchStudio(argc, argv, config);
}
WebAssembly Build#
The MuJoCo Live web application (live.mujoco.org) compiles
mujoco::studio::App to WebAssembly via Emscripten (emscripten.cc). JavaScript drives the application loop
through Embind bindings—init, loadFile, loadUrl, loadKeyframe, renderFrame, and deinit—and
emscripten.cc registers custom mjpResourceProvider handlers for http:, https:, and github: URLs
backed by an asynchronous fetch cache. For example, clicking any robot thumbnail on the MuJoCo Menagerie page opens that robot directly in live.mujoco.org via its
github: model URL. See MuJoCo Live in Web Viewers for browser usage,
drag-and-drop archives, and ?model= URL parameters.