Blender V4.3
usd_reader_stage.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Tangent Animation and. NVIDIA Corporation. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "usd_reader_stage.hh"
7#include "usd_reader_curve.hh"
9#include "usd_reader_light.hh"
11#include "usd_reader_mesh.hh"
12#include "usd_reader_nurbs.hh"
14#include "usd_reader_points.hh"
15#include "usd_reader_prim.hh"
16#include "usd_reader_shape.hh"
18#include "usd_reader_volume.hh"
19#include "usd_reader_xform.hh"
20#include "usd_utils.hh"
21
22#include <pxr/pxr.h>
23#include <pxr/usd/usdGeom/camera.h>
24#include <pxr/usd/usdGeom/capsule.h>
25#include <pxr/usd/usdGeom/cone.h>
26#include <pxr/usd/usdGeom/cube.h>
27#include <pxr/usd/usdGeom/cylinder.h>
28#include <pxr/usd/usdGeom/mesh.h>
29#include <pxr/usd/usdGeom/nurbsCurves.h>
30#include <pxr/usd/usdGeom/pointInstancer.h>
31#include <pxr/usd/usdGeom/points.h>
32#include <pxr/usd/usdGeom/scope.h>
33#include <pxr/usd/usdGeom/sphere.h>
34#include <pxr/usd/usdGeom/xform.h>
35#include <pxr/usd/usdLux/boundableLightBase.h>
36#include <pxr/usd/usdLux/nonboundableLightBase.h>
37#include <pxr/usd/usdShade/material.h>
38
39#include "BLI_map.hh"
40#include "BLI_math_base.h"
41#include "BLI_sort.hh"
42#include "BLI_string.h"
43
44#include "BKE_collection.hh"
45#include "BKE_lib_id.hh"
46#include "BKE_modifier.hh"
47#include "BKE_report.hh"
48
49#include "CLG_log.h"
50
52#include "DNA_material_types.h"
53
54#include <fmt/format.h>
55
56static CLG_LogRef LOG = {"io.usd"};
57
58namespace blender::io::usd {
59
60static void decref(USDPrimReader *reader)
61{
62 if (!reader) {
63 return;
64 }
65
66 reader->decref();
67
68 if (reader->refcount() == 0) {
69 delete reader;
70 }
71}
72
76static Collection *create_collection(Main *bmain, Collection *parent, const char *name)
77{
78 if (!bmain) {
79 return nullptr;
80 }
81
82 return BKE_collection_add(bmain, parent, name);
83}
84
91 USDInstanceReader *instance_reader,
92 const blender::Map<pxr::SdfPath, Collection *> &proto_collection_map)
93{
94 if (!instance_reader) {
95 return;
96 }
97
98 pxr::SdfPath proto_path = instance_reader->proto_path();
99
100 Collection *collection = proto_collection_map.lookup_default(proto_path, nullptr);
101 if (collection != nullptr) {
102 instance_reader->set_instance_collection(collection);
103 }
104 else {
105 CLOG_WARN(
106 &LOG, "Couldn't find prototype collection for %s", instance_reader->prim_path().c_str());
107 }
108}
109
111 const USDImportParams &params,
112 const ImportSettings &settings)
113 : stage_(stage), params_(params), settings_(settings)
114{
115}
116
121
123{
124 return stage_;
125}
126
127bool USDStageReader::is_primitive_prim(const pxr::UsdPrim &prim) const
128{
129 return (prim.IsA<pxr::UsdGeomCapsule>() || prim.IsA<pxr::UsdGeomCylinder>() ||
130 prim.IsA<pxr::UsdGeomCone>() || prim.IsA<pxr::UsdGeomCube>() ||
131 prim.IsA<pxr::UsdGeomSphere>());
132}
133
135{
136 if (params_.support_scene_instancing && prim.IsInstance()) {
137 return new USDInstanceReader(prim, params_, settings_);
138 }
139 if (params_.import_shapes && is_primitive_prim(prim)) {
140 return new USDShapeReader(prim, params_, settings_);
141 }
142 if (prim.IsA<pxr::UsdGeomPointInstancer>()) {
143 return new USDPointInstancerReader(prim, params_, settings_);
144 }
145 if (params_.import_cameras && prim.IsA<pxr::UsdGeomCamera>()) {
146 return new USDCameraReader(prim, params_, settings_);
147 }
148 if (params_.import_curves && prim.IsA<pxr::UsdGeomBasisCurves>()) {
149 return new USDCurvesReader(prim, params_, settings_);
150 }
151 if (params_.import_curves && prim.IsA<pxr::UsdGeomNurbsCurves>()) {
152 return new USDNurbsReader(prim, params_, settings_);
153 }
154 if (params_.import_meshes && prim.IsA<pxr::UsdGeomMesh>()) {
155 return new USDMeshReader(prim, params_, settings_);
156 }
157 if (params_.import_lights && prim.IsA<pxr::UsdLuxDomeLight>()) {
158 /* Dome lights are handled elsewhere. */
159 return nullptr;
160 }
162 (prim.IsA<pxr::UsdLuxBoundableLightBase>() || prim.IsA<pxr::UsdLuxNonboundableLightBase>()))
163 {
164 return new USDLightReader(prim, params_, settings_);
165 }
166 if (params_.import_volumes && prim.IsA<pxr::UsdVolVolume>()) {
167 return new USDVolumeReader(prim, params_, settings_);
168 }
169 if (params_.import_skeletons && prim.IsA<pxr::UsdSkelSkeleton>()) {
170 return new USDSkeletonReader(prim, params_, settings_);
171 }
172 if (params_.import_points && prim.IsA<pxr::UsdGeomPoints>()) {
173 return new USDPointsReader(prim, params_, settings_);
174 }
175 if (prim.IsA<pxr::UsdGeomImageable>()) {
176 return new USDXformReader(prim, params_, settings_);
177 }
178
179 return nullptr;
180}
181
183{
184 if (params_.support_scene_instancing && prim.IsInstance()) {
185 return new USDInstanceReader(prim, params_, settings_);
186 }
187 if (is_primitive_prim(prim)) {
188 return new USDShapeReader(prim, params_, settings_);
189 }
190 if (prim.IsA<pxr::UsdGeomCamera>()) {
191 return new USDCameraReader(prim, params_, settings_);
192 }
193 if (prim.IsA<pxr::UsdGeomBasisCurves>()) {
194 return new USDCurvesReader(prim, params_, settings_);
195 }
196 if (prim.IsA<pxr::UsdGeomNurbsCurves>()) {
197 return new USDNurbsReader(prim, params_, settings_);
198 }
199 if (prim.IsA<pxr::UsdGeomMesh>()) {
200 return new USDMeshReader(prim, params_, settings_);
201 }
202 if (prim.IsA<pxr::UsdLuxDomeLight>()) {
203 /* We don't handle dome lights. */
204 return nullptr;
205 }
206 if (prim.IsA<pxr::UsdLuxBoundableLightBase>() || prim.IsA<pxr::UsdLuxNonboundableLightBase>()) {
207 return new USDLightReader(prim, params_, settings_);
208 }
209 if (prim.IsA<pxr::UsdVolVolume>()) {
210 return new USDVolumeReader(prim, params_, settings_);
211 }
212 if (prim.IsA<pxr::UsdSkelSkeleton>()) {
213 return new USDSkeletonReader(prim, params_, settings_);
214 }
215 if (prim.IsA<pxr::UsdGeomPoints>()) {
216 return new USDPointsReader(prim, params_, settings_);
217 }
218 if (prim.IsA<pxr::UsdGeomImageable>()) {
219 return new USDXformReader(prim, params_, settings_);
220 }
221 return nullptr;
222}
223
224bool USDStageReader::include_by_visibility(const pxr::UsdGeomImageable &imageable) const
225{
227 /* Invisible prims are allowed. */
228 return true;
229 }
230
231 pxr::UsdAttribute visibility_attr = imageable.GetVisibilityAttr();
232
233 if (!visibility_attr) {
234 /* No visibility attribute, so allow. */
235 return true;
236 }
237
238 /* Include if the prim has an animating visibility attribute or is not invisible. */
239
240 if (visibility_attr.ValueMightBeTimeVarying()) {
241 return true;
242 }
243
244 pxr::TfToken visibility;
245 visibility_attr.Get(&visibility);
246 return visibility != pxr::UsdGeomTokens->invisible;
247}
248
249bool USDStageReader::include_by_purpose(const pxr::UsdGeomImageable &imageable) const
250{
251 if (params_.import_skeletons && imageable.GetPrim().IsA<pxr::UsdSkelSkeleton>()) {
252 /* Always include skeletons, if requested by the user, regardless of purpose. */
253 return true;
254 }
255
257 /* The options allow any purpose, so we trivially include the prim. */
258 return true;
259 }
260
261 pxr::UsdAttribute purpose_attr = imageable.GetPurposeAttr();
262
263 if (!purpose_attr) {
264 /* No purpose attribute, so trivially include the prim. */
265 return true;
266 }
267
268 pxr::TfToken purpose;
269 purpose_attr.Get(&purpose);
270
271 if (purpose == pxr::UsdGeomTokens->guide) {
272 return params_.import_guide;
273 }
274 if (purpose == pxr::UsdGeomTokens->proxy) {
275 return params_.import_proxy;
276 }
277 if (purpose == pxr::UsdGeomTokens->render) {
278 return params_.import_render;
279 }
280
281 return true;
282}
283
284/* Determine if the given reader can use the parent of the encapsulated USD prim
285 * to compute the Blender object's transform. If so, the reader is appropriately
286 * flagged and the function returns true. Otherwise, the function returns false. */
288{
289 USDXformReader *xform_reader = dynamic_cast<USDXformReader *>(reader);
290
291 if (!xform_reader) {
292 return false;
293 }
294
295 /* Check if the Xform reader is already merged. */
296 if (xform_reader->use_parent_xform()) {
297 return false;
298 }
299
300 /* Only merge if the parent is an Xform. */
301 if (!xform_reader->prim().GetParent().IsA<pxr::UsdGeomXform>()) {
302 return false;
303 }
304
305 /* Don't merge Xform and Scope prims. */
306 if (xform_reader->prim().IsA<pxr::UsdGeomXform>() ||
307 xform_reader->prim().IsA<pxr::UsdGeomScope>())
308 {
309 return false;
310 }
311
312 /* Don't merge if the prim has authored transform ops. */
313 if (xform_reader->prim_has_xform_ops()) {
314 return false;
315 }
316
317 /* Flag the Xform reader as merged. */
318 xform_reader->set_use_parent_xform(true);
319
320 return true;
321}
322
323USDPrimReader *USDStageReader::collect_readers(const pxr::UsdPrim &prim,
324 const UsdPathSet &pruned_prims,
325 const bool defined_prims_only,
327{
328 if (prim.IsA<pxr::UsdGeomImageable>()) {
329 pxr::UsdGeomImageable imageable(prim);
330
331 if (!include_by_purpose(imageable)) {
332 return nullptr;
333 }
334
335 if (!include_by_visibility(imageable)) {
336 return nullptr;
337 }
338 }
339
340 if (prim.IsA<pxr::UsdLuxDomeLight>()) {
341 dome_lights_.append(pxr::UsdLuxDomeLight(prim));
342 }
343
344 pxr::Usd_PrimFlagsConjunction filter_flags = pxr::UsdPrimIsActive && pxr::UsdPrimIsLoaded &&
345 !pxr::UsdPrimIsAbstract;
346
347 if (defined_prims_only) {
348 filter_flags &= pxr::UsdPrimIsDefined;
349 }
350
351 pxr::Usd_PrimFlagsPredicate filter_predicate(filter_flags);
353 filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
354 }
355
357
358 pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_predicate);
359
360 for (const auto &child_prim : children) {
361 if (pruned_prims.contains(child_prim.GetPath())) {
362 continue;
363 }
364 if (USDPrimReader *child_reader = collect_readers(
365 child_prim, pruned_prims, defined_prims_only, r_readers))
366 {
367 child_readers.append(child_reader);
368 }
369 }
370
371 if (prim.IsPseudoRoot()) {
372 return nullptr;
373 }
374
375 /* If we find prims that have been auto generated by Blender, we skip them on import
376 * so that the imported scene can closely match the exported scene */
377 if (!settings_.skip_prefix.IsEmpty()) {
378 if (settings_.skip_prefix.HasPrefix(prim.GetPath())) {
379 return nullptr;
380 }
381 }
382
383 /* Check if we can merge an Xform with its child prim. */
384 if (child_readers.size() == 1) {
385
386 USDPrimReader *child_reader = child_readers.first();
387
388 if (merge_with_parent(child_reader)) {
389 return child_reader;
390 }
391 }
392
393 if (prim.IsA<pxr::UsdShadeMaterial>()) {
394 /* Record material path for later processing, if needed,
395 * e.g., when importing all materials. */
396 material_paths_.append(prim.GetPath().GetAsString());
397
398 /* We don't create readers for materials, so return early. */
399 return nullptr;
400 }
401
402 USDPrimReader *reader = create_reader_if_allowed(prim);
403
404 if (!reader) {
405 return nullptr;
406 }
407
408 r_readers.append(reader);
409 reader->incref();
410
411 /* Set each child reader's parent. */
412 for (USDPrimReader *child_reader : child_readers) {
413 child_reader->parent(reader);
414 }
415
416 return reader;
417}
418
420{
421 if (!valid()) {
422 return;
423 }
424
427
428 /* Identify paths to point instancer prototypes, as these will be converted
429 * in a separate pass over the stage. */
430 UsdPathSet instancer_proto_paths = collect_point_instancer_proto_paths();
431
432 /* Iterate through the stage. */
433 pxr::UsdPrim root = stage_->GetPseudoRoot();
434
435 stage_->SetInterpolationType(pxr::UsdInterpolationType::UsdInterpolationTypeHeld);
436
437 /* Create readers, skipping over prototype prims in this pass. */
438 collect_readers(root, instancer_proto_paths, params_.import_defined_only, readers_);
439
441 /* Collect the scene-graph instance prototypes. */
442 std::vector<pxr::UsdPrim> protos = stage_->GetPrototypes();
443
444 for (const pxr::UsdPrim &proto_prim : protos) {
446 collect_readers(proto_prim, instancer_proto_paths, true, proto_readers);
447 proto_readers_.add(proto_prim.GetPath(), proto_readers);
448
449 for (USDPrimReader *reader : proto_readers) {
450 readers_.append(reader);
451 reader->incref();
452 }
453 }
454 }
455
456 if (!instancer_proto_paths.is_empty()) {
457 create_point_instancer_proto_readers(instancer_proto_paths);
458 }
459}
460
462{
463 /* Iterate over the skeleton readers to create the
464 * armature object map, which maps a USD skeleton prim
465 * path to the corresponding armature object. */
466 blender::Map<std::string, Object *> usd_path_to_armature;
467 for (const USDPrimReader *reader : readers_) {
468 if (dynamic_cast<const USDSkeletonReader *>(reader) && reader->object()) {
469 usd_path_to_armature.add(reader->prim_path(), reader->object());
470 }
471 }
472
473 /* Iterate over the mesh readers and set armature objects on armature modifiers. */
474 for (const USDPrimReader *reader : readers_) {
475 if (!reader->object()) {
476 continue;
477 }
478 const USDMeshReader *mesh_reader = dynamic_cast<const USDMeshReader *>(reader);
479 if (!mesh_reader) {
480 continue;
481 }
482 /* Check if the mesh object has an armature modifier. */
484 if (!md) {
485 continue;
486 }
487
488 ArmatureModifierData *amd = reinterpret_cast<ArmatureModifierData *>(md);
489
490 /* Assign the armature based on the bound USD skeleton path of the skinned mesh. */
491 std::string skel_path = mesh_reader->get_skeleton_path();
492 Object *object = usd_path_to_armature.lookup_default(skel_path, nullptr);
493 if (object == nullptr) {
496 "%s: Couldn't find armature object corresponding to USD skeleton %s",
497 __func__,
498 skel_path.c_str());
499 }
500 amd->object = object;
501 }
502}
503
505{
506 BLI_assert(valid());
507
508 /* Build the material name map if it's not built yet. */
511 }
512
513 USDMaterialReader mtl_reader(params_, bmain);
514
515 for (const std::string &mtl_path : material_paths_) {
516 pxr::UsdPrim prim = stage_->GetPrimAtPath(pxr::SdfPath(mtl_path));
517
518 pxr::UsdShadeMaterial usd_mtl(prim);
519 if (!usd_mtl) {
520 continue;
521 }
522
525 {
526 /* The material already exists. */
527 continue;
528 }
529
530 /* Add the material now. */
531 Material *new_mtl = mtl_reader.add_material(usd_mtl);
532 BLI_assert_msg(new_mtl, "Failed to create material");
533
534 const std::string mtl_name = make_safe_name(new_mtl->id.name + 2, true);
536
538 /* Record the unique name of the Blender material we created for the USD material
539 * with the given path, so we don't import the material again when assigning
540 * materials to objects elsewhere in the code. */
542 prim.GetPath().GetAsString()) = mtl_name;
543 }
544 }
545}
546
548{
549 /* Iterate over the imported materials and set a fake user for any unused
550 * materials. */
551 for (const auto path_mat_pair : settings_.usd_path_to_mat_name.items()) {
552 Material *mat = settings_.mat_name_to_mat.lookup_default(path_mat_pair.value, nullptr);
553 if (mat == nullptr) {
554 continue;
555 }
556
557 if (mat->id.us == 0) {
558 id_fake_user_set(&mat->id);
559 }
560 }
561}
562
564{
565 for (USDPrimReader *reader : readers_) {
566 decref(reader);
567 }
568 readers_.clear();
569
570 for (const auto item : proto_readers_.items()) {
571 for (USDPrimReader *reader : item.value) {
572 decref(reader);
573 }
574 }
576
577 for (const auto item : instancer_proto_readers_.items()) {
578 for (USDPrimReader *reader : item.value) {
579 decref(reader);
580 }
581 }
583}
584
586{
588 readers_.begin(), readers_.end(), [](const USDPrimReader *a, const USDPrimReader *b) {
589 const char *na = a ? a->name().c_str() : "";
590 const char *nb = b ? b->name().c_str() : "";
591 return BLI_strcasecmp(na, nb) < 0;
592 });
593}
594
596{
598 return;
599 }
600
601 Collection *all_protos_collection = create_collection(bmain, parent_collection, "prototypes");
602
603 if (all_protos_collection) {
604 all_protos_collection->flag |= COLLECTION_HIDE_VIEWPORT;
605 all_protos_collection->flag |= COLLECTION_HIDE_RENDER;
606 if (parent_collection) {
607 DEG_id_tag_update(&parent_collection->id, ID_RECALC_HIERARCHY);
608 }
609 }
610
611 blender::Map<pxr::SdfPath, Collection *> proto_collection_map;
612
613 for (const pxr::SdfPath &path : proto_readers_.keys()) {
614 Collection *proto_collection = create_collection(bmain, all_protos_collection, "proto");
615
616 proto_collection_map.add(path, proto_collection);
617 }
618
619 /* Set the instance collections on the readers, including the prototype
620 * readers (which are included in readers_), as instancing may be nested. */
621
622 for (USDPrimReader *reader : readers_) {
623 if (USDInstanceReader *instance_reader = dynamic_cast<USDInstanceReader *>(reader)) {
624 set_instance_collection(instance_reader, proto_collection_map);
625 }
626 }
627
628 /* Add the prototype objects to the collections. */
629 for (const auto &item : proto_readers_.items()) {
630 Collection *collection = proto_collection_map.lookup_default(item.key, nullptr);
631 if (collection == nullptr) {
632 CLOG_WARN(&LOG,
633 "Couldn't find collection when adding objects for prototype %s",
634 item.key.GetAsString().c_str());
635 continue;
636 }
637
638 for (USDPrimReader *reader : item.value) {
639 Object *ob = reader->object();
640
641 if (!ob) {
642 continue;
643 }
644
645 BKE_collection_object_add(bmain, collection, ob);
646 }
647 }
648
649 /* Create collections for the point instancer prototypes. */
650
651 /* For every point instancer reader, create a "prototypes" collection and set it
652 * on the Collection Info node referenced by the geometry nodes modifier created by
653 * the reader. We also create collections containing prototype geometry as children
654 * of the "prototypes" collection. These child collections will be indexed for
655 * instancing by the Instance on Points geometry node.
656 *
657 * Note that the prototype collections will be ordered alphabetically by the Collection
658 * Info node. We must therefore take care to generate collection names that will maintain
659 * the original prototype order, so that the prototype indices will remain valid. We use
660 * the naming convention proto_<index>, where the index suffix may be zero padded (e.g.,
661 * "proto_00", "proto_01", "proto_02", etc.).
662 */
663
664 for (USDPrimReader *reader : readers_) {
665 USDPointInstancerReader *instancer_reader = dynamic_cast<USDPointInstancerReader *>(reader);
666
667 if (!instancer_reader) {
668 continue;
669 }
670
671 const pxr::SdfPath &instancer_path = reader->prim().GetPath();
672 Collection *instancer_protos_coll = create_collection(
673 bmain, all_protos_collection, instancer_path.GetName().c_str());
674
675 /* Determine the max number of digits we will need for the possibly zero-padded
676 * string representing the prototype index. */
677 const int max_index_digits = integer_digits_i(instancer_reader->proto_paths().size());
678
679 int proto_index = 0;
680
681 for (const pxr::SdfPath &proto_path : instancer_reader->proto_paths()) {
682 BLI_assert(max_index_digits > 0);
683
684 /* Format the collection name to follow the proto_<index> pattern. */
685 std::string coll_name = fmt::format("proto_{0:0{1}}", proto_index, max_index_digits);
686
687 /* Create the collection and populate it with the prototype objects. */
688 Collection *proto_coll = create_collection(bmain, instancer_protos_coll, coll_name.c_str());
690 proto_path, {});
691 for (USDPrimReader *proto : proto_readers) {
692 Object *ob = proto->object();
693 if (!ob) {
694 continue;
695 }
696 BKE_collection_object_add(bmain, proto_coll, ob);
697 }
698 ++proto_index;
699 }
700
701 instancer_reader->set_collection(bmain, *instancer_protos_coll);
702 }
703}
704
705void USDStageReader::create_point_instancer_proto_readers(const UsdPathSet &proto_paths)
706{
707 if (proto_paths.is_empty()) {
708 return;
709 }
710
711 for (const pxr::SdfPath &path : proto_paths) {
712
713 pxr::UsdPrim proto_prim = stage_->GetPrimAtPath(path);
714
715 if (!proto_prim) {
716 continue;
717 }
718
719 Vector<USDPrimReader *> proto_readers;
720
721 /* Note that point instancer prototypes may be defined as overs, so
722 * we must call collect readers with argument defined_prims_only = false. */
723 collect_readers(proto_prim, proto_paths, false /* include undefined prims */, proto_readers);
724
725 instancer_proto_readers_.add(path, proto_readers);
726
727 for (USDPrimReader *reader : proto_readers) {
728 reader->set_is_in_instancer_proto(true);
729 readers_.append(reader);
730 reader->incref();
731 }
732 }
733}
734
735void USDStageReader::collect_point_instancer_proto_paths(const pxr::UsdPrim &prim,
736 UsdPathSet &r_paths) const
737{
738 /* Note that we use custom filter flags to allow traversing undefined prims,
739 * because prototype prims may be defined as overs which are skipped by the
740 * default predicate. */
741 pxr::Usd_PrimFlagsConjunction filter_flags = pxr::UsdPrimIsActive && pxr::UsdPrimIsLoaded &&
742 !pxr::UsdPrimIsAbstract;
743
744 pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_flags);
745
746 for (const auto &child_prim : children) {
747 if (pxr::UsdGeomPointInstancer instancer = pxr::UsdGeomPointInstancer(child_prim)) {
748 /* We should only collect the prototype paths from this instancer if it would be included
749 * by our purpose and visibility checks, matching what is inside #collect_readers. */
750 if (!include_by_purpose(instancer)) {
751 continue;
752 }
753 if (!include_by_visibility(instancer)) {
754 continue;
755 }
756
757 pxr::SdfPathVector paths;
758 instancer.GetPrototypesRel().GetTargets(&paths);
759 for (const pxr::SdfPath &path : paths) {
760 r_paths.add(path);
761 }
762 }
763
764 collect_point_instancer_proto_paths(child_prim, r_paths);
765 }
766}
767
768UsdPathSet USDStageReader::collect_point_instancer_proto_paths() const
769{
771
772 if (!stage_) {
773 return result;
774 }
775
776 collect_point_instancer_proto_paths(stage_->GetPseudoRoot(), result);
777
778 std::vector<pxr::UsdPrim> protos = stage_->GetPrototypes();
779
780 for (const pxr::UsdPrim &proto_prim : protos) {
781 collect_point_instancer_proto_paths(proto_prim, result);
782 }
783
784 return result;
785}
786
787} // namespace blender::io::usd
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
void id_fake_user_set(ID *id)
Definition lib_id.cc:389
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
MINLINE int integer_digits_i(int i)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_HIERARCHY
Definition DNA_ID.h:1125
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_RENDER
@ COLLECTION_HIDE_VIEWPORT
@ eModifierType_Armature
void clear()
Definition BLI_map.hh:989
Value & lookup_or_add_default(const Key &key)
Definition BLI_map.hh:601
KeyIterator keys() const
Definition BLI_map.hh:837
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
ItemIterator items() const
Definition BLI_map.hh:864
bool is_empty() const
Definition BLI_map.hh:937
bool is_empty() const
Definition BLI_set.hh:572
int64_t size() const
void append(const T &value)
const T & first() const
void set_instance_collection(Collection *coll)
Material * add_material(const pxr::UsdShadeMaterial &usd_material) const
std::string get_skeleton_path() const
void set_collection(Main *bmain, Collection &coll)
const std::string & prim_path() const
const pxr::UsdPrim & prim() const
USDPrimReader * create_reader(const pxr::UsdPrim &prim)
blender::Vector< pxr::UsdLuxDomeLight > dome_lights_
USDPrimReader * create_reader_if_allowed(const pxr::UsdPrim &prim)
blender::Vector< USDPrimReader * > readers_
blender::Vector< std::string > material_paths_
void create_proto_collections(Main *bmain, Collection *parent_collection)
USDStageReader(pxr::UsdStageRefPtr stage, const USDImportParams &params, const ImportSettings &settings)
void import_all_materials(struct Main *bmain)
local_group_size(16, 16) .push_constant(Type b
EvaluationStage stage
Definition deg_eval.cc:83
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define LOG(severity)
Definition log.h:33
void build_material_map(const Main *bmain, blender::Map< std::string, Material * > *r_mat_map)
blender::Set< pxr::SdfPath > UsdPathSet
static void decref(USDPrimReader *reader)
std::string make_safe_name(const std::string &name, bool allow_unicode)
Definition usd_utils.cc:16
Material * find_existing_material(const pxr::SdfPath &usd_mat_path, const USDImportParams &params, const blender::Map< std::string, Material * > &mat_map, const blender::Map< std::string, std::string > &usd_path_to_mat_name)
static Collection * create_collection(Main *bmain, Collection *parent, const char *name)
static void set_instance_collection(USDInstanceReader *instance_reader, const blender::Map< pxr::SdfPath, Collection * > &proto_collection_map)
@ USD_MTL_NAME_COLLISION_MAKE_UNIQUE
Definition usd.hh:36
static bool merge_with_parent(USDPrimReader *reader)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
Definition BLI_sort.hh:23
int us
Definition DNA_ID.h:435
char name[66]
Definition DNA_ID.h:425
blender::Map< std::string, Material * > mat_name_to_mat
blender::Map< std::string, std::string > usd_path_to_mat_name
eUSDMtlNameCollisionMode mtl_name_collision_mode
Definition usd.hh:217
static CLG_LogRef LOG