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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs