[Bf-blender-cvs] [5c123200554] usd-importer-T81257: USD importer instancing.

Michael A. Kowalski noreply at git.blender.org
Fri Nov 6 23:17:29 CET 2020


Commit: 5c123200554aa5f5c6c77b111a1ad75b281fad05
Author: Michael A. Kowalski
Date:   Fri Nov 6 17:15:18 2020 -0500
Branches: usd-importer-T81257
https://developer.blender.org/rB5c123200554aa5f5c6c77b111a1ad75b281fad05

USD importer instancing.

Added basic support for sharing instance prototype meshes.
This allows sharing of mesh geometry for instanceable
prims, but doesn't yet handle converting the point
instancer prim.

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

M	source/blender/editors/io/io_usd.c
M	source/blender/io/usd/import/usd_importer_context.h
M	source/blender/io/usd/import/usd_prim_iterator.cc
M	source/blender/io/usd/import/usd_prim_iterator.h
M	source/blender/io/usd/import/usd_reader_mesh_base.cc
M	source/blender/io/usd/import/usd_reader_mesh_base.h
M	source/blender/io/usd/intern/usd_capi.cc
M	source/blender/io/usd/usd.h

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

diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c
index c223e22bc46..a665b5e1aa1 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -277,13 +277,16 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
 
   const bool debug = RNA_boolean_get(op->ptr, "debug");
 
+  const bool use_instancing = RNA_boolean_get(op->ptr, "use_instancing");
+
   /* Switch out of edit mode to avoid being stuck in it (T54326). */
   Object *obedit = CTX_data_edit_object(C);
   if (obedit) {
     ED_object_mode_set(C, OB_MODE_OBJECT);
   }
 
-  struct USDImportParams params = {import_uvs, import_normals, import_materials, scale, debug};
+  struct USDImportParams params = {
+      import_uvs, import_normals, import_materials, scale, debug, use_instancing};
 
   bool ok = USD_import(C, filename, &params, as_background_job);
 
@@ -307,6 +310,10 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
   uiItemR(col, ptr, "import_normals", 0, NULL, ICON_NONE);
   uiItemR(col, ptr, "import_materials", 0, NULL, ICON_NONE);
   uiItemR(col, ptr, "debug", 0, NULL, ICON_NONE);
+
+  box = uiLayoutBox(layout);
+  uiItemL(box, IFACE_("Experimental"), ICON_NONE);
+  uiItemR(box, ptr, "use_instancing", 0, NULL, ICON_NONE);
 }
 
 void WM_OT_usd_import(wmOperatorType *ot)
@@ -350,6 +357,14 @@ void WM_OT_usd_import(wmOperatorType *ot)
 
   RNA_def_boolean(
       ot->srna, "debug", false, "debug", "When checked, output debug information to the shell.");
+
+  RNA_def_boolean(
+      ot->srna,
+      "use_instancing",
+      false,
+      "Instancing",
+      "When checked, instanced USD references are imported as shared data in Blender. "
+      "When unchecked, instanced USD reference are imported as unique data in Blender.");
 }
 
 #endif /* WITH_USD */
diff --git a/source/blender/io/usd/import/usd_importer_context.h b/source/blender/io/usd/import/usd_importer_context.h
index 6f8b2791cbb..0970fd9e789 100644
--- a/source/blender/io/usd/import/usd_importer_context.h
+++ b/source/blender/io/usd/import/usd_importer_context.h
@@ -24,9 +24,14 @@
 
 namespace blender::io::usd {
 
+class USDXformableReader;
+
+typedef std::map<pxr::SdfPath, USDXformableReader *> ObjectReaderMap;
+
 struct USDImporterContext {
   const pxr::TfToken stage_up_axis;
   const USDImportParams import_params;
+  ObjectReaderMap *proto_readers;
 };
 
 }  // namespace blender::io::usd
diff --git a/source/blender/io/usd/import/usd_prim_iterator.cc b/source/blender/io/usd/import/usd_prim_iterator.cc
index 6f40538c787..491103e6135 100644
--- a/source/blender/io/usd/import/usd_prim_iterator.cc
+++ b/source/blender/io/usd/import/usd_prim_iterator.cc
@@ -52,6 +52,33 @@ void USDPrimIterator::create_object_readers(const USDImporterContext &context,
   create_object_readers(stage_->GetPseudoRoot(), context, r_readers, child_readers);
 }
 
+void USDPrimIterator::create_prototype_object_readers(
+    const USDImporterContext &context,
+    std::map<pxr::SdfPath, USDXformableReader *> &r_proto_readers) const
+{
+  if (!stage_) {
+    return;
+  }
+
+  std::vector<pxr::UsdPrim> protos = stage_->GetMasters();
+
+  for (const pxr::UsdPrim &proto_prim : protos) {
+    std::vector<USDXformableReader *> proto_readers;
+    std::vector<USDXformableReader *> child_readers;
+
+    create_object_readers(proto_prim, context, proto_readers, child_readers);
+
+    for (USDXformableReader *reader : proto_readers) {
+      if (reader) {
+        pxr::UsdPrim reader_prim = reader->prim();
+        if (reader_prim) {
+          r_proto_readers.insert(std::make_pair(reader_prim.GetPath(), reader));
+        }
+      }
+    }
+  }
+}
+
 void USDPrimIterator::debug_traverse_stage() const
 {
   debug_traverse_stage(stage_);
@@ -147,7 +174,12 @@ void USDPrimIterator::debug_traverse_stage(const pxr::UsdStageRefPtr &usd_stage)
   for (const pxr::UsdPrim &prim : prims) {
     std::cout << prim.GetPath() << std::endl;
     std::cout << "  Type: " << prim.GetTypeName() << std::endl;
-    ;
+    if (prim.IsInstanceProxy()) {
+      pxr::UsdPrim proto_prim = prim.GetPrimInMaster();
+      if (proto_prim) {
+        std::cout << "  Prototype prim: " << proto_prim.GetPath() << std::endl;
+      }
+    }
   }
 }
 
diff --git a/source/blender/io/usd/import/usd_prim_iterator.h b/source/blender/io/usd/import/usd_prim_iterator.h
index e7a9c5484a6..672dbb098c6 100644
--- a/source/blender/io/usd/import/usd_prim_iterator.h
+++ b/source/blender/io/usd/import/usd_prim_iterator.h
@@ -20,6 +20,7 @@
 
 #include "pxr/usd/usd/common.h"
 
+#include <map>
 #include <vector>
 
 namespace blender::io::usd {
@@ -37,6 +38,10 @@ class USDPrimIterator {
   void create_object_readers(const USDImporterContext &context,
                              std::vector<USDXformableReader *> &r_readers) const;
 
+  void create_prototype_object_readers(
+      const USDImporterContext &context,
+      std::map<pxr::SdfPath, USDXformableReader *> &r_proto_readers) const;
+
   void debug_traverse_stage() const;
 
   static USDXformableReader *get_object_reader(const pxr::UsdPrim &prim,
diff --git a/source/blender/io/usd/import/usd_reader_mesh_base.cc b/source/blender/io/usd/import/usd_reader_mesh_base.cc
index 5b53624d64b..409b90096cd 100644
--- a/source/blender/io/usd/import/usd_reader_mesh_base.cc
+++ b/source/blender/io/usd/import/usd_reader_mesh_base.cc
@@ -23,6 +23,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 
+#include "BKE_lib_id.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
 #include "BKE_object.h"
@@ -33,6 +34,8 @@
 
 namespace blender::io::usd {
 
+std::map<pxr::SdfPath, Mesh *> USDMeshReaderBase::s_prototype_meshes;
+
 USDMeshReaderBase::USDMeshReaderBase(const pxr::UsdPrim &prim, const USDImporterContext &context)
     : USDXformableReader(prim, context)
 {
@@ -83,9 +86,61 @@ void USDMeshReaderBase::create_object(Main *bmain, double time)
 
 Mesh *USDMeshReaderBase::read_mesh(Main *bmain, double time)
 {
-  /* We will add logic here to return a shared mesh
-   * if instancing is enabled, rather than calling
-   * create_mes(). */
+  /* If this prim is an instance proxy and instancing is enabled,
+   * return the shared mesh created by the instance prototype. */
+
+  if (this->context_.import_params.use_instancing && this->context_.proto_readers &&
+      this->prim_.IsInstanceProxy()) {
+
+    pxr::UsdPrim proto_prim = this->prim_.GetPrimInMaster();
+
+    if (proto_prim) {
+
+      pxr::SdfPath proto_path = proto_prim.GetPath();
+
+      /* See if the prototype is already been cached. */
+      std::map<pxr::SdfPath, Mesh *>::const_iterator proto_mesh_iter = s_prototype_meshes.find(
+          proto_path);
+      if (proto_mesh_iter != s_prototype_meshes.end()) {
+        Mesh *cached_mesh = proto_mesh_iter->second;
+        if (cached_mesh) {
+          /* Increment the user count before returning. */
+          id_us_plus(&cached_mesh->id);
+        }
+        return cached_mesh;
+      }
+
+      /* No cached mesh.  Lookup the reader for the prototype prim. */
+
+      ObjectReaderMap::iterator proto_reader_iter = this->context_.proto_readers->find(proto_path);
+
+      if (proto_reader_iter != this->context_.proto_readers->end()) {
+
+        USDXformableReader *proto_reader = proto_reader_iter->second;
+
+        USDMeshReaderBase *proto_mesh_reader = dynamic_cast<USDMeshReaderBase *>(proto_reader);
+
+        if (proto_mesh_reader) {
+          Mesh *proto_mesh = proto_mesh_reader->create_mesh(bmain, time);
+
+          if (proto_mesh) {
+            s_prototype_meshes.insert(std::make_pair(proto_path, proto_mesh));
+            return proto_mesh;
+          }
+          else {
+            std::cerr << "Couldn't evaluate prototype " << proto_path.GetString()
+                      << " mesh for instance " << this->prim_path_ << std::endl;
+          }
+        }
+        else {
+          std::cerr << "Invalid prototype " << proto_path.GetString()
+                    << " reader type for instance " << this->prim_path_ << std::endl;
+        }
+      }
+    }
+  }
+
+  /* Not sharing the prototype mesh, so create unique mesh data. */
   return create_mesh(bmain, time);
 }
 
diff --git a/source/blender/io/usd/import/usd_reader_mesh_base.h b/source/blender/io/usd/import/usd_reader_mesh_base.h
index 687659e7887..d30e5c05f92 100644
--- a/source/blender/io/usd/import/usd_reader_mesh_base.h
+++ b/source/blender/io/usd/import/usd_reader_mesh_base.h
@@ -20,6 +20,10 @@
 
 #include "usd_reader_xformable.h"
 
+#include <map>
+
+struct Mesh;
+
 namespace blender::io::usd {
 
 /* Abstract base class of readers that can create a Blender mesh object.
@@ -28,6 +32,9 @@ namespace blender::io::usd {
 
 class USDMeshReaderBase : public USDXformableReader {
  protected:
+  /* Shared meshes for instancing. */
+  static std::map<pxr::SdfPath, Mesh *> s_prototype_meshes;
+
  public:
   USDMeshReaderBase(const pxr::UsdPrim &prim, const USDImporterContext &context);
 
@@ -39,6 +46,15 @@ class USDMeshReaderBase : public USDXformableReader {
 
   virtual struct Mesh *create_mesh(Main *bmain, double time) = 0;
   virtual void assign_materials(Main *bmain, Mesh *mesh, double time) = 0;
+
+  static const std::map<pxr::SdfPath, Mesh *> &prototype_meshes()
+  {
+    return s_prototype_meshes;
+  }
+  static void clear_prototype_meshes()
+  {
+    s_prototype_meshes.clear();
+  }
 };
 
 }  // namespace blender::io::usd
diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc
index 4e64ae1e8c5..90ffe235736 100644
--- a/source/blender/io/usd/intern/usd_capi.cc
+++ b/source/blender/io/usd/intern/usd_capi.cc
@@ -19,6 +19,7 @@
 
 #include "import/usd_importer_context.h"
 #include "import/usd_prim_iterator.h"
+#include "import/usd_reader_mesh_base.h"
 #include "import/usd_reader_xformable.h"
 #include "usd.h"
 #include "usd_hierarchy_iterator.h"
@@ -233,6 +234,7 @@ struct ImportJobData {
 
   pxr::UsdStageRefPtr stage;
   std::vector<USDXformableReader *> readers;
+  std::map<pxr::SdfPath, USDXformableReader *> proto_readers;
 };
 
 static void import_startjob(void *user_data, short *stop, short *do_update, float *progress)
@@ -258,7 +260,7 @@ static void

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list