OBJ: more robust .mtl texture offset/scale parsing (T89421)
As pointed out in a comment on T89421, if a MTL file contained something like: `map_Ka -o 1 2.png` then it was parsed as having offset `1 2` and the texture filename just a `.png`. Make it so that mtl option numbers are parsed in a way where the number is only accepted only if it's followed by whitespace. Differential Revision: https://developer.blender.org/D15385
This commit is contained in:
parent
bddcb89cda
commit
50f9c1c09c
|
@ -626,15 +626,15 @@ static bool parse_texture_option(const char *&p,
|
|||
{
|
||||
p = drop_whitespace(p, end);
|
||||
if (parse_keyword(p, end, "-o")) {
|
||||
p = parse_floats(p, end, 0.0f, tex_map.translation, 3);
|
||||
p = parse_floats(p, end, 0.0f, tex_map.translation, 3, true);
|
||||
return true;
|
||||
}
|
||||
if (parse_keyword(p, end, "-s")) {
|
||||
p = parse_floats(p, end, 1.0f, tex_map.scale, 3);
|
||||
p = parse_floats(p, end, 1.0f, tex_map.scale, 3, true);
|
||||
return true;
|
||||
}
|
||||
if (parse_keyword(p, end, "-bm")) {
|
||||
p = parse_float(p, end, 1.0f, material->map_Bump_strength);
|
||||
p = parse_float(p, end, 1.0f, material->map_Bump_strength, true, true);
|
||||
return true;
|
||||
}
|
||||
if (parse_keyword(p, end, "-type")) {
|
||||
|
|
|
@ -62,8 +62,12 @@ static const char *drop_plus(const char *p, const char *end)
|
|||
return p;
|
||||
}
|
||||
|
||||
const char *parse_float(
|
||||
const char *p, const char *end, float fallback, float &dst, bool skip_space)
|
||||
const char *parse_float(const char *p,
|
||||
const char *end,
|
||||
float fallback,
|
||||
float &dst,
|
||||
bool skip_space,
|
||||
bool require_trailing_space)
|
||||
{
|
||||
if (skip_space) {
|
||||
p = drop_whitespace(p, end);
|
||||
|
@ -73,13 +77,23 @@ const char *parse_float(
|
|||
if (res.ec == std::errc::invalid_argument || res.ec == std::errc::result_out_of_range) {
|
||||
dst = fallback;
|
||||
}
|
||||
else if (require_trailing_space && res.ptr < end && !is_whitespace(*res.ptr)) {
|
||||
/* If there are trailing non-space characters, do not eat up the number. */
|
||||
dst = fallback;
|
||||
return p;
|
||||
}
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
const char *parse_floats(const char *p, const char *end, float fallback, float *dst, int count)
|
||||
const char *parse_floats(const char *p,
|
||||
const char *end,
|
||||
float fallback,
|
||||
float *dst,
|
||||
int count,
|
||||
bool require_trailing_space)
|
||||
{
|
||||
for (int i = 0; i < count; ++i) {
|
||||
p = parse_float(p, end, fallback, dst[i]);
|
||||
p = parse_float(p, end, fallback, dst[i], true, require_trailing_space);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -62,12 +62,17 @@ const char *parse_int(
|
|||
* The parsed result is stored in `dst`. The function skips
|
||||
* leading white-space unless `skip_space=false`. If the
|
||||
* number can't be parsed (invalid syntax, out of range),
|
||||
* `fallback` value is stored instead.
|
||||
* `fallback` value is stored instead. If `require_trailing_space`
|
||||
* is true, the character after the number has to be whitespace.
|
||||
*
|
||||
* Returns the start of remainder of the input string after parsing.
|
||||
*/
|
||||
const char *parse_float(
|
||||
const char *p, const char *end, float fallback, float &dst, bool skip_space = true);
|
||||
const char *parse_float(const char *p,
|
||||
const char *end,
|
||||
float fallback,
|
||||
float &dst,
|
||||
bool skip_space = true,
|
||||
bool require_trailing_space = false);
|
||||
|
||||
/**
|
||||
* Parse a number of white-space separated floats from an input string.
|
||||
|
@ -77,6 +82,11 @@ const char *parse_float(
|
|||
*
|
||||
* Returns the start of remainder of the input string after parsing.
|
||||
*/
|
||||
const char *parse_floats(const char *p, const char *end, float fallback, float *dst, int count);
|
||||
const char *parse_floats(const char *p,
|
||||
const char *end,
|
||||
float fallback,
|
||||
float *dst,
|
||||
int count,
|
||||
bool require_trailing_space = false);
|
||||
|
||||
} // namespace blender::io::obj
|
||||
|
|
|
@ -29,9 +29,14 @@ static StringRef parse_int(StringRef s, int fallback, int &dst, bool skip_space
|
|||
{
|
||||
return StringRef(parse_int(s.begin(), s.end(), fallback, dst, skip_space), s.end());
|
||||
}
|
||||
static StringRef parse_float(StringRef s, float fallback, float &dst, bool skip_space = true)
|
||||
static StringRef parse_float(StringRef s,
|
||||
float fallback,
|
||||
float &dst,
|
||||
bool skip_space = true,
|
||||
bool require_trailing_space = false)
|
||||
{
|
||||
return StringRef(parse_float(s.begin(), s.end(), fallback, dst, skip_space), s.end());
|
||||
return StringRef(
|
||||
parse_float(s.begin(), s.end(), fallback, dst, skip_space, require_trailing_space), s.end());
|
||||
}
|
||||
|
||||
TEST(obj_import_string_utils, drop_whitespace)
|
||||
|
@ -126,6 +131,9 @@ TEST(obj_import_string_utils, parse_float_invalid)
|
|||
/* Has leading white-space when we don't expect it */
|
||||
EXPECT_STRREF_EQ(" 1", parse_float(" 1", -4.0f, val, false));
|
||||
EXPECT_EQ(val, -4.0f);
|
||||
/* Has trailing non-number characters when we don't want them */
|
||||
EXPECT_STRREF_EQ("123.5.png", parse_float(" 123.5.png", -5.0f, val, true, true));
|
||||
EXPECT_EQ(val, -5.0f);
|
||||
}
|
||||
|
||||
} // namespace blender::io::obj
|
||||
|
|
|
@ -247,7 +247,7 @@ TEST_F(obj_mtl_parser_test, materials)
|
|||
ks.image_path = "ScaleOffsetBothTwovalues.png";
|
||||
tex_map_XX &ns = mat[5].tex_map_of_type(eMTLSyntaxElement::map_Ns);
|
||||
ns.scale = {0.5f, 1.0f, 1.0f};
|
||||
ns.image_path = "ScaleOneValue.png";
|
||||
ns.image_path = "1.Value.png";
|
||||
}
|
||||
|
||||
check("materials.mtl", mat, ARRAY_SIZE(mat));
|
||||
|
|
Loading…
Reference in New Issue