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/***********************************************************************************************************************
31** MjtFont
32***********************************************************************************************************************/
33pub type MjtFont = mjtFont;
34
35/***********************************************************************************************************************
36** MjtFontScale
37***********************************************************************************************************************/
38pub type MjtFontScale = mjtFontScale;
39
40/***********************************************************************************************************************
41** MjtGridPos
42***********************************************************************************************************************/
43pub type MjtGridPos = mjtGridPos;
44
45/***********************************************************************************************************************
46** MjtFramebuffer
47***********************************************************************************************************************/
48pub type MjtFramebuffer = mjtFramebuffer;
49
50/***********************************************************************************************************************
51** MjrContext
52***********************************************************************************************************************/
53#[derive(Debug)]
54pub struct MjrContext {
55    ffi: mjrContext
56}
57
58impl MjrContext {
59    pub fn new(model: &MjModel) -> Self {
60        unsafe {
61            let mut c = MaybeUninit::uninit();
62            mjr_defaultContext(c.as_mut_ptr());
63            mjr_makeContext(model.ffi(), c.as_mut_ptr(), MjtFontScale::mjFONTSCALE_100 as i32);
64            Self {ffi: c.assume_init()}
65        }
66    }
67
68    /// Set OpenGL framebuffer for rendering to mjFB_OFFSCREEN.
69    pub fn offscreen(&mut self) -> &mut Self {
70        unsafe {
71            mjr_setBuffer(MjtFramebuffer::mjFB_OFFSCREEN as i32, &mut self.ffi);
72        }
73        self
74    }
75
76    /// Set OpenGL framebuffer for rendering to mjFB_WINDOW.
77    pub fn window(&mut self) -> &mut Self {
78        unsafe {
79            mjr_setBuffer(MjtFramebuffer::mjFB_WINDOW as i32, &mut self.ffi);
80        }
81        self
82    }
83
84    /// Change font of existing context.
85    pub fn change_font(&mut self, fontscale: MjtFontScale) {
86        unsafe { mjr_changeFont(fontscale as i32, self.ffi_mut()) }
87    }
88
89    /// Add Aux buffer with given index to context; free previous Aux buffer.
90    pub fn add_aux(&mut self, index: usize, width: u32, height: u32, samples: usize) {
91        unsafe { mjr_addAux(index as i32, width as i32, height as i32, samples as i32, self.ffi_mut()); }
92    }
93
94    /// Resize offscreen buffers.
95    pub fn resize_offscreen(&mut self, width: u32, height: u32) {
96        unsafe { mjr_resizeOffscreen(width as i32, height as i32, self.ffi_mut()); }
97    }
98
99    /// Upload texture to GPU, overwriting previous upload if any.
100    pub fn upload_texture(&mut self, model: &MjModel, texid: u32) {
101        unsafe { mjr_uploadTexture(model.ffi(), self.ffi_mut(), texid as i32); }
102    }
103
104    /// Make the context's buffer current again.
105    pub fn restore_buffer(&mut self) {
106        unsafe { mjr_restoreBuffer(self.ffi_mut()); }
107    }
108
109    pub fn mjr_set_buffer(&mut self, framebuffer: i32) {
110        unsafe { mjr_setBuffer(framebuffer, self.ffi_mut()); }
111    }
112
113    /// Read pixels from current OpenGL framebuffer to client buffer.
114    /// The ``rgb`` array is of size [width * height * 3], while ``depth`` is of size [width * height].
115    pub fn read_pixels(&self, rgb: Option<&mut [u8]>, depth: Option<&mut [f32]>, viewport: &MjrRectangle) {
116        unsafe {
117            mjr_readPixels(
118                rgb.map_or(ptr::null_mut(), |x| x.as_mut_ptr()),
119                depth.map_or(ptr::null_mut(), |x| x.as_mut_ptr()),
120                viewport.clone(), self.ffi()
121            )
122        }
123    }
124
125    /// Set Aux buffer for custom OpenGL rendering (call restoreBuffer when done).
126    pub fn set_aux(&mut self, index: usize) {
127        unsafe { mjr_setAux(index as i32, self.ffi_mut()); }
128    }
129
130    /// Draws a text overlay.
131    pub fn overlay(&mut self, font: MjtFont, gridpos: MjtGridPos, viewport: MjrRectangle, overlay: &str, overlay2: Option<&str>) {
132        let c_overlay = CString::new(overlay).unwrap();
133        let c_overlay2 = overlay2.map(|x| CString::new(x).unwrap());
134
135        unsafe { mjr_overlay(
136            font as i32, gridpos as i32, viewport,
137            c_overlay.as_ptr(),
138            c_overlay2.as_ref().map_or(std::ptr::null(), |x| x.as_ptr()),
139            self.ffi()
140        ); }
141    }
142
143    pub fn ffi(&self) -> &mjrContext {
144        &self.ffi
145    }
146
147    pub unsafe fn ffi_mut(&mut self) -> &mut mjrContext {
148        &mut self.ffi
149    }
150}
151
152impl Drop for MjrContext {
153    fn drop(&mut self) {
154        unsafe {
155            mjr_freeContext(&mut self.ffi);
156        }
157    }
158}
159