Add an "offscreen" mode that allows users to render studio to a texture
then uses SDL to blit the texture into the window. PiperOrigin-RevId: 861697047 Change-Id: Ib949b4ade0c79d867ba74ce013bc2b6fa2571f56
This commit is contained in:
committed by
Copybara-Service
parent
dce2ed00ea
commit
669e9b7484
@@ -46,17 +46,16 @@
|
||||
|
||||
namespace mujoco::studio {
|
||||
|
||||
static constexpr platform::Window::Config kWindowConfig = {
|
||||
static constexpr platform::Window::RenderConfig kRenderConfig =
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
.render_config = platform::Window::RenderConfig::kFilamentWebGL,
|
||||
platform::Window::RenderConfig::kFilamentWebGL;
|
||||
#elif defined(USE_FILAMENT_VULKAN)
|
||||
.render_config = platform::Window::RenderConfig::kFilamentVulkan,
|
||||
platform::Window::RenderConfig::kFilamentVulkan;
|
||||
#elif defined(USE_FILAMENT_OPENGL)
|
||||
.render_config = platform::Window::RenderConfig::kFilamentOpenGL,
|
||||
platform::Window::RenderConfig::kFilamentOpenGL;
|
||||
#elif defined(USE_CLASSIC_OPENGL)
|
||||
.render_config = platform::Window::RenderConfig::kClassicOpenGL,
|
||||
platform::Window::RenderConfig::kClassicOpenGL;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void ToggleFlag(mjtByte& flag) { flag = flag ? 0 : 1; }
|
||||
|
||||
@@ -113,10 +112,13 @@ static constexpr std::array<const char*, 31> kPercentRealTime = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
App::App(int width, int height, std::string ini_path)
|
||||
: ini_path_(std::move(ini_path)) {
|
||||
window_ = std::make_unique<platform::Window>("MuJoCo Studio", width, height,
|
||||
kWindowConfig);
|
||||
App::App(Config config)
|
||||
: ini_path_(std::move(config.ini_path)) {
|
||||
platform::Window::Config window_config;
|
||||
window_config.render_config = kRenderConfig;
|
||||
window_config.offscreen_mode = config.offscreen_mode;
|
||||
window_ = std::make_unique<platform::Window>("MuJoCo Studio", config.width,
|
||||
config.height, window_config);
|
||||
renderer_ =
|
||||
std::make_unique<platform::Renderer>(window_->GetNativeWindowHandle());
|
||||
|
||||
@@ -428,11 +430,16 @@ void App::Render() {
|
||||
const float height = window_->GetHeight();
|
||||
const float scale = window_->GetScale();
|
||||
|
||||
if (window_->IsOffscreenMode()) {
|
||||
pixels_.resize(width * height * 3);
|
||||
} else {
|
||||
pixels_.clear();
|
||||
}
|
||||
renderer_->Render(model_, data_, &perturb_, &camera_, &vis_options_,
|
||||
width * scale, height * scale);
|
||||
width * scale, height * scale, pixels_);
|
||||
|
||||
window_->EndFrame();
|
||||
window_->Present();
|
||||
window_->Present(pixels_);
|
||||
|
||||
if (data_) {
|
||||
for (int i = 0; i < mjNTIMER; i++) {
|
||||
|
||||
@@ -39,7 +39,22 @@ namespace mujoco::studio {
|
||||
// Owns, updates, and renders a MuJoCo simulation.
|
||||
class App {
|
||||
public:
|
||||
App(int width, int height, std::string ini_path);
|
||||
// Configuration/initialization options for the application.
|
||||
struct Config {
|
||||
// The original width and height of the window.
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
// The path to the ini file containing the user settings.
|
||||
std::string ini_path;
|
||||
|
||||
// By default, we render directly to the window surface. However, in some
|
||||
// cases, we may want to render to an (offscreen) texture and blit the
|
||||
// texture to the window surface.
|
||||
bool offscreen_mode = false;
|
||||
};
|
||||
|
||||
explicit App(Config config);
|
||||
|
||||
// Loads an empty mjModel.
|
||||
void InitEmptyModel();
|
||||
@@ -211,6 +226,7 @@ class App {
|
||||
mjSpec* spec_ = nullptr;
|
||||
mjModel* model_ = nullptr;
|
||||
mjData* data_ = nullptr;
|
||||
std::vector<std::byte> pixels_;
|
||||
|
||||
mjvCamera camera_;
|
||||
mjvPerturb perturb_;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
ABSL_FLAG(int, window_width, 1400, "Window width");
|
||||
ABSL_FLAG(int, window_height, 720, "Window height");
|
||||
ABSL_FLAG(std::string, model_file, "", "MuJoCo model file.");
|
||||
ABSL_FLAG(bool, offscreen_mode, false, "Offscreen mode");
|
||||
|
||||
std::string Resolve(std::string_view path) {
|
||||
std::string_view subpath = path.substr(path.find(':') + 1);
|
||||
@@ -100,7 +101,13 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
const int width = absl::GetFlag(FLAGS_window_width);
|
||||
const int height = absl::GetFlag(FLAGS_window_height);
|
||||
mujoco::studio::App app(width, height, ini_path);
|
||||
const bool offscreen_mode = absl::GetFlag(FLAGS_offscreen_mode);
|
||||
mujoco::studio::App app({
|
||||
.width = width,
|
||||
.height = height,
|
||||
.ini_path = ini_path,
|
||||
.offscreen_mode = offscreen_mode,
|
||||
});
|
||||
|
||||
// If the model file is not specified, try to load it from the first argument
|
||||
std::string model_file = absl::GetFlag(FLAGS_model_file);
|
||||
|
||||
@@ -91,7 +91,11 @@ void Init() {
|
||||
resource_provider.prefix = "filament";
|
||||
mjp_registerResourceProvider(&resource_provider);
|
||||
|
||||
g_app = new mujoco::studio::App(width, height, ini_path);
|
||||
g_app = new mujoco::studio::App({
|
||||
.width = width,
|
||||
.height = height,
|
||||
.ini_path = ini_path,
|
||||
});
|
||||
g_app->InitEmptyModel();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user