diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index a610a960..623e73ed 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -1653,18 +1653,9 @@ The texture data can be loaded from files or can be generated by the compiler as different texture types require different parameters, only a subset of the attributes below are used for any given texture. Provisions are provided for loading cube and skybox textures from individual image files. -Three file formats are supported for loading textures: PNG, KTX, and a custom MuJoCo texture format. The -loader will use the extension of the file name to determine which format to use, defaulting to the custom format if -the extension is not recognized. Alternatively, the content_type attribute can be used to specify the format -explicitly. Only ``image/png``, ``image/ktx``, or ``image/vnd.mujoco.texture`` are supported. - -The custom MuJoCo format is assumed to be a binary file containing the following data: - -.. code:: Text - - (int32) width - (int32) height - (byte) rgb_data[3*width*height] +Two file formats are supported for loading textures: PNG and KTX. The loader will use the extension of the file name to +determine which format to use. Alternatively, the content_type attribute can be used to specify the format explicitly. +Only ``image/png`` and ``image/ktx`` are supported. .. _asset-texture-name: @@ -1687,7 +1678,7 @@ The custom MuJoCo format is assumed to be a binary file containing the following corresponding texture color. The six square images defining the cube can be the same or different; if they are the same, only one copy is stored in mjModel. There are four mechanisms for specifying the texture data: - #. Single file (PNG or custom) specified with the file attribute, containing a square image which is repeated on each + #. Single file (PNG or KTX) specified with the file attribute, containing a square image which is repeated on each side of the cube. This is the most common approach. If for example the goal is to create the appearance of wood, repeating the same image on all sides is sufficient. #. Single file containing a composite image from which the six squares are extracted by the compiler. The layout of @@ -1722,8 +1713,7 @@ The custom MuJoCo format is assumed to be a binary file containing the following :at:`content_type`: :at-val:`string, optional` If the file attribute is specified, then this sets the `Media Type `_ (formerly known as MIME types) of the - file to be loaded. Any filename extensions will be ignored. Currently ``image/png``, ``image/ktx``, and - ``image/vnd.mujoco.texture`` are supported. + file to be loaded. Any filename extensions will be ignored. Currently ``image/png`` and ``image/ktx`` are supported. .. _asset-texture-file: diff --git a/doc/changelog.rst b/doc/changelog.rst index 62dc26cf..825b409f 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -14,6 +14,13 @@ General and gated by tests, as are the schema's enum keywords and declared defaults against the C headers and default-constructors. +.. admonition:: Breaking API changes + :class: attention + + - Removed the custom binary texture format (``image/vnd.mujoco.texture``) and the automatic fallback to custom + textures when loading files with unrecognized extensions. Textures can now only be loaded from PNG (``image/png``) + and KTX (``image/ktx``) files. + Actuation ^^^^^^^^^ - Added the :ref:`pid` actuator: a PID controller with real position and velocity setpoint inputs, diff --git a/doc/overview.rst b/doc/overview.rst index b3ab291e..245766bc 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -425,7 +425,7 @@ the other objects in the simulation, so the number of contacts will be small for Texture ^^^^^^^ -Textures can be loaded from PNG files or synthesized by the compiler based on user-defined procedural parameters. +Textures can be loaded from PNG or KTX files or synthesized by the compiler based on user-defined procedural parameters. There is also the option to leave the texture empty at model creation time and change it later at runtime -- so as to render video in a MuJoCo simulation, or create other dynamic effects. The visualizer supports two types of texture mapping: 2D and cube. 2D mapping is useful for planes and height fields. Cube mapping is useful for "shrink-wrapping" diff --git a/src/user/user_objects.cc b/src/user/user_objects.cc index 5bc0d065..68f8075c 100644 --- a/src/user/user_objects.cc +++ b/src/user/user_objects.cc @@ -5293,43 +5293,6 @@ void mjCTexture::LoadKTX(mjResource* resource, std::vector& image, } // load custom file -void mjCTexture::LoadCustom(mjResource* resource, std::vector& image, - unsigned int& w, unsigned int& h, bool& is_srgb) { - const void* buffer = 0; - int buffer_sz = mju_readResource(resource, &buffer); - - // still not found - if (buffer_sz < 0) { - throw mjCError(this, "could not read texture file '%s'", resource->name); - } else if (!buffer_sz) { - throw mjCError(this, "texture file is empty: '%s'", resource->name); - } - - - // read dimensions - int* pint = (int*)buffer; - w = pint[0]; - h = pint[1]; - - // assume linear color space - is_srgb = false; - - // check dimensions - if (w < 1 || h < 1) { - throw mjCError(this, "Non-PNG texture, assuming custom binary file format,\n" - "non-positive texture dimensions in file '%s'", resource->name); - } - - // check buffer size - if (buffer_sz != 2*sizeof(int) + w*h*3*sizeof(char)) { - throw mjCError(this, "Non-PNG texture, assuming custom binary file format,\n" - "unexpected file size in file '%s'", resource->name); - } - - // allocate and copy - image.resize(w*h*3); - memcpy(image.data(), (void*)(pint+2), w*h*3*sizeof(char)); -} void mjCTexture::FlipIfNeeded(std::vector& image, unsigned int w, unsigned int h) { @@ -5398,12 +5361,7 @@ void mjCTexture::LoadFlip(std::string filename, const mjVFS* vfs, std::string asset_type = GetAssetContentType(filename, content_type_); - // fallback to custom - if (asset_type.empty()) { - asset_type = "image/vnd.mujoco.texture"; - } - - if (asset_type != "image/png" && asset_type != "image/ktx" && asset_type != "image/vnd.mujoco.texture") { + if (asset_type != "image/png" && asset_type != "image/ktx") { throw mjCError(this, "unsupported content type: '%s'", asset_type.c_str()); } @@ -5423,8 +5381,6 @@ void mjCTexture::LoadFlip(std::string filename, const mjVFS* vfs, throw mjCError(this, "cannot flip KTX textures"); } LoadKTX(resource, image, w, h, is_srgb); - } else { - LoadCustom(resource, image, w, h, is_srgb); } } catch(mjCError err) { mju_closeResource(resource); diff --git a/src/user/user_objects.h b/src/user/user_objects.h index b257000a..f2403e36 100644 --- a/src/user/user_objects.h +++ b/src/user/user_objects.h @@ -1494,8 +1494,6 @@ class mjCTexture : public mjCTexture_, private mjsTexture { unsigned int& w, unsigned int& h, bool& is_srgb); void LoadKTX(mjResource* resource, std::vector& image, unsigned int& w, unsigned int& h, bool& is_srgb); - void LoadCustom(mjResource* resource, std::vector& image, - unsigned int& w, unsigned int& h, bool& is_srgb); bool clear_data_; // if true, data_ is empty and should be filled by Compile }; diff --git a/test/user/user_objects_test.cc b/test/user/user_objects_test.cc index fda09851..85784724 100644 --- a/test/user/user_objects_test.cc +++ b/test/user/user_objects_test.cc @@ -126,34 +126,6 @@ TEST_F(VfsTest, TexturePngWithVFS) { mj_deleteVFS(vfs.get()); } -TEST_F(VfsTest, TextureCustomWithVFS) { - static constexpr char xml[] = R"( - - - - - - - - - - - )"; - - char error[1024]; - size_t error_sz = 1024; - - // load VFS on the heap - auto vfs = std::make_unique(); - mj_defaultVFS(vfs.get()); - - // should fallback to OS filesystem - MjModelPtr model = LoadModelFromString(xml, error, error_sz, vfs.get()); - EXPECT_THAT(model.get(), IsNull()); - EXPECT_THAT(error, HasSubstr("Error opening file")); - mj_deleteVFS(vfs.get()); -} - // ------------------------ test content_type attribute ------------------------ using ContentTypeTest = MujocoTest; @@ -270,35 +242,6 @@ TEST_F(ContentTypeTest, TexturePngWithContentType) { mj_deleteVFS(vfs.get()); } -TEST_F(ContentTypeTest, TextureCustomWithContentType) { - static constexpr char xml[] = R"( - - - - - - - - - - - )"; - - char error[1024]; - size_t error_sz = 1024; - - // load VFS on the heap - auto vfs = std::make_unique(); - mj_defaultVFS(vfs.get()); - - // should try loading the file - MjModelPtr model = LoadModelFromString(xml, error, error_sz, vfs.get()); - EXPECT_THAT(model.get(), IsNull()); - EXPECT_THAT(error, HasSubstr("Error opening file")); - mj_deleteVFS(vfs.get()); -} - TEST_F(ContentTypeTest, TextureWithContentTypeError) { static constexpr char xml[] = R"(