diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index 0d9ab9123a2..9cf817167ef 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -667,7 +667,7 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont if (!transform_writer) { /* Unable to export, so there is nothing to attach any children to; just abort this entire * branch of the export hierarchy. */ - return; + continue; } const bool need_writers = context->is_point_proto || (!context->is_point_instance && diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc index d7fee9724b1..ab19732e76d 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc @@ -149,23 +149,22 @@ USDExporterContext USDHierarchyIterator::create_usd_export_context(const Hierarc return exporter_context; } -void USDHierarchyIterator::determine_point_instancers(const HierarchyContext *context) +bool USDHierarchyIterator::determine_point_instancers(const HierarchyContext *context) { if (!context) { - return; + return true; } if (context->object->type == OB_ARMATURE) { - return; + return true; } + bool is_referencing_self = false; if (context->is_point_instancer()) { /* Mark the point instancer's children as a point instance. */ USDExporterContext usd_export_context = create_usd_export_context(context); const ExportChildren *children = graph_children(context); - bool is_referencing_self = false; - pxr::SdfPath instancer_path; if (!params_.root_prim_path.empty()) { instancer_path = pxr::SdfPath(params_.root_prim_path + context->export_path); @@ -243,6 +242,8 @@ void USDHierarchyIterator::determine_point_instancers(const HierarchyContext *co } } } + + return !is_referencing_self; } AbstractHierarchyWriter *USDHierarchyIterator::create_transform_writer( @@ -251,7 +252,12 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_transform_writer( /* The transform writer is always called before data writers, * so determine if the #Xform's children is a point instancer before writing data. */ if (params_.use_instancing) { - determine_point_instancers(context); + if (!determine_point_instancers(context)) { + /* If we could not determine that our point instancing setup is safe, we should not continue + * writing. Continuing would result in enormous amounts of USD warnings about cyclic + * references. */ + return nullptr; + } } return new USDTransformWriter(create_usd_export_context(context)); diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.hh b/source/blender/io/usd/intern/usd_hierarchy_iterator.hh index 32f9a95886b..2d25b091396 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.hh +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.hh @@ -51,7 +51,7 @@ class USDHierarchyIterator : public AbstractHierarchyIterator { protected: bool mark_as_weak_export(const Object *object) const override; - void determine_point_instancers(const HierarchyContext *context); + bool determine_point_instancers(const HierarchyContext *context); AbstractHierarchyWriter *create_transform_writer(const HierarchyContext *context) override; AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) override;