drawing_scene/
drawing_scene.rs

1//! This example illustrates how to use the MjViewer::user_scn_mut to draw custom
2//! visual-only geoms.
3use std::time::Duration;
4
5use mujoco_rs::viewer::MjViewer;
6use mujoco_rs::prelude::*;
7
8
9const EXAMPLE_MODEL: &str = "
10<mujoco>
11  <worldbody>
12    <light ambient=\"0.2 0.2 0.2\"/>
13    <body name=\"ball1\" pos=\".2 .2 .2\">
14        <geom size=\".1 .1 .1\" rgba=\"0 1 0 1\" solref=\"0.004 1.0\"/>
15        <joint name=\"ball1_joint\" type=\"free\"/>
16    </body>
17
18    <body name=\"ball2\" pos=\".5 .2 .2\">
19        <geom size=\".1\" rgba=\"0 1 0 1\" solref=\"0.004 1.0\"/>
20        <joint name=\"ball2_joint\" type=\"free\"/>
21    </body>
22
23    <geom name=\"floor1\" type=\"plane\" size=\"10 10 1\" euler=\"15 4 0\" solref=\"0.004 1.0\"/>
24    <geom name=\"floor2\" type=\"plane\" pos=\"15 -20 0\" size=\"10 10 1\" euler=\"-15 -4 0\" solref=\"0.004 1.0\"/>
25
26  </worldbody>
27</mujoco>
28";
29
30
31
32fn main() {
33    /* Create model and data */
34    let model = MjModel::from_xml_string(EXAMPLE_MODEL).expect("could not load the model");
35    let mut data = model.make_data();
36
37    /* Launch a passive Rust-native viewer */
38    let mut viewer = MjViewer::launch_passive(
39        &model,
40        10  // create space for 10 visual-only geoms
41    )
42        .expect("could not launch the viewer");
43
44    /* Obtain joint info */
45    let ball1_joint_info = data.joint("ball1_joint").unwrap();
46    let ball2_joint_info = data.joint("ball2_joint").unwrap();
47
48    /* Give the first ball some y-velocity to showcase the visualization */
49    ball1_joint_info.view_mut(&mut data).qvel[1] = 2.0;
50
51    let timestep = model.ffi().opt.timestep;
52    let mut user_scn;
53    while viewer.running() {
54        /* Step the simulation and sync the viewer */
55        viewer.sync(&mut data);
56        data.step();
57
58        /* Prepare the scene */
59        user_scn = viewer.user_scn_mut();  // obtain a mutable reference to the user scene. The method name mirrors the C++ viewer.
60        user_scn.clear_geom();  // clear existing geoms
61
62        /* Create a line, that (visually) connects the two balls we have in the example model */
63        let new_geom = user_scn.create_geom(
64            MjtGeom::mjGEOM_LINE,  // type of geom to draw.
65            None,  // size, ignore here as we set it below.
66            None,   // position: ignore here as we set it below.
67            None,   // rotational matrix: ignore here as we set it below.
68            Some([1.0, 1.0, 1.0, 1.0])  // color (rgba): pure white.
69        );
70
71        /* Read X, Y and Z coordinates of both balls. */
72        let ball1_position = ball1_joint_info.view(&data).qpos[..3]
73            .try_into().unwrap();
74        let ball2_position = ball2_joint_info.view(&data).qpos[..3]
75            .try_into().unwrap();
76
77        /* Modify the visual geom's position, orientation and length, to connect the balls */
78        new_geom.connect(
79            0.0,            // width
80            ball1_position,  // from
81            ball2_position     //  to
82        );
83
84        std::thread::sleep(Duration::from_secs_f64(timestep));
85    }
86}