[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, ¶ms, 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