Add mjz support to studio.
PiperOrigin-RevId: 861627355 Change-Id: Iafd291965ca78d03fdc1efe0e40dabcd4f2dacc4
This commit is contained in:
committed by
Copybara-Service
parent
32a4412e2b
commit
fe16255602
@@ -41,6 +41,7 @@
|
||||
#include "experimental/platform/renderer.h"
|
||||
#include "experimental/platform/step_control.h"
|
||||
#include "experimental/platform/window.h"
|
||||
#include "user/user_resource.h"
|
||||
|
||||
namespace mujoco::studio {
|
||||
|
||||
@@ -202,6 +203,22 @@ void App::LoadModelFromFile(const std::string& filepath) {
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
struct BufferProvider : public mjpResourceProvider {
|
||||
BufferProvider(std::span<const std::byte> buffer) : buffer(buffer) {
|
||||
mjp_defaultResourceProvider(this);
|
||||
open = [](mjResource* resource) {
|
||||
return 1;
|
||||
};
|
||||
read = [](mjResource* resource, const void** buffer) {
|
||||
BufferProvider* self = (BufferProvider*)resource->provider;
|
||||
*buffer = self->buffer.data();
|
||||
return static_cast<int>(self->buffer.size());
|
||||
};
|
||||
close = [](mjResource* resource) {};
|
||||
}
|
||||
std::span<const std::byte> buffer;
|
||||
};
|
||||
|
||||
void App::LoadModelFromBuffer(std::span<const std::byte> buffer,
|
||||
std::string_view content_type,
|
||||
std::string_view filename) {
|
||||
@@ -217,6 +234,14 @@ void App::LoadModelFromBuffer(std::span<const std::byte> buffer,
|
||||
spec = mj_parseXMLString(ptr, nullptr, err, sizeof(err));
|
||||
} else if (content_type == "application/mjb") {
|
||||
model = mj_loadModelBuffer(buffer.data(), buffer.size());
|
||||
} else if (content_type == "application/zip") {
|
||||
BufferProvider provider(buffer);
|
||||
mjResource resource;
|
||||
memset(&resource, 0, sizeof(mjResource));
|
||||
resource.vfs = &vfs;
|
||||
resource.provider = &provider;
|
||||
resource.name = (char*)filename.data();
|
||||
spec = mju_decodeResource(&resource, content_type.data(), &vfs);
|
||||
} else {
|
||||
SetLoadError(
|
||||
"Unknown content type; expected text/xml or application/mjb");
|
||||
|
||||
@@ -45,11 +45,13 @@ class App {
|
||||
void InitEmptyModel();
|
||||
|
||||
// Loads an mjModel from the given file. This extension should be one of:
|
||||
// .xml or .mjb.
|
||||
// .xml, .mjb, or .mjz.
|
||||
void LoadModelFromFile(const std::string& filepath);
|
||||
|
||||
// Loads an mjModel from the given memory buffer. The content_type should be
|
||||
// one of: "text/xml" or "application/mjb".
|
||||
// one of: "text/xml", "application/mjb", or "application/mjz". For zip files,
|
||||
// a name is required in order to uniquely identify the model within the
|
||||
// archive.
|
||||
void LoadModelFromBuffer(std::span<const std::byte> buffer,
|
||||
std::string_view content_type,
|
||||
std::string_view name);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<body style="margin: 0; overflow: hidden">
|
||||
<div style="position: absolute; top: 3px; right: 3px; z-index: 1;">
|
||||
<button id="uploadButton">Upload Model</button>
|
||||
<input type="file" id="fileInput" accept=".xml,.mjb" style="display: none;">
|
||||
<input type="file" id="fileInput" accept=".xml,.mjb,.mjz,.zip" style="display: none;">
|
||||
</div>
|
||||
<canvas
|
||||
class="emscripten"
|
||||
|
||||
@@ -104,6 +104,10 @@ void LoadFile(const std::string& filename, const std::string& data) {
|
||||
std::string content_type;
|
||||
if (filename.ends_with(".mjb")) {
|
||||
content_type = "application/mjb";
|
||||
} else if (filename.ends_with(".mjz")) {
|
||||
content_type = "application/zip";
|
||||
} else if (filename.ends_with(".zip")) {
|
||||
content_type = "application/zip";
|
||||
} else if (filename.ends_with(".xml")) {
|
||||
content_type = "text/xml";
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user