[Bf-blender-cvs] [25cb3e3cbd3] usd-importer-T81257: USD Import: support instance collections.

makowalski noreply at git.blender.org
Mon Feb 15 05:53:24 CET 2021


Commit: 25cb3e3cbd3a16d9635b42a2365f89e647109799
Author: makowalski
Date:   Sun Feb 14 23:47:15 2021 -0500
Branches: usd-importer-T81257
https://developer.blender.org/rB25cb3e3cbd3a16d9635b42a2365f89e647109799

USD Import: support instance collections.

Extended the experimental instancing option to support
collection-based instancing.  (Previously, the initial instancing
experiment was an optimization based on shared meshes, to
reduce memory usage for large instanced scenes, but this did
not conform to the standard Blender instancing workflows and
could not be easily extended to animations.)

===================================================================

M	source/blender/io/usd/CMakeLists.txt
M	source/blender/io/usd/import/usd_prim_iterator.cc
M	source/blender/io/usd/import/usd_prim_iterator.h
A	source/blender/io/usd/import/usd_reader_instance.cc
A	source/blender/io/usd/import/usd_reader_instance.h
M	source/blender/io/usd/import/usd_reader_mesh_base.cc
M	source/blender/io/usd/intern/usd_capi.cc

===================================================================

diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt
index 3e94517ee47..990d78f4faa 100644
--- a/source/blender/io/usd/CMakeLists.txt
+++ b/source/blender/io/usd/CMakeLists.txt
@@ -59,6 +59,7 @@ set(SRC
   import/usd_material_importer.cc
   import/usd_prim_iterator.cc
   import/usd_reader_camera.cc
+  import/usd_reader_instance.cc
   import/usd_reader_light.cc
   import/usd_reader_mesh.cc
   import/usd_reader_mesh_base.cc
@@ -83,6 +84,7 @@ set(SRC
   import/usd_material_importer.h
   import/usd_prim_iterator.h
   import/usd_reader_camera.h
+  import/usd_reader_instance.h
   import/usd_reader_light.h
   import/usd_reader_mesh.h
   import/usd_reader_mesh_base.h
diff --git a/source/blender/io/usd/import/usd_prim_iterator.cc b/source/blender/io/usd/import/usd_prim_iterator.cc
index f212211e8dc..6d6ce31b437 100644
--- a/source/blender/io/usd/import/usd_prim_iterator.cc
+++ b/source/blender/io/usd/import/usd_prim_iterator.cc
@@ -23,6 +23,7 @@
 #include "usd_data_cache.h"
 #include "usd_importer_context.h"
 #include "usd_reader_camera.h"
+#include "usd_reader_instance.h"
 #include "usd_reader_light.h"
 #include "usd_reader_mesh.h"
 #include "usd_reader_shape.h"
@@ -122,9 +123,19 @@ USDXformableReader *USDPrimIterator::get_object_reader(const pxr::UsdPrim &prim)
 USDXformableReader *USDPrimIterator::get_object_reader(const pxr::UsdPrim &prim,
                                                        const USDImporterContext &context)
 {
+  if (!prim) {
+    return nullptr;
+  }
+
   USDXformableReader *result = nullptr;
 
-  if (prim.IsA<pxr::UsdGeomCamera>()) {
+  if (context.import_params.use_instancing && prim.IsInstance()) {
+    std::cout << "Have instance " << prim.GetPath() << std::endl;
+    std::cout << "    Instance type: " << prim.GetTypeName() << std::endl;
+    std::cout << "    Master: " << prim.GetMaster().GetPath() << std::endl;
+    result = new USDInstanceReader(prim, context);
+  }
+  else if (prim.IsA<pxr::UsdGeomCamera>()) {
     result = new USDCameraReader(prim, context);
   }
   else if (prim.IsA<pxr::UsdGeomMesh>()) {
@@ -197,8 +208,14 @@ void USDPrimIterator::create_object_readers(const pxr::UsdPrim &prim,
   std::vector<USDXformableReader *> child_readers;
 
   /* Recursively create readers for the child prims. */
-  pxr::UsdPrimSiblingRange child_prims = prim.GetFilteredChildren(
-      pxr::UsdTraverseInstanceProxies(pxr::UsdPrimDefaultPredicate));
+
+  pxr::Usd_PrimFlagsPredicate filter_predicate = pxr::UsdPrimDefaultPredicate;
+
+  if (!context.import_params.use_instancing) {
+    filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
+  }
+
+  pxr::UsdPrimSiblingRange child_prims = prim.GetFilteredChildren(filter_predicate);
 
   int num_child_prims = 0;
   for (const pxr::UsdPrim &child_prim : child_prims) {
@@ -214,13 +231,14 @@ void USDPrimIterator::create_object_readers(const pxr::UsdPrim &prim,
   /* We prune away empty transform or scope hierarchies (we can add an import flag to make this
    * behavior optional).  Therefore, we skip this prim if it's an Xform or Scope and if
    * it has no corresponding child readers. */
-  if ((prim.IsA<pxr::UsdGeomXform>() || prim.IsA<pxr::UsdGeomScope>()) && child_readers.empty()) {
+  if (!context.import_params.use_instancing &&
+      (prim.IsA<pxr::UsdGeomXform>() || prim.IsA<pxr::UsdGeomScope>()) && child_readers.empty()) {
     return;
   }
 
   /* If this is an Xform prim, see if we can merge with the child reader. */
 
-  if (prim.IsA<pxr::UsdGeomXform>() && num_child_prims == 1 &&
+  if (prim.IsA<pxr::UsdGeomXform>() && child_readers.size() == 1 &&
       !child_readers.front()->merged_with_parent() &&
       child_readers.front()->can_merge_with_parent()) {
     child_readers.front()->set_merged_with_parent(true);
@@ -239,7 +257,7 @@ void USDPrimIterator::create_object_readers(const pxr::UsdPrim &prim,
     r_child_readers.push_back(reader);
     r_readers.push_back(reader);
   }
-  else {
+  else if (!child_readers.empty()) {
     /* No reader was allocated for this prim, so we pass our child readers back to the caller,
      * for possible handling by a parent reader. */
     r_child_readers.insert(r_child_readers.end(), child_readers.begin(), child_readers.end());
@@ -292,14 +310,53 @@ void USDPrimIterator::cache_prototype_data(USDDataCache &r_cache) const
   }
 }
 
+void USDPrimIterator::create_prototype_object_readers(
+    std::map<pxr::SdfPath, std::vector<USDXformableReader *>> &r_proto_readers) const
+{
+  if (!stage_) {
+    return;
+  }
+
+  std::vector<pxr::UsdPrim> protos = stage_->GetMasters();
+
+  for (const pxr::UsdPrim &proto_prim : protos) {
+
+    if (!proto_prim) {
+      continue;
+    }
+
+    std::cout << "master: " << proto_prim.GetPath() << std::endl;
+
+    std::vector<pxr::UsdPrim> insts = proto_prim.GetInstances();
+
+    for (const pxr::UsdPrim &inst : insts) {
+      if (inst) {
+        std::cout << "   inst: " << inst.GetPath() << std::endl;
+      }
+    }
+
+    std::vector<USDXformableReader *> proto_readers;
+    std::vector<USDXformableReader *> child_readers;
+
+    create_object_readers(proto_prim, context_, proto_readers, child_readers);
+
+    r_proto_readers.insert(std::make_pair(proto_prim.GetPath(), proto_readers));
+  }
+}
+
 bool USDPrimIterator::gather_objects_paths(ListBase *object_paths) const
 {
   if (!stage_) {
     return false;
   }
 
-  pxr::UsdPrimRange prims = stage_->Traverse(
-      pxr::UsdTraverseInstanceProxies(pxr::UsdPrimDefaultPredicate));
+  pxr::Usd_PrimFlagsPredicate filter_predicate = pxr::UsdPrimDefaultPredicate;
+
+  if (!context_.import_params.use_instancing) {
+    filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
+  }
+
+  pxr::UsdPrimRange prims = stage_->Traverse(filter_predicate);
 
   for (const pxr::UsdPrim &prim : prims) {
     void *usd_path_void = MEM_callocN(sizeof(CacheObjectPath), "CacheObjectPath");
diff --git a/source/blender/io/usd/import/usd_prim_iterator.h b/source/blender/io/usd/import/usd_prim_iterator.h
index 8fd7d8a290f..3668d3fe508 100644
--- a/source/blender/io/usd/import/usd_prim_iterator.h
+++ b/source/blender/io/usd/import/usd_prim_iterator.h
@@ -58,6 +58,9 @@ class USDPrimIterator {
 
   void cache_prototype_data(USDDataCache &r_cache) const;
 
+  void create_prototype_object_readers(
+      std::map<pxr::SdfPath, std::vector<USDXformableReader *>> &r_proto_readers) const;
+
   bool gather_objects_paths(ListBase *object_paths) const;
 
   void debug_traverse_stage() const;
diff --git a/source/blender/io/usd/import/usd_reader_instance.cc b/source/blender/io/usd/import/usd_reader_instance.cc
new file mode 100644
index 00000000000..1c024390e36
--- /dev/null
+++ b/source/blender/io/usd/import/usd_reader_instance.cc
@@ -0,0 +1,88 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "usd_reader_instance.h"
+
+#include "BKE_object.h"
+#include "DNA_object_types.h"
+
+#include <iostream>
+
+namespace blender::io::usd {
+
+USDInstanceReader::USDInstanceReader(const pxr::UsdPrim &prim, const USDImporterContext &context)
+    : USDXformableReader(prim, context)
+{
+}
+
+bool USDInstanceReader::valid() const
+{
+  return prim_ && prim_.IsInstance();
+}
+
+void USDInstanceReader::create_object(Main *bmain, double time, USDDataCache *data_cache)
+{
+  if (!this->valid()) {
+    return;
+  }
+
+  /* Determine prim visibility.
+   * TODO(makowalski): Consider optimizations to avoid this expensive call,
+   * for example, by determining visibility during stage traversal. */
+
+  pxr::UsdGeomImageable imageable(prim_);
+
+  if (imageable) {
+    pxr::TfToken vis_tok = imageable.ComputeVisibility();
+
+    if (vis_tok == pxr::UsdGeomTokens->invisible) {
+      return;
+    }
+  }
+
+  std::string obj_name = this->prim_name();
+
+  if (obj_name.empty()) {
+    /* Sanity check. */
+    std::cerr << "Warning: couldn't determine object name for " << this->prim_path() << std::endl;
+  }
+
+  this->object_ = BKE_object_add_only_object(bmain, OB_EMPTY, obj_name.c_str());
+  this->object_->data = nullptr;
+  this->object_->transflag |= OB_DUPLICOLLECTION;
+}
+
+void USDInstanceReader::set_instance_collection(Collection *coll)
+{
+  if (coll && this->object_) {
+    this->object_->instance_collection = coll;
+  }
+}
+
+pxr::SdfPath USDInstanceReader::proto_path() const
+{
+  if (pxr::UsdPrim master = prim_.GetMaster())
+  {
+    return master.GetPath();
+  }
+
+  return pxr::SdfPath();
+}
+
+}  // namespace blender::io::usd
diff --git a/source/blender/io/usd/import/usd_reader_instance.h b/source/blender/io/usd/import/usd_reader_instance.h
new file mode 100644
index 00000000000..9b62c62b1a1
--- /dev/null
+++ b/source/blender/io/usd/import/usd_reader_instance.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list