mujoco_rs/wrappers/
mj_rendering.rs

1//! Definitions related to rendering.
2use std::{ffi::CString, mem::{zeroed, MaybeUninit}};
3use crate::mujoco_c::*;
4
5use super::mj_model::MjModel;
6use std::ptr;
7
8/***********************************************************************************************************************
9** MjrRectangle
10***********************************************************************************************************************/
11pub type MjrRectangle = mjrRect;
12impl MjrRectangle {
13    pub fn new(left: i32, bottom: i32, width: i32, height: i32) -> Self {
14        Self {
15            left,
16            bottom,
17            width,
18            height,
19        }
20    }
21}
22
23impl Default for MjrRectangle {
24    fn default() -> Self {
25        unsafe { zeroed() }
26    }
27}
28
29
30/// These are the possible grid positions for text overlays. They are used as an argument to the function
31/// `mjr_overlay`.
32pub type MjtGridPos = mjtGridPos;
33
34/// These are the possible framebuffers. They are used as an argument to the function `mjr_setBuffer`.
35pub type MjtFramebuffer = mjtFramebuffer;
36
37/// These are the depth mapping options. They are used as a value for the ``readPixelDepth`` attribute of the
38/// `mjrContext` struct, to control how the depth returned by `mjr_readPixels` is mapped from
39/// ``znear`` to ``zfar``.
40pub type MjtDepthMap = mjtDepthMap;
41
42/// These are the possible font sizes. The fonts are predefined bitmaps stored in the dynamic library at three different
43/// sizes.
44pub type MjtFontScale = mjtFontScale;
45
46/// These are the possible font types.
47pub type MjtFont = mjtFont;
48
49/***********************************************************************************************************************
50** MjrContext
51***********************************************************************************************************************/
52#[derive(Debug)]
53pub struct MjrContext {
54    ffi: mjrContext
55}
56
57impl MjrContext {
58    pub fn new(model: &MjModel) -> Self {
59        unsafe {
60            let mut c = MaybeUninit::uninit();
61            mjr_defaultContext(c.as_mut_ptr());
62            mjr_makeContext(model.ffi(), c.as_mut_ptr(), MjtFontScale::mjFONTSCALE_100 as i32);
63            Self {ffi: c.assume_init()}
64        }
65    }
66
67    /// Set OpenGL framebuffer for rendering to mjFB_OFFSCREEN.
68    pub fn offscreen(&mut self) -> &mut Self {
69        unsafe {
70            mjr_setBuffer(MjtFramebuffer::mjFB_OFFSCREEN as i32, &mut self.ffi);
71        }
72        self
73    }
74
75    /// Set OpenGL framebuffer for rendering to mjFB_WINDOW.
76    pub fn window(&mut self) -> &mut Self {
77        unsafe {
78            mjr_setBuffer(MjtFramebuffer::mjFB_WINDOW as i32, &mut self.ffi);
79        }
80        self
81    }
82
83    /// Change font of existing context.
84    pub fn change_font(&mut self, fontscale: MjtFontScale) {
85        unsafe { mjr_changeFont(fontscale as i32, self.ffi_mut()) }
86    }
87
88    /// Add Aux buffer with given index to context; free previous Aux buffer.
89    pub fn add_aux(&mut self, index: usize, width: u32, height: u32, samples: usize) {
90        unsafe { mjr_addAux(index as i32, width as i32, height as i32, samples as i32, self.ffi_mut()); }
91    }
92
93    /// Resize offscreen buffers.
94    pub fn resize_offscreen(&mut self, width: u32, height: u32) {
95        unsafe { mjr_resizeOffscreen(width as i32, height as i32, self.ffi_mut()); }
96    }
97
98    /// Upload texture to GPU, overwriting previous upload if any.
99    pub fn upload_texture(&mut self, model: &MjModel, texid: u32) {
100        unsafe { mjr_uploadTexture(model.ffi(), self.ffi_mut(), texid as i32); }
101    }
102
103    /// Make the context's buffer current again.
104    pub fn restore_buffer(&mut self) {
105        unsafe { mjr_restoreBuffer(self.ffi_mut()); }
106    }
107
108    pub fn mjr_set_buffer(&mut self, framebuffer: i32) {
109        unsafe { mjr_setBuffer(framebuffer, self.ffi_mut()); }
110    }
111
112    /// Read pixels from current OpenGL framebuffer to client buffer.
113    /// The ``rgb`` array is of size [width * height * 3], while ``depth`` is of size [width * height].
114    pub fn read_pixels(&self, rgb: Option<&mut [u8]>, depth: Option<&mut [f32]>, viewport: &MjrRectangle) {
115        unsafe {
116            mjr_readPixels(
117                rgb.map_or(ptr::null_mut(), |x| x.as_mut_ptr()),
118                depth.map_or(ptr::null_mut(), |x| x.as_mut_ptr()),
119                viewport.clone(), self.ffi()
120            )
121        }
122    }
123
124    /// Set Aux buffer for custom OpenGL rendering (call restoreBuffer when done).
125    pub fn set_aux(&mut self, index: usize) {
126        unsafe { mjr_setAux(index as i32, self.ffi_mut()); }
127    }
128
129    /// Draws a text overlay. The optional `overlay2` parameter displays additional overlay, next to `overlay`.
130    /// # Panics
131    /// When the `overlay` or `overlay2` contain '\0' characters, a panic occurs.
132    pub fn overlay(&mut self, font: MjtFont, gridpos: MjtGridPos, viewport: MjrRectangle, overlay: &str, overlay2: Option<&str>) {
133        let c_overlay = CString::new(overlay).unwrap();
134        let c_overlay2 = overlay2.map(|x| CString::new(x).unwrap());
135
136        unsafe { mjr_overlay(
137            font as i32, gridpos as i32, viewport,
138            c_overlay.as_ptr(),
139            c_overlay2.as_ref().map_or(std::ptr::null(), |x| x.as_ptr()),
140            self.ffi()
141        ); }
142    }
143
144    pub fn ffi(&self) -> &mjrContext {
145        &self.ffi
146    }
147
148    pub unsafe fn ffi_mut(&mut self) -> &mut mjrContext {
149        &mut self.ffi
150    }
151}
152
153impl Drop for MjrContext {
154    fn drop(&mut self) {
155        unsafe {
156            mjr_freeContext(&mut self.ffi);
157        }
158    }
159}
160