From 66def34e0ef39a26c7008624fe137f9f6f96e0a0 Mon Sep 17 00:00:00 2001 From: Saran Tunyasuvunakool Date: Mon, 24 Apr 2023 07:36:51 -0700 Subject: [PATCH] Fix broken OBJ and PNG loading when a VFS is provided to `mj_loadXML`. At present, if a VFS is used but an OBJ or PNG asset doesn't exist in the VFS, the model compilation will fail without trying to first locate the asset on disk. This breaks the Python bindings `MjModel.from_xml_string` almost entirely when OBJ assets are involved. Also modify error messages to disambiguate between different modes of asset loading failures. PiperOrigin-RevId: 526637686 Change-Id: Iba02cc94989083bc2835a3e67dfc78c0a21047e9 --- src/user/user_mesh.cc | 18 +++++++++--------- src/user/user_objects.cc | 26 ++++++++++++++++---------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/user/user_mesh.cc b/src/user/user_mesh.cc index a0abee9f..19029344 100644 --- a/src/user/user_mesh.cc +++ b/src/user/user_mesh.cc @@ -591,10 +591,10 @@ void mjCMesh::LoadOBJ(int default_provider) { mjResource* r = nullptr; // try reading from default provider - if((r = mju_openResource(filename.c_str(), default_provider)) == nullptr) { + if ((r = mju_openResource(filename.c_str(), default_provider)) == nullptr) { // try reading from filesystem - if (default_provider || (r = mju_openResource(filename.c_str(), 0)) == nullptr) { - throw mjCError(this, "could not parse OBJ file '%s'", filename.c_str()); + if (!default_provider || (r = mju_openResource(filename.c_str(), 0)) == nullptr) { + throw mjCError(this, "could not open OBJ file '%s'", filename.c_str()); } } @@ -603,7 +603,7 @@ void mjCMesh::LoadOBJ(int default_provider) { int buffer_sz = mju_readResource(r, &bytes); if (buffer_sz < 0) { mju_closeResource(r); - throw mjCError(this, "could not parse OBJ file '%s'", filename.c_str()); + throw mjCError(this, "could not read OBJ file '%s'", filename.c_str()); } // TODO(etom): support .mtl files? @@ -706,7 +706,7 @@ void mjCMesh::LoadSTL(int default_provider) { // still not found if (buffer_sz < 0) { mju_closeResource(r); - throw mjCError(this, "could not open STL file '%s'", filename.c_str()); + throw mjCError(this, "could not read STL file '%s'", filename.c_str()); } else if (!buffer_sz) { mju_closeResource(r); throw mjCError(this, "STL file '%s' is empty", filename.c_str()); @@ -792,7 +792,7 @@ void mjCMesh::LoadMSH(int default_provider) { if((r = mju_openResource(filename.c_str(), default_provider)) == nullptr) { // fall back to OS filesystem if(!default_provider || (r = mju_openResource(filename.c_str(), 0)) == nullptr) { - throw mjCError(this, "could not open STL file '%s'", filename.c_str()); + throw mjCError(this, "could not open MSH file '%s'", filename.c_str()); } } @@ -803,10 +803,10 @@ void mjCMesh::LoadMSH(int default_provider) { // still not found if (buffer_sz < 0) { mju_closeResource(r); - throw mjCError(this, "could not open STL file '%s'", filename.c_str()); + throw mjCError(this, "could not read MSH file '%s'", filename.c_str()); } else if (!buffer_sz) { mju_closeResource(r); - throw mjCError(this, "STL file '%s' is empty", filename.c_str()); + throw mjCError(this, "MSH file '%s' is empty", filename.c_str()); } // make sure header is present @@ -1741,7 +1741,7 @@ void mjCSkin::LoadSKN(int default_provider) { if (buffer_sz < 0) { mju_closeResource(r); - throw mjCError(this, "could not open SKN file '%s'", filename.c_str()); + throw mjCError(this, "could not read SKN file '%s'", filename.c_str()); } else if (!buffer_sz) { mju_closeResource(r); throw mjCError(this, "SKN file '%s' is empty", filename.c_str()); diff --git a/src/user/user_objects.cc b/src/user/user_objects.cc index d1bd7602..64f7dd5d 100644 --- a/src/user/user_objects.cc +++ b/src/user/user_objects.cc @@ -1983,7 +1983,7 @@ void mjCHField::LoadCustom(string filename, int default_provider) { const void* buffer = 0; mjResource* resource = nullptr; - if((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { + if ((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { // default to OS filesystem if (!default_provider || (resource = mju_openResource(filename.c_str(), 0)) == nullptr) { throw mjCError(this, "could not open hfield file '%s'", filename.c_str()); @@ -1994,7 +1994,7 @@ void mjCHField::LoadCustom(string filename, int default_provider) { // still not found if (!buffer || buffer_sz < 1) { - throw mjCError(this, "could not open hfield file '%s'", filename.c_str()); + throw mjCError(this, "could not read hfield file '%s'", filename.c_str()); } if (buffer_sz < 2*sizeof(int)) { @@ -2041,8 +2041,11 @@ void mjCHField::LoadPNG(string filename, int default_provider) { const void* inbuffer = 0; mjResource* resource = nullptr; - if((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { - throw mjCError(this, "could not open PNG file '%s'", filename.c_str()); + if ((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { + // try reading from filesystem + if (!default_provider || (resource = mju_openResource(filename.c_str(), 0)) == nullptr) { + throw mjCError(this, "could not open PNG file '%s' %d", filename.c_str(), default_provider); + } } int inbuffer_sz = mju_readResource(resource, &inbuffer); @@ -2050,7 +2053,7 @@ void mjCHField::LoadPNG(string filename, int default_provider) { // still not found if (!inbuffer || inbuffer_sz < 1) { mju_closeResource(resource); - throw mjCError(this, "could not open PNG file '%s'", filename.c_str()); + throw mjCError(this, "could not read PNG file '%s'", filename.c_str()); } // load PNG from file or memory @@ -2434,8 +2437,11 @@ void mjCTexture::LoadPNG(string filename, int default_provider, const void* inbuffer = 0; mjResource* resource = nullptr; - if((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { - throw mjCError(this, "could not open PNG file '%s'", filename.c_str()); + if ((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { + // try reading from filesystem + if (!default_provider || (resource = mju_openResource(filename.c_str(), 0)) == nullptr) { + throw mjCError(this, "could not open PNG file '%s' %d", filename.c_str(), default_provider); + } } int inbuffer_sz = mju_readResource(resource, &inbuffer); @@ -2443,7 +2449,7 @@ void mjCTexture::LoadPNG(string filename, int default_provider, // still not found if (!inbuffer || inbuffer_sz < 1) { mju_closeResource(resource); - throw mjCError(this, "could not open PNG file '%s'", filename.c_str()); + throw mjCError(this, "could not read PNG file '%s'", filename.c_str()); } // load PNG from file or memory @@ -2469,7 +2475,7 @@ void mjCTexture::LoadCustom(string filename, int default_provider, const void* buffer = 0; mjResource* resource = nullptr; - if((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { + if ((resource = mju_openResource(filename.c_str(), default_provider)) == nullptr) { // default to OS filesystem if (!default_provider || (resource = mju_openResource(filename.c_str(), 0)) == nullptr) { throw mjCError(this, "could not open texture file '%s'", filename.c_str()); @@ -2481,7 +2487,7 @@ void mjCTexture::LoadCustom(string filename, int default_provider, // still not found if (!buffer || buffer_sz < 0) { mju_closeResource(resource); - throw mjCError(this, "could not open texture file '%s'", filename.c_str()); + throw mjCError(this, "could not read texture file '%s'", filename.c_str()); } // read dimensions