Remove custom mujoco.texture format.

PiperOrigin-RevId: 960257562
Change-Id: I318c84d82576d405f0a5d8510acd5bab5f08c9af
This commit is contained in:
Sam Haves
2026-08-06 06:13:17 -07:00
committed by Copybara-Service
parent 84950fa371
commit 6fe04aa8d3
6 changed files with 14 additions and 120 deletions
+5 -15
View File
@@ -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 <https://www.iana.org/assignments/media-types/media-types.xhtml>`_ (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:
+7
View File
@@ -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-pid>` actuator: a PID controller with real position and velocity setpoint inputs,
+1 -1
View File
@@ -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"
+1 -45
View File
@@ -5293,43 +5293,6 @@ void mjCTexture::LoadKTX(mjResource* resource, std::vector<std::byte>& image,
}
// load custom file
void mjCTexture::LoadCustom(mjResource* resource, std::vector<std::byte>& 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<std::byte>& 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);
-2
View File
@@ -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<std::byte>& image,
unsigned int& w, unsigned int& h, bool& is_srgb);
void LoadCustom(mjResource* resource, std::vector<std::byte>& image,
unsigned int& w, unsigned int& h, bool& is_srgb);
bool clear_data_; // if true, data_ is empty and should be filled by Compile
};
-57
View File
@@ -126,34 +126,6 @@ TEST_F(VfsTest, TexturePngWithVFS) {
mj_deleteVFS(vfs.get());
}
TEST_F(VfsTest, TextureCustomWithVFS) {
static constexpr char xml[] = R"(
<mujoco>
<asset>
<texture name="texture" file="unknown_file" type="2d"/>
<material name="material" texture="texture"/>
</asset>
<worldbody>
<geom type="plane" material="material" size="4 4 4"/>
</worldbody>
</mujoco>
)";
char error[1024];
size_t error_sz = 1024;
// load VFS on the heap
auto vfs = std::make_unique<mjVFS>();
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"(
<mujoco>
<asset>
<texture name="texture" content_type="image/vnd.mujoco.texture"
file="some_file" type="2d"/>
<material name="material" texture="texture"/>
</asset>
<worldbody>
<geom type="plane" material="material" size="4 4 4"/>
</worldbody>
</mujoco>
)";
char error[1024];
size_t error_sz = 1024;
// load VFS on the heap
auto vfs = std::make_unique<mjVFS>();
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"(
<mujoco>