MaterialX
MaterialX copied to clipboard
Default float formatting causes programmatically generated documents to be invalid
When using the C++ API with default settings, very small or large float values (f.i. from an external data source) can cause a programmatically generated document to be invalid.
Following test case demonstrates the issue:
in MaterialXTest/MaterialXFormat/XmlIo.cpp:
TEST_CASE("Float value representation", "[xmlio]")
{
float floatCloseToZero = std::nextafter(0.0f, 1.0f);
auto floatString = mx::Value::createValue(floatCloseToZero)->getValueString();
mx::DocumentPtr doc = mx::createDocument();
auto node = doc->addNode("constant", mx::EMPTY_STRING, "float");
auto input = node->addInput("value", "float");
input->setValueString(floatString);
std::string errMsg;
bool validationResult = doc->validate(&errMsg);
if (!errMsg.empty())
{
fprintf(stderr, "%s\n", errMsg.c_str());
}
REQUIRE(validationResult);
}
The problem is that the <iostream> API is used to serialize the float to a string (Value.cpp:95), where the default format mode emits a scientific notation (1.4013e-45
in this case), which is not valid MaterialX float syntax. The behaviour can be 'fixed' by setting the float format mode:
mx::ScopedFloatFormatting fmt(mx::Value::FloatFormatFixed);
However, this is not the default behaviour and the need for setting a specific float format mode only becomes apparent after running into the problem described above.