用户界面#

MuJoCo 有一个原生的 UI 框架。它的用法在 simulate.cc 查看器中有所说明。它被设计成更新和渲染速度快,开发者和用户都易于使用,跨平台,并与原生的 MuJoCo 渲染器集成。为了实现这些设计目标,我们省略了其他 UI 框架中提供的许多特性和自定义选项,转而专注于效率和自动化。

设计概述#

原生 OpenGL 渲染

我们不使用任何辅助工具或库。相反,我们提供 C 代码,直接在 OpenGL 中渲染所有 UI 元素。我们支持多个 UI,每个 UI 都是一个虚拟矩形,其高度可以超过可见窗口。每个 UI 的元素都在辅助 OpenGL 缓冲区中进行离屏渲染,通过最小化的更新,仅在必要时进行更改。每次屏幕刷新时,我们将这些辅助缓冲区中的像素复制到窗口帧缓冲区,并在窗口小于 UI 时实现垂直滚动条。这个复制操作在 GPU 上完成,速度非常快。

平台抽象#

软件设计分为 3 层:与 MuJoCo 渲染器协同工作的 UI 元素的 OpenGL 渲染(完全跨平台);在 PlatformUIAdapter 类中定义为纯虚函数的窗口、键盘和鼠标访问抽象函数;以及在派生类 GlfwAdapter 中实现的这些函数。GLFW 本身是跨平台的。尽管如此,我们选择了这种分层设计,以将通用功能与平台特定功能分开。如果由于某种原因需要用另一个类似的框架替换 GLFW,只需重写 GlfwAdapter

主题和外观#

单个 UI 元素不允许自定义外观或布局。相反,我们使用主题来定义颜色和间距,并自动排列所有 UI 元素。提供了几种内置主题,用户可以设计自定义主题,但是整个 UI 的所有元素都使用同一个主题。外观是极简主义的:主要是带文本的彩色矩形。不支持位图和其他自定义装饰。UI 元素的类型包括复选框、单选按钮组、选择列表、滑块、文本编辑框、静态文本、按钮、分隔符。这些元素被分组到可以展开和折叠的部分中。

布局和矩形#

每个 UI 都是一个虚拟矩形,其宽度由主题决定,高度由部分、每个部分内的项目以及每个部分的展开/折叠状态决定。这些虚拟矩形的大小和辅助缓冲区在 UI 更新时自动处理。每个 UI 在屏幕上都有一个可见的矩形,此外还有其他矩形——用于 3D 渲染、2D 图形以及可能的自定义 OpenGL 渲染。所有这些可见矩形都保存在 (mjuiState 中) 并用于确定鼠标事件应该导向何处。矩形布局由用户提供的回调函数更新。

静态分配和创建#

我们不是分配和释放大量对应于 UI 元素的对象并将它们链接在一起,而是创建一个具有静态分配的单个 C 结构体 (类型 mjUI),支持最大数量的部分和元素;然后记录使用了多少。通过助手函数简化 UI 创建,其输入是一个 C 结构体 (类型 mjuiDef),它本质上是一个表格,每行描述一个 UI 元素(见下文)。这使得用非常少的 C 代码构建复杂的用户界面成为可能。也可以通过编程方式创建 UI,例如在 UI 中填充与 MuJoCo 模型关节对应的滑块。

最小化状态#

UI 的设计尽可能无状态,以简化开发。这有两个方面。首先,我们不是在 UI 元素中复制用户数据,而是存储指向用户数据的指针。例如,我们可以创建一个 UI 滑块并将其数据指针设置为 mjData* d->qpos+7。这个滑块将可视化并控制 MuJoCo 模型的 qpos 向量的第 7 个标量分量。因此,当仿真更新时,我们必须记住也要更新 UI。此外,当仿真正在更新时,我们必须禁用 UI 编辑。但优点是 UI 构建变得更容易,并且不会出现用户数据与 UI 不一致的危险。其次,UI 元素本身大多是无状态的。相反,我们跟踪一组最小化的全局状态,特别是鼠标和键盘状态、部分的展开/折叠状态、正在编辑的文本框的内容(如果有)。

自动启用和禁用#

虽然可以直接将每个 UI 项目设置为启用或禁用状态,但我们也提供自动化功能。每个 UI 项目可以分配一个整数类别。然后,一个 mjfItemEnable 回调函数根据一些程序特定条件确定每个类别是否应该启用或禁用。例如,可以更改 MuJoCo 模型关节值的滑块在仿真状态正在更新时应该被禁用。

主要 API#

点击以下链接查看主要 UI 数据结构和函数的详细 API 参考。

主要数据结构

  • mjUI: 整个 UI。

  • mjuiState: 全局 UI 状态。

  • mjuiDef: 用于构建 UI 的定义表中的一个条目。

主要函数