From 8f4c5c4b168103767383b2beef85805e7bd6f906 Mon Sep 17 00:00:00 2001 From: Tom Power Date: Wed, 12 Mar 2025 12:16:31 -0700 Subject: [PATCH] add support for non-rgb textures in xml_native_writer PiperOrigin-RevId: 736221430 Change-Id: I83c19e06f0f7be054a88c3e894807e7b90ee012a --- src/xml/xml_base.h | 1 + src/xml/xml_native_writer.cc | 22 ++++++++++++++++------ test/xml/testdata/hfield.png | Bin 0 -> 1117 bytes test/xml/testdata/hfield_png_nonrgb.xml | 17 +++++++++++++++++ test/xml/xml_native_writer_test.cc | 21 +++++++++++++++++++++ 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 test/xml/testdata/hfield.png create mode 100644 test/xml/testdata/hfield_png_nonrgb.xml diff --git a/src/xml/xml_base.h b/src/xml/xml_base.h index bf2c92d6..ba914229 100644 --- a/src/xml/xml_base.h +++ b/src/xml/xml_base.h @@ -60,6 +60,7 @@ extern const mjMap jac_map[]; extern const mjMap solver_map[]; extern const mjMap equality_map[]; extern const mjMap texture_map[]; +extern const mjMap texrole_map[]; extern const mjMap builtin_map[]; extern const mjMap mark_map[]; extern const mjMap dyn_map[]; diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc index 44646531..4643a925 100644 --- a/src/xml/xml_native_writer.cc +++ b/src/xml/xml_native_writer.cc @@ -323,6 +323,7 @@ void mjXWriter::OneMaterial(XMLElement* elem, const mjCMaterial* material, mjCDe } // defaults and regular + // check if we have non-rgb textures bool has_non_rgb = false; for (int i=1; itextures_[i].empty()) { @@ -330,14 +331,23 @@ void mjXWriter::OneMaterial(XMLElement* elem, const mjCMaterial* material, mjCDe has_non_rgb = true; } } - if (material->textures_[i] != def->Material().textures_[i]) { - WriteAttrTxt(elem, "texture", material->get_texture(i)); + } + + // if we have non-rgb textures, write them as layers + if (has_non_rgb) { + for (int i=1; itextures_[i].empty()) { + XMLElement * child_elem = InsertEnd(elem, "layer"); + WriteAttrTxt(child_elem, "texture", material->textures_[i]); + WriteAttrTxt(child_elem, "role", FindValue(texrole_map, 9, i)); + } + } + } else { + if (material->textures_[mjTEXROLE_RGB] != def->Material().textures_[mjTEXROLE_RGB]) { + WriteAttrTxt(elem, "texture", material->get_texture(mjTEXROLE_RGB)); } } - if (has_non_rgb) { - // // TODO elem = InsertEnd(section, "role"); - throw mjXError(0, "no support for non-RGB textures."); - } + WriteAttrKey(elem, "texuniform", bool_map, 2, material->texuniform, def->Material().texuniform); WriteAttr(elem, "texrepeat", 2, material->texrepeat, def->Material().texrepeat); WriteAttr(elem, "emission", 1, &material->emission, &def->Material().emission); diff --git a/test/xml/testdata/hfield.png b/test/xml/testdata/hfield.png new file mode 100644 index 0000000000000000000000000000000000000000..22fcde5eaed42e9281756aacfdede509ac4933d1 GIT binary patch literal 1117 zcmV-j1fu(iP)A|0D+qips-3?RqE0fIO-C63Mik{GT5Og|xp0|G0L7vN<38Ti>T zCo|^!>iHu${`%qqz(fEbLbc&#suc+Mv)9<-(%kh6nBa41ewxjGZo&;z;vkfPFk;LC z79@c}Zj3EoUd%;04QD@>g!s^a05anSjPj&XK!jsMh>0tgAe~I`&9mbWAG#c&7Y?d4 ze^YKAAMST#T?f&}9b*Opxv@ux$h#W%7V~bAifehvmundVJ@QX&h6oiCp0Jq!N^>_X zk%ss2p?;Bf5b2nVs3wg8B|sW6b?hN6WRh_UfRzSuVfu9tV60Uj`aITPh;VB5e*%7P zT-%UF$ymT5B%uIP7JyQ5MrTUXj#Y+Oh+zsifNK2!I^EygQ8sA-<@qnL=bN8?Ai#q? zE5|59U5GgUjf0=C`sOpce|Ue+a_(nSkWP)V=jF;aRO|bkf%#cGU7|E;Yj<=)#Y7lA zXP^z`jjBw8Vu4uYw_e$XM(dcfm7mloH%r*j2^9mGR6=grY@a~2-eNNyyxdeD@bf7d zeW!Z{)p`>NG3|`rNP&?CgMpoTo7qDaSi40j;5AS4zsr6%1p{1&S!eVSB2=w7R5cY} zvvtJm<&7N?)dZwdBf|N#Y`^Q3Ew)FaeT0NKplQZKU?LevrxGmJJpV1ZhKh^-2BG>u zMgMUZI;UrRU9AC~?zv)sfDyd}5E#^R1`14MfB-0l%9Sr74ZOxn#aRL1yXJ(k#)O!W zc25h~DZ-F}5ecAkdX9PnO@jbXoMELGcDvQr?@@#SV?hcrpXSsX?c1FKDnQiLxUd2g z*`ciSl_yIwda8ch#2W2GxyRjNUO(oElL3XkfDV-=6_gYw-=s{%Mw`-uI|4x6I8`~& za10BPIy7K2K*bk!wPyQR2upuSDZkwUJXY5>tyjCv4>eVa3wdjg$TGzA@6`6~`XvE0 z+lNAQJbFgILGNkzm#_n*C$3u2(|wF8;1@pASx3VM6^eq<9?}mug+lFwK=s?6=mmq| z=cXJQaGdKIK|f0YD + + + + + + + + + + + + + + + + diff --git a/test/xml/xml_native_writer_test.cc b/test/xml/xml_native_writer_test.cc index f1e7eb8a..4de0a7fd 100644 --- a/test/xml/xml_native_writer_test.cc +++ b/test/xml/xml_native_writer_test.cc @@ -46,6 +46,9 @@ using ::testing::FloatEq; using XMLWriterTest = PluginTest; +static const char* const kNonRgbTextureXMLPath = + "xml/testdata/hfield_png_nonrgb.xml"; + TEST_F(XMLWriterTest, EmptyModel) { static constexpr char xml[] = ""; mjModel* model = LoadModelFromString(xml); @@ -1326,6 +1329,24 @@ TEST_F(XMLWriterLocaleTest, IgnoresLocale) { EXPECT_EQ(std::string(formatted), "3,9375"); } +TEST_F(XMLWriterTest, NonRGBTextures) { + const std::string xml_path = GetTestDataFilePath(kNonRgbTextureXMLPath); + std::array error; + mjModel* model = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size()); + ASSERT_THAT(model, NotNull()) << error.data(); + + std::string saved_xml = SaveAndReadXml(model); + EXPECT_FALSE(saved_xml.empty()); + + // check that layers are written correctly + EXPECT_THAT(saved_xml, HasSubstr("")); + EXPECT_THAT(saved_xml, HasSubstr("")); + EXPECT_THAT(saved_xml, HasSubstr("")); + EXPECT_THAT(saved_xml, + HasSubstr("")); + + mj_deleteModel(model); +} // ------------------- test loading and saving multiple files ------------------ TEST_F(XMLWriterTest, WriteReadCompare) {