Commit: b599820418fbfa1cbec88572ed5ff8a6dbce9e13 Author: Aras Pranckevicius Date: Thu Jan 12 22:47:39 2023 +0200 Branches: master https://developer.blender.org/rBb599820418fbfa1cbec88572ed5ff8a6dbce9e13
OBJ: add split by objects/groups import options (T103839) The new C++ OBJ importer was missing "split by objects" / "split by groups" import settings of the older Python importer. Implements T103839. Added test coverage for all 4 possible combinations of these two options. =================================================================== M source/blender/editors/io/io_obj.c M source/blender/io/wavefront_obj/IO_wavefront_obj.h M source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc M source/blender/io/wavefront_obj/importer/obj_import_mesh.cc M source/blender/io/wavefront_obj/tests/obj_importer_tests.cc =================================================================== diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c index ce121203972..e1dba4ee954 100644 --- a/source/blender/editors/io/io_obj.c +++ b/source/blender/editors/io/io_obj.c @@ -410,6 +410,8 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op) import_params.clamp_size = RNA_float_get(op->ptr, "clamp_size"); import_params.forward_axis = RNA_enum_get(op->ptr, "forward_axis"); import_params.up_axis = RNA_enum_get(op->ptr, "up_axis"); + import_params.use_split_objects = RNA_boolean_get(op->ptr, "use_split_objects"); + import_params.use_split_groups = RNA_boolean_get(op->ptr, "use_split_groups"); import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups"); import_params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes"); import_params.relative_paths = ((U.flag & USER_RELPATHS) != 0); @@ -472,6 +474,8 @@ static void ui_obj_import_settings(uiLayout *layout, PointerRNA *imfptr) box = uiLayoutBox(layout); uiItemL(box, IFACE_("Options"), ICON_EXPORT); col = uiLayoutColumn(box, false); + uiItemR(col, imfptr, "use_split_objects", 0, NULL, ICON_NONE); + uiItemR(col, imfptr, "use_split_groups", 0, NULL, ICON_NONE); uiItemR(col, imfptr, "import_vertex_groups", 0, NULL, ICON_NONE); uiItemR(col, imfptr, "validate_meshes", 0, NULL, ICON_NONE); } @@ -531,6 +535,16 @@ void WM_OT_obj_import(struct wmOperatorType *ot) RNA_def_property_update_runtime(prop, (void *)forward_axis_update); prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", ""); RNA_def_property_update_runtime(prop, (void *)up_axis_update); + RNA_def_boolean(ot->srna, + "use_split_objects", + true, + "Split By Object", + "Import each OBJ 'o' as a separate object"); + RNA_def_boolean(ot->srna, + "use_split_groups", + false, + "Split By Group", + "Import each OBJ 'g' as a separate object"); RNA_def_boolean(ot->srna, "import_vertex_groups", false, diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.h b/source/blender/io/wavefront_obj/IO_wavefront_obj.h index cf6464eeb37..2c039958bee 100644 --- a/source/blender/io/wavefront_obj/IO_wavefront_obj.h +++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.h @@ -68,6 +68,8 @@ struct OBJImportParams { float global_scale; eIOAxis forward_axis; eIOAxis up_axis; + bool use_split_objects; + bool use_split_groups; bool import_vertex_groups; bool validate_meshes; bool relative_paths; 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 1a3a333d957..b90a0c99424 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 @@ -363,6 +363,24 @@ static void geom_update_smooth_group(const char *p, const char *end, bool &r_sta r_state_shaded_smooth = smooth != 0; } +static void geom_new_object(const char *p, + const char *end, + bool &r_state_shaded_smooth, + std::string &r_state_group_name, + int &r_state_material_index, + Geometry *&r_curr_geom, + Vector<std::unique_ptr<Geometry>> &r_all_geometries) +{ + r_state_shaded_smooth = false; + r_state_group_name = ""; + /* Reset object-local material index that's used in face infos. + * NOTE: do not reset the material name; that has to carry over + * into the next object if needed. */ + r_state_material_index = -1; + r_curr_geom = create_geometry( + r_curr_geom, GEOM_MESH, StringRef(p, end).trim(), r_all_geometries); +} + OBJParser::OBJParser(const OBJImportParams &import_params, size_t read_buffer_size = 64 * 1024) : import_params_(import_params), read_buffer_size_(read_buffer_size) { @@ -534,22 +552,34 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries, } /* Objects. */ else if (parse_keyword(p, end, "o")) { - state_shaded_smooth = false; - state_group_name = ""; - /* Reset object-local material index that's used in face infos. - * NOTE: do not reset the material name; that has to carry over - * into the next object if needed. */ - state_material_index = -1; - curr_geom = create_geometry( - curr_geom, GEOM_MESH, StringRef(p, end).trim(), r_all_geometries); + if (import_params_.use_split_objects) { + geom_new_object(p, + end, + state_shaded_smooth, + state_group_name, + state_material_index, + curr_geom, + r_all_geometries); + } } /* Groups. */ else if (parse_keyword(p, end, "g")) { - geom_update_group(StringRef(p, end).trim(), state_group_name); - int new_index = curr_geom->group_indices_.size(); - state_group_index = curr_geom->group_indices_.lookup_or_add(state_group_name, new_index); - if (new_index == state_group_index) { - curr_geom->group_order_.append(state_group_name); + if (import_params_.use_split_groups) { + geom_new_object(p, + end, + state_shaded_smooth, + state_group_name, + state_material_index, + curr_geom, + r_all_geometries); + } + else { + geom_update_group(StringRef(p, end).trim(), state_group_name); + int new_index = curr_geom->group_indices_.size(); + state_group_index = curr_geom->group_indices_.lookup_or_add(state_group_name, new_index); + if (new_index == state_group_index) { + curr_geom->group_order_.append(state_group_name); + } } } /* Smoothing groups. */ diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index 6323b5ba1fc..794d307730c 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -53,7 +53,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain, obj->data = BKE_object_obdata_add_from_type(bmain, OB_MESH, ob_name.c_str()); create_vertices(mesh); - create_polys_loops(mesh, import_params.import_vertex_groups); + create_polys_loops(mesh, import_params.import_vertex_groups && !import_params.use_split_groups); create_edges(mesh); create_uv_verts(mesh); create_normals(mesh); @@ -222,8 +222,11 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) continue; } const int group_index = curr_face.vertex_group_index; - MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[mloop.v], group_index); - dw->weight = 1.0f; + /* Note: face might not belong to any group */ + if (group_index >= 0 || 1) { + MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[mloop.v], group_index); + dw->weight = 1.0f; + } } } 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 5f5587577a1..f15687e7bef 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -48,6 +48,19 @@ struct Expectation { class obj_importer_test : public BlendfileLoadingBaseTest { public: + obj_importer_test() + { + params.global_scale = 1.0f; + params.clamp_size = 0; + params.forward_axis = IO_AXIS_NEGATIVE_Z; + params.up_axis = IO_AXIS_Y; + params.validate_meshes = true; + params.use_split_objects = true; + params.use_split_groups = false; + params.import_vertex_groups = false; + params.relative_paths = true; + params.clear_selection = true; + } void import_and_check(const char *path, const Expectation *expect, size_t expect_count, @@ -59,16 +72,6 @@ class obj_importer_test : public BlendfileLoadingBaseTest { return; } - OBJImportParams params; - params.global_scale = 1.0f; - params.clamp_size = 0; - params.forward_axis = IO_AXIS_NEGATIVE_Z; - params.up_axis = IO_AXIS_Y; - params.validate_meshes = true; - params.import_vertex_groups = false; - params.relative_paths = true; - params.clear_selection = true; - std::string obj_path = blender::tests::flags_test_asset_dir() + "/io_tests/obj/" + path; strncpy(params.filepath, obj_path.c_str(), FILE_MAX - 1); const size_t read_buffer_size = 650; @@ -81,6 +84,32 @@ class obj_importer_test : public BlendfileLoadingBaseTest { deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI; + + constexpr bool print_result_scene = false; + if (print_result_scene) { + printf("Result was:\n"); + DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) { + printf(" {\"%s\", ", object->id.name); + if (object->type == OB_MESH) { + Mesh *mesh = BKE_object_get_evaluated_mesh(object); + const Span<float3> positions = mesh->vert_positions(); + printf("OB_MESH, %i, %i, %i, %i, float3(%g, %g, %g), float3(%g, %g, %g)", + mesh->totvert, + mesh->totedge, + mesh->totpoly, + mesh->totloop, + positions.first().x, + positions.first().y, + positions.first().z, + positions.last().x, + positions.last().y, + positions.last().z); + } + printf("},\ @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs