Blender V4.3
obj_importer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <string>
10
11#include "BLI_map.hh"
12#include "BLI_set.hh"
13#include "BLI_sort.hh"
14#include "BLI_string.h"
15#include "BLI_string_ref.hh"
16
17#include "BKE_context.hh"
19#include "BKE_geometry_set.hh"
20#include "BKE_instances.hh"
21#include "BKE_layer.hh"
22
24
26
27#include "obj_export_mtl.hh"
29#include "obj_import_mesh.hh"
30#include "obj_import_nurbs.hh"
31#include "obj_import_objects.hh"
32#include "obj_importer.hh"
33
34namespace blender::io::obj {
35
37 Collection *target,
38 const std::string &geom_name,
39 const OBJImportParams &import_params)
40{
41 if (target == nullptr || import_params.collection_separator == 0) {
42 return target;
43 }
44 size_t subname_start = 0;
45 size_t sep_pos = geom_name.find(import_params.collection_separator);
46 if (sep_pos == std::string::npos) {
47 return target;
48 }
49 while (sep_pos != std::string::npos) {
50 /* Get current sub-name, find or create collection with that name. */
51 if (sep_pos > subname_start) {
52 std::string subname = geom_name.substr(subname_start, sep_pos - subname_start);
53 bool found = false;
54 LISTBASE_FOREACH (CollectionChild *, child, &target->children) {
55 if (GS(child->collection->id.name) == ID_GR &&
56 STREQ(child->collection->id.name + 2, subname.c_str()))
57 {
58 target = child->collection;
59 found = true;
60 break;
61 }
62 }
63 if (!found) {
64 target = BKE_collection_add(bmain, target, subname.c_str());
65 }
66 }
67
68 /* Proceed to next sub-name component. */
69 subname_start = sep_pos + 1;
70 if (subname_start >= geom_name.size()) {
71 break;
72 }
73 sep_pos = geom_name.find(import_params.collection_separator, subname_start);
74 }
75 return target;
76}
77
78static void geometry_to_blender_geometry_set(const OBJImportParams &import_params,
79 const Span<std::unique_ptr<Geometry>> all_geometries,
80 const GlobalVertices &global_vertices,
81 Vector<bke::GeometrySet> &geometries)
82{
83 for (const std::unique_ptr<Geometry> &geometry : all_geometries) {
84 bke::GeometrySet geometry_set;
85
86 if (geometry->geom_type_ == GEOM_MESH) {
87 MeshFromGeometry mesh_ob_from_geometry{*geometry, global_vertices};
88 Mesh *mesh = mesh_ob_from_geometry.create_mesh(import_params);
89 geometry_set = bke::GeometrySet::from_mesh(mesh);
90 }
91 else if (geometry->geom_type_ == GEOM_CURVE) {
92 CurveFromGeometry curve_ob_from_geometry(*geometry, global_vertices);
93 Curve *curve = curve_ob_from_geometry.create_curve();
94 Curves *curves_id = bke::curve_legacy_to_curves(*curve);
95 geometry_set = bke::GeometrySet::from_curves(curves_id);
96 }
97
98 geometries.append(std::move(geometry_set));
99 }
100}
101
106 Scene *scene,
107 ViewLayer *view_layer,
108 const OBJImportParams &import_params,
109 MutableSpan<std::unique_ptr<Geometry>> all_geometries,
110 const GlobalVertices &global_vertices,
111 Map<std::string, std::unique_ptr<MTLMaterial>> &materials,
112 Map<std::string, Material *> &created_materials)
113{
115
116 /* Sort objects by name: creating many objects is much faster if the creation
117 * order is sorted by name. */
119 all_geometries.begin(), all_geometries.end(), [](const auto &a, const auto &b) {
120 const char *na = a ? a->geometry_name_.c_str() : "";
121 const char *nb = b ? b->geometry_name_.c_str() : "";
122 return BLI_strcasecmp(na, nb) < 0;
123 });
124
125 /* Create all the objects. */
126 Vector<Object *> objects;
127 objects.reserve(all_geometries.size());
128 Set<Collection *> collections;
129 for (const std::unique_ptr<Geometry> &geometry : all_geometries) {
130 Object *obj = nullptr;
131 if (geometry->geom_type_ == GEOM_MESH) {
132 MeshFromGeometry mesh_ob_from_geometry{*geometry, global_vertices};
133 obj = mesh_ob_from_geometry.create_mesh_object(
134 bmain, materials, created_materials, import_params);
135 }
136 else if (geometry->geom_type_ == GEOM_CURVE) {
137 CurveFromGeometry curve_ob_from_geometry(*geometry, global_vertices);
138 obj = curve_ob_from_geometry.create_curve_object(bmain, import_params);
139 }
140 if (obj != nullptr) {
141 Collection *target_collection = find_or_create_collection(
142 bmain, lc->collection, geometry->geometry_name_, import_params);
143 collections.add(target_collection);
144
145 BKE_collection_object_add(bmain, target_collection, obj);
146 objects.append(obj);
147 }
148 }
149
150 /* Do object selections in a separate loop (allows just one view layer sync). */
151 BKE_view_layer_synced_ensure(scene, view_layer);
152 for (Object *obj : objects) {
153 Base *base = BKE_view_layer_base_find(view_layer, obj);
155
158 DEG_id_tag_update_ex(bmain, &obj->id, flags);
159 }
160 for (Collection *col : collections) {
162 }
163
166}
167
168void importer_geometry(const OBJImportParams &import_params,
169 Vector<bke::GeometrySet> &geometries,
170 size_t read_buffer_size)
171{
172 /* List of geometries to be parsed from OBJ file. */
173 Vector<std::unique_ptr<Geometry>> all_geometries;
174 /* Container for vertex and UV vertex coordinates. */
175 GlobalVertices global_vertices;
176
177 OBJParser obj_parser{import_params, read_buffer_size};
178 obj_parser.parse(all_geometries, global_vertices);
179
180 geometry_to_blender_geometry_set(import_params, all_geometries, global_vertices, geometries);
181}
182
183void importer_main(bContext *C, const OBJImportParams &import_params)
184{
185 Main *bmain = CTX_data_main(C);
186 Scene *scene = CTX_data_scene(C);
187 ViewLayer *view_layer = CTX_data_view_layer(C);
188 importer_main(bmain, scene, view_layer, import_params);
189}
190
191void importer_main(Main *bmain,
192 Scene *scene,
193 ViewLayer *view_layer,
194 const OBJImportParams &import_params,
195 size_t read_buffer_size)
196{
197 /* List of geometries to be parsed from OBJ file. */
198 Vector<std::unique_ptr<Geometry>> all_geometries;
199 /* Container for vertex and UV vertex coordinates. */
200 GlobalVertices global_vertices;
201 /* List of MTLMaterial instances to be parsed from MTL file. */
203 Map<std::string, Material *> created_materials;
204
205 OBJParser obj_parser{import_params, read_buffer_size};
206 obj_parser.parse(all_geometries, global_vertices);
207
208 for (StringRefNull mtl_library : obj_parser.mtl_libraries()) {
209 MTLParser mtl_parser{mtl_library, import_params.filepath};
210 mtl_parser.parse_and_store(materials);
211 }
212
213 if (import_params.clear_selection) {
214 BKE_view_layer_base_deselect_all(scene, view_layer);
215 }
217 scene,
218 view_layer,
219 import_params,
220 all_geometries,
221 global_vertices,
222 materials,
223 created_materials);
224}
225} // namespace blender::io::obj
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
LayerCollection * BKE_layer_collection_get_active(ViewLayer *view_layer)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_view_layer_base_deselect_all(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
void BKE_view_layer_base_select_and_set_active(ViewLayer *view_layer, Base *selbase)
#define LISTBASE_FOREACH(type, var, list)
#define STREQ(a, b)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_tag_update_ex(Main *bmain, ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1044
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1071
@ ID_GR
Object groups, one object can be in many groups at once.
bool add(const Key &key)
Definition BLI_set.hh:248
void reserve(const int64_t min_capacity)
Object * create_curve_object(Main *bmain, const OBJImportParams &import_params)
local_group_size(16, 16) .push_constant(Type b
uint col
#define GS(x)
Definition iris.cc:202
Curves * curve_legacy_to_curves(const Curve &curve_legacy)
static Collection * find_or_create_collection(Main *bmain, Collection *target, const std::string &geom_name, const OBJImportParams &import_params)
static void geometry_to_blender_objects(Main *bmain, Scene *scene, ViewLayer *view_layer, const OBJImportParams &import_params, MutableSpan< std::unique_ptr< Geometry > > all_geometries, const GlobalVertices &global_vertices, Map< std::string, std::unique_ptr< MTLMaterial > > &materials, Map< std::string, Material * > &created_materials)
void importer_geometry(const OBJImportParams &import_params, Vector< bke::GeometrySet > &geometries, size_t read_buffer_size)
static void geometry_to_blender_geometry_set(const OBJImportParams &import_params, const Span< std::unique_ptr< Geometry > > all_geometries, const GlobalVertices &global_vertices, Vector< bke::GeometrySet > &geometries)
void importer_main(bContext *C, const OBJImportParams &import_params)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
Definition BLI_sort.hh:23
struct Collection * collection
char filepath[FILE_MAX]
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)