From 39150096d8bcf925b14c4304e660e19a6df76fa5 Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Mon, 13 May 2024 11:45:20 +0300 Subject: [PATCH] Fix #121720: OBJ does not import some curves properly If a curve was not using U parameter range of 0..1, the importer did not properly detect whether the "U endpoint" flag should be set on it. Fixed that, along with test coverage for the case. --- .../importer/obj_import_file_reader.cc | 5 ++- .../importer/obj_import_nurbs.cc | 9 ++++-- .../importer/obj_import_objects.hh | 1 + .../wavefront_obj/tests/obj_importer_tests.cc | 32 +++++++++++++++++++ tests/data | 2 +- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc index 650e9f37012..a59e2213793 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc @@ -358,9 +358,8 @@ static void geom_add_curve_vertex_indices(Geometry *geom, const char *end, const GlobalVertices &global_vertices) { - /* Curve lines always have "0.0" and "1.0", skip over them. */ - float dummy[2]; - p = parse_floats(p, end, 0, dummy, 2); + /* Parse curve parameter range. */ + p = parse_floats(p, end, 0, geom->nurbs_element_.range, 2); /* Parse indices. */ while (p < end) { int index; diff --git a/source/blender/io/wavefront_obj/importer/obj_import_nurbs.cc b/source/blender/io/wavefront_obj/importer/obj_import_nurbs.cc index 24ada0fbdaf..737bf3e09ff 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_nurbs.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_nurbs.cc @@ -78,16 +78,21 @@ void CurveFromGeometry::create_nurbs(Curve *curve) } BKE_nurb_knot_calc_u(nurb); + + /* Figure out whether curve should have U endpoint flag set: + * the parameters should have at least (degree+1) values on each end, + * and their values should match curve range. */ bool do_endpoints = false; int deg1 = nurbs_geometry.degree + 1; if (nurbs_geometry.parm.size() >= deg1 * 2) { do_endpoints = true; + const float2 range = nurbs_geometry.range; for (int i = 0; i < deg1; ++i) { - if (abs(nurbs_geometry.parm[i]) > 0.0001f) { + if (abs(nurbs_geometry.parm[i] - range.x) > 0.0001f) { do_endpoints = false; break; } - if (abs(nurbs_geometry.parm[nurbs_geometry.parm.size() - 1 - i] - 1.0f) > 0.0001f) { + if (abs(nurbs_geometry.parm[nurbs_geometry.parm.size() - 1 - i] - range.y) > 0.0001f) { do_endpoints = false; break; } diff --git a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh index 31a21d3cd58..0a40398b177 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh @@ -69,6 +69,7 @@ struct NurbsElement { */ std::string group_; int degree = 0; + float2 range{0.0f, 1.0f}; /** * Indices into the global list of vertex coordinates. Must be non-negative. */ diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index c37442edc03..c132c24ad84 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -316,6 +316,38 @@ TEST_F(OBJImportTest, import_nurbs_cyclic) import_and_check("nurbs_cyclic.obj", expect, std::size(expect), 0); } +TEST_F(OBJImportTest, import_nurbs_endpoint) +{ + Expectation expect[] = { + {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)}, + {"OBCurveEndpointRange01", + OB_CURVES_LEGACY, + 15, + 1, + 4, + 0, + float3(0.29f, 0, -0.11f), + float3(22.17f, 0, -5.31f)}, + {"OBCurveEndpointRangeNon01", + OB_CURVES_LEGACY, + 15, + 1, + 4, + 0, + float3(0.29f, 0, -0.11f), + float3(22.17f, 0, -5.31f)}, + {"OBCurveNoEndpointRange01", + OB_CURVES_LEGACY, + 15, + 0, + 4, + 0, + float3(0.29f, 0, -0.11f), + float3(22.17f, 0, -5.31f)}, + }; + import_and_check("nurbs_endpoint.obj", expect, std::size(expect), 0); +} + TEST_F(OBJImportTest, import_nurbs_manual) { Expectation expect[] = { diff --git a/tests/data b/tests/data index d8d9c4c5fbc..71e05fc367d 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit d8d9c4c5fbca4e11c72fc7247b50655b8c9c7914 +Subproject commit 71e05fc367d26218dede9a97f4a0577a3b72a8c8