During mj_parse, if mju_openResource fails pass a resource with only the filename to decoders.
This enables decoders to leverage their own file resolution systems. For example: USD can compose a stage (scene) from memory, via a file on disk, or via custom asset resolver. Passing it through to the decoder reduces the need for custom resource providers that wrap these other resolution systems. This will also enable a fun, but likely niche usecase where the decoder does procedural generation and does not have to be backed by a resource. See the tests for an example of this. PiperOrigin-RevId: 828939899 Change-Id: Ic319a685332d91198a4ae926867c834bf7f7f724
This commit is contained in:
committed by
Copybara-Service
parent
89fec8f7b2
commit
8051f40817
@@ -78,49 +78,44 @@ TEST_F(DecoderPluginTest, CanDecode) {
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
char error[1024];
|
||||
|
||||
// create VFS with the XML model and a dummy mesh
|
||||
mjVFS vfs;
|
||||
mj_defaultVFS(&vfs);
|
||||
mj_addBufferVFS(&vfs, "model.xml", xml, strlen(xml));
|
||||
mj_addBufferVFS(&vfs, "dummy.fakeformat", "0 1 2", strlen("0 1 2"));
|
||||
mj_addBufferVFS(&vfs, "dummy.alsoFakeFormat", "0 1 2", strlen("0 1 2"));
|
||||
|
||||
// Check referencing a resource via XML invokes the decoder.
|
||||
mjModel* model = mj_loadXML("model.xml", &vfs, error, sizeof(error));
|
||||
char error[1024];
|
||||
mjSpec* spec =
|
||||
mj_parseXMLString(xml, nullptr, error, sizeof(error));
|
||||
mjModel* model = mj_compile(spec, nullptr);
|
||||
ASSERT_THAT(model, testing::NotNull()) << error;
|
||||
EXPECT_EQ(model->nbody, 2); // world + included body
|
||||
EXPECT_EQ(model->ngeom, 1);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteSpec(spec);
|
||||
|
||||
// Check mj_parse with extension .fakeformat
|
||||
mjSpec* spec =
|
||||
mj_parse("dummy.fakeformat", nullptr, &vfs, error, sizeof(error));
|
||||
model = mj_compile(spec, &vfs);
|
||||
spec =
|
||||
mj_parse("dummy.fakeformat", nullptr, nullptr, error, sizeof(error));
|
||||
model = mj_compile(spec, nullptr);
|
||||
EXPECT_EQ(model->nbody, 2); // world + included body
|
||||
EXPECT_EQ(model->ngeom, 1);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteSpec(spec);
|
||||
|
||||
// Check mj_parse with extension .alsoFakeFormat
|
||||
spec = mj_parse("dummy.alsoFakeFormat", nullptr, &vfs, error, sizeof(error));
|
||||
model = mj_compile(spec, &vfs);
|
||||
spec =
|
||||
mj_parse("dummy.alsoFakeFormat", nullptr, nullptr, error, sizeof(error));
|
||||
model = mj_compile(spec, nullptr);
|
||||
EXPECT_EQ(model->nbody, 2); // world + included body
|
||||
EXPECT_EQ(model->ngeom, 1);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteSpec(spec);
|
||||
|
||||
// Check mj_parse with content_type
|
||||
spec = mj_parse("dummy.fakeformat", "model/fakeformat", &vfs, error,
|
||||
spec = mj_parse("dummy.fakeformat", "model/fakeformat", nullptr, error,
|
||||
sizeof(error));
|
||||
model = mj_compile(spec, &vfs);
|
||||
model = mj_compile(spec, nullptr);
|
||||
EXPECT_EQ(model->nbody, 2); // world + included body
|
||||
EXPECT_EQ(model->ngeom, 1);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteSpec(spec);
|
||||
|
||||
mj_deleteVFS(&vfs);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user