24#include <pxr/usd/usd/primRange.h>
25#include <pxr/usd/usdGeom/camera.h>
26#include <pxr/usd/usdGeom/capsule.h>
27#include <pxr/usd/usdGeom/capsule_1.h>
28#include <pxr/usd/usdGeom/cone.h>
29#include <pxr/usd/usdGeom/cube.h>
30#include <pxr/usd/usdGeom/cylinder.h>
31#include <pxr/usd/usdGeom/cylinder_1.h>
32#include <pxr/usd/usdGeom/mesh.h>
33#include <pxr/usd/usdGeom/metrics.h>
34#include <pxr/usd/usdGeom/nurbsCurves.h>
35#include <pxr/usd/usdGeom/plane.h>
36#include <pxr/usd/usdGeom/pointInstancer.h>
37#include <pxr/usd/usdGeom/points.h>
38#include <pxr/usd/usdGeom/scope.h>
39#include <pxr/usd/usdGeom/sphere.h>
40#include <pxr/usd/usdGeom/tokens.h>
41#include <pxr/usd/usdGeom/xform.h>
42#include <pxr/usd/usdLux/boundableLightBase.h>
43#include <pxr/usd/usdLux/domeLight.h>
44#include <pxr/usd/usdLux/domeLight_1.h>
45#include <pxr/usd/usdLux/nonboundableLightBase.h>
46#include <pxr/usd/usdShade/material.h>
105 if (!instance_reader) {
109 pxr::SdfPath proto_path = instance_reader->
proto_path();
112 if (collection !=
nullptr) {
117 "Couldn't find prototype collection for %s",
118 instance_reader->
prim_path().GetAsString().c_str());
126 if (!stage || pxr::UsdGeomGetStageUpAxis(stage) == pxr::UsdGeomTokens->
z) {
134 float axis[3] = {1.0f, 0.0f, 0.0f};
151 pxr::TfToken generated_key(
"Blender:generated");
152 pxr::SdfPath path(
"/");
153 auto prim = stage->GetPseudoRoot();
156 uint32_t child_count = 0;
157 for (
auto child : prim.GetChildren()) {
158 if (child_count == 0) {
159 prim = child.GetPrim();
164 if (child_count != 1) {
172 if (!prim.HasCustomDataKey(generated_key)) {
175 path = path.AppendChild(prim.GetName());
179 if (path == pxr::SdfPath(
"/")) {
180 path = pxr::SdfPath();
191 const std::string doc = stage->GetRootLayer()->GetDocumentation();
194 if (doc.find(
"Blender v", 0) == 0) {
202 const std::function<
CacheFile *()> &get_cache_file_fn)
208 settings_.get_cache_file = get_cache_file_fn;
209 settings_.stage_meters_per_unit = pxr::UsdGeomGetStageMetersPerUnit(
stage);
211 if (
params.apply_unit_conversion_scale) {
226bool USDStageReader::is_primitive_prim(
const pxr::UsdPrim &prim)
const
228 return (prim.IsA<pxr::UsdGeomCapsule>() || prim.IsA<pxr::UsdGeomCapsule_1>() ||
229 prim.IsA<pxr::UsdGeomCylinder>() || prim.IsA<pxr::UsdGeomCylinder_1>() ||
230 prim.IsA<pxr::UsdGeomCone>() || prim.IsA<pxr::UsdGeomCube>() ||
231 prim.IsA<pxr::UsdGeomSphere>() || prim.IsA<pxr::UsdGeomPlane>());
236 if (
params_.support_scene_instancing && prim.IsInstance()) {
239 if (
params_.import_shapes && is_primitive_prim(prim)) {
242 if (prim.IsA<pxr::UsdGeomPointInstancer>()) {
245 if (
params_.import_cameras && prim.IsA<pxr::UsdGeomCamera>()) {
248 if (
params_.import_curves && prim.IsA<pxr::UsdGeomBasisCurves>()) {
251 if (
params_.import_curves && prim.IsA<pxr::UsdGeomNurbsCurves>()) {
254 if (
params_.import_meshes && prim.IsA<pxr::UsdGeomMesh>()) {
258 (prim.IsA<pxr::UsdLuxDomeLight>() || prim.IsA<pxr::UsdLuxDomeLight_1>()))
264 (prim.IsA<pxr::UsdLuxBoundableLightBase>() || prim.IsA<pxr::UsdLuxNonboundableLightBase>()))
268 if (
params_.import_volumes && prim.IsA<pxr::UsdVolVolume>()) {
271 if (
params_.import_skeletons && prim.IsA<pxr::UsdSkelSkeleton>()) {
274 if (
params_.import_points && prim.IsA<pxr::UsdGeomPoints>()) {
277 if (prim.IsA<pxr::UsdGeomImageable>()) {
286 if (
params_.support_scene_instancing && prim.IsInstance()) {
289 if (is_primitive_prim(prim)) {
292 if (prim.IsA<pxr::UsdGeomCamera>()) {
295 if (prim.IsA<pxr::UsdGeomBasisCurves>()) {
298 if (prim.IsA<pxr::UsdGeomNurbsCurves>()) {
301 if (prim.IsA<pxr::UsdGeomMesh>()) {
304 if (prim.IsA<pxr::UsdLuxDomeLight>() || prim.IsA<pxr::UsdLuxDomeLight_1>()) {
308 if (prim.IsA<pxr::UsdLuxBoundableLightBase>() || prim.IsA<pxr::UsdLuxNonboundableLightBase>()) {
311 if (prim.IsA<pxr::UsdVolVolume>()) {
314 if (prim.IsA<pxr::UsdSkelSkeleton>()) {
317 if (prim.IsA<pxr::UsdGeomPoints>()) {
320 if (prim.IsA<pxr::UsdGeomPointInstancer>()) {
323 if (prim.IsA<pxr::UsdGeomImageable>()) {
329bool USDStageReader::include_by_visibility(
const pxr::UsdGeomImageable &imageable)
const
336 pxr::UsdAttribute visibility_attr = imageable.GetVisibilityAttr();
338 if (!visibility_attr) {
345 if (visibility_attr.ValueMightBeTimeVarying()) {
349 pxr::TfToken visibility;
350 visibility_attr.Get(&visibility);
351 return visibility != pxr::UsdGeomTokens->invisible;
354bool USDStageReader::include_by_purpose(
const pxr::UsdGeomImageable &imageable)
const
356 if (
params_.import_skeletons && imageable.GetPrim().IsA<pxr::UsdSkelSkeleton>()) {
366 pxr::UsdAttribute purpose_attr = imageable.GetPurposeAttr();
373 pxr::TfToken purpose;
374 purpose_attr.Get(&purpose);
376 if (purpose == pxr::UsdGeomTokens->guide) {
379 if (purpose == pxr::UsdGeomTokens->proxy) {
382 if (purpose == pxr::UsdGeomTokens->render) {
389bool USDStageReader::merge_with_parent(
USDPrimReader *reader)
const
392 if (!
params_.merge_parent_xform) {
396 USDXformReader *xform_reader =
dynamic_cast<USDXformReader *
>(reader);
403 if (xform_reader->use_parent_xform()) {
408 if (!xform_reader->prim().GetParent().IsA<pxr::UsdGeomXform>()) {
413 if (xform_reader->prim().IsA<pxr::UsdGeomXform>() ||
414 xform_reader->prim().IsA<pxr::UsdGeomScope>())
420 if (xform_reader->prim_has_xform_ops()) {
425 xform_reader->set_use_parent_xform(
true);
432 const bool defined_prims_only,
433 blender::Vector<USDPrimReader *> &r_readers)
435 if (prim.IsA<pxr::UsdGeomImageable>()) {
436 pxr::UsdGeomImageable imageable(prim);
438 if (!include_by_purpose(imageable)) {
442 if (!include_by_visibility(imageable)) {
447 if (prim.IsA<pxr::UsdLuxDomeLight>() || prim.IsA<pxr::UsdLuxDomeLight_1>()) {
448 USDDomeLightReader *reader =
new USDDomeLightReader(prim,
params_,
settings_);
453 pxr::Usd_PrimFlagsConjunction filter_flags = pxr::UsdPrimIsActive && pxr::UsdPrimIsLoaded &&
454 !pxr::UsdPrimIsAbstract;
456 if (defined_prims_only) {
457 filter_flags &= pxr::UsdPrimIsDefined;
460 pxr::Usd_PrimFlagsPredicate filter_predicate(filter_flags);
461 if (!
params_.support_scene_instancing) {
462 filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
465 blender::Vector<USDPrimReader *> child_readers;
467 pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_predicate);
469 for (
const auto &child_prim : children) {
470 if (pruned_prims.contains(child_prim.GetPath())) {
474 child_prim, pruned_prims, defined_prims_only, r_readers))
476 child_readers.
append(child_reader);
480 if (prim.IsPseudoRoot()) {
487 if (
settings_.skip_prefix.HasPrefix(prim.GetPath())) {
493 if (child_readers.
size() == 1) {
495 USDPrimReader *child_reader = child_readers.
first();
497 if (merge_with_parent(child_reader)) {
502 if (prim.IsA<pxr::UsdShadeMaterial>()) {
516 if (!reader->valid()) {
524 for (USDPrimReader *child_reader : child_readers) {
525 child_reader->parent(reader);
541 UsdPathSet instancer_proto_paths = collect_point_instancer_proto_paths();
544 pxr::UsdPrim root =
stage_->GetPseudoRoot();
546 stage_->SetInterpolationType(pxr::UsdInterpolationType::UsdInterpolationTypeHeld);
551 if (
params_.support_scene_instancing) {
553 std::vector<pxr::UsdPrim> protos =
stage_->GetPrototypes();
555 for (
const pxr::UsdPrim &proto_prim : protos) {
557 collect_readers(proto_prim, instancer_proto_paths,
true, proto_readers);
567 if (!instancer_proto_paths.
is_empty()) {
568 create_point_instancer_proto_readers(instancer_proto_paths);
580 usd_path_to_armature.
add(reader->prim_path(), reader->object());
586 if (!reader->object()) {
604 if (
object ==
nullptr) {
607 "%s: Couldn't find armature object corresponding to USD skeleton %s",
609 skel_path.GetAsString().c_str());
620 if (
settings_.mat_name_to_mat.is_empty()) {
626 pxr::UsdPrim prim =
stage_->GetPrimAtPath(mtl_path);
628 pxr::UsdShadeMaterial usd_mtl(prim);
641 const bool have_import_hook =
settings_.mat_import_hook_sources.contains(mtl_path);
654 settings_.usd_path_to_mat.add_new(mtl_path, new_mtl);
657 if (have_import_hook) {
660 settings_.usd_path_to_mat_for_hook.add_new(mtl_path, new_mtl);
670 if (mat->id.us == 0) {
678 pxr::UsdPrimRange range =
stage_->Traverse();
679 for (pxr::UsdPrim prim : range) {
680 if (prim.IsA<pxr::UsdShadeMaterial>()) {
681 pxr::UsdShadeMaterial usd_mat(prim);
683 settings_.mat_import_hook_sources.add(prim.GetPath());
691 if (
settings_.usd_path_to_mat_for_hook.is_empty()) {
696 for (
const auto item :
settings_.usd_path_to_mat_for_hook.items()) {
697 pxr::UsdPrim prim =
stage_->GetPrimAtPath(item.key);
699 pxr::UsdShadeMaterial usd_mtl(prim);
710 "USD hook 'on_material_import' for material %s failed, attempting to convert USD "
711 "Preview Surface material",
712 usd_mtl.GetPath().GetAsString().c_str());
751 const char *na = a ? a->name().c_str() :
"";
752 const char *nb = b ? b->name().c_str() :
"";
753 return BLI_strcasecmp(na, nb) < 0;
765 if (all_protos_collection) {
768 if (parent_collection) {
778 proto_collection_map.
add(path, proto_collection);
793 if (collection ==
nullptr) {
795 "Couldn't find collection when adding objects for prototype %s",
796 item.key.GetAsString().c_str());
828 if (!instancer_reader) {
832 pxr::SdfPathVector proto_paths = instancer_reader->
proto_paths();
833 const pxr::SdfPath &instancer_path = reader->prim().GetPath();
835 bmain, all_protos_collection, instancer_path.GetName().c_str());
843 for (
const pxr::SdfPath &proto_path : proto_paths) {
847 std::string coll_name = fmt::format(
"proto_{0:0{1}}", proto_index, max_index_digits);
854 Object *ob = proto->object();
867void USDStageReader::create_point_instancer_proto_readers(
const UsdPathSet &proto_paths)
873 for (
const pxr::SdfPath &path : proto_paths) {
875 pxr::UsdPrim proto_prim =
stage_->GetPrimAtPath(path);
889 for (USDPrimReader *reader : proto_readers) {
890 reader->set_is_in_instancer_proto(
true);
897void USDStageReader::collect_point_instancer_proto_paths(
const pxr::UsdPrim &prim,
903 pxr::Usd_PrimFlagsConjunction filter_flags = pxr::UsdPrimIsActive && pxr::UsdPrimIsLoaded &&
904 !pxr::UsdPrimIsAbstract;
906 pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_flags);
908 for (
const auto &child_prim : children) {
912 if (child_prim.IsDefined()) {
913 const pxr::UsdGeomImageable imageable = pxr::UsdGeomImageable(child_prim);
921 if (!include_by_purpose(imageable)) {
925 if (!include_by_visibility(imageable)) {
932 if (!
params_.support_scene_instancing && child_prim.IsInPrototype()) {
936 if (pxr::UsdGeomPointInstancer instancer = pxr::UsdGeomPointInstancer(child_prim)) {
937 pxr::SdfPathVector paths;
938 instancer.GetPrototypesRel().GetTargets(&paths);
939 for (
const pxr::SdfPath &path : paths) {
944 collect_point_instancer_proto_paths(child_prim, r_paths);
948UsdPathSet USDStageReader::collect_point_instancer_proto_paths()
const
956 collect_point_instancer_proto_paths(
stage_->GetPseudoRoot(),
result);
958 std::vector<pxr::UsdPrim> protos =
stage_->GetPrototypes();
960 for (
const pxr::UsdPrim &proto_prim : protos) {
961 collect_point_instancer_proto_paths(proto_prim,
result);
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
void id_fake_user_set(ID *id)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_msg(a, msg)
MINLINE int integer_digits_i(int i)
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void unit_m4(float m[4][4])
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
#define CLOG_WARN(clg_ref,...)
void DEG_id_tag_update(ID *id, unsigned int flags)
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_VIEWPORT
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
void append(const T &value)
pxr::SdfPath proto_path() const
void set_instance_collection(Collection *coll)
Material * add_material(const pxr::UsdShadeMaterial &usd_material, bool read_usd_preview=true) const
void import_usd_preview(Material *mtl, const pxr::UsdShadeMaterial &usd_material) const
pxr::SdfPath get_skeleton_path() const
pxr::SdfPathVector proto_paths() const
void set_collection(Main *bmain, Collection &coll)
pxr::SdfPath prim_path() const
ReportList * reports() const
ProtoReaderMap proto_readers_
USDPrimReader * create_reader(const pxr::UsdPrim &prim)
void fake_users_for_unused_materials()
void call_material_import_hooks(struct Main *bmain) const
pxr::UsdStageRefPtr stage()
const USDImportParams & params() const
USDPrimReader * create_reader_if_allowed(const pxr::UsdPrim &prim)
blender::Vector< USDPrimReader * > readers_
pxr::UsdStageRefPtr stage_
blender::Vector< pxr::SdfPath > material_paths_
void find_material_import_hook_sources()
USDStageReader(pxr::UsdStageRefPtr stage, const USDImportParams ¶ms, const std::function< CacheFile *()> &get_cache_file_fn={})
blender::Vector< USDDomeLightReader * > dome_light_readers_
ProtoReaderMap instancer_proto_readers_
void create_proto_collections(Main *bmain, Collection *parent_collection)
void process_armature_modifiers() const
void import_all_materials(struct Main *bmain)
bool have_material_import_hook(pxr::UsdStageRefPtr stage, const pxr::UsdShadeMaterial &usd_material, const USDImportParams &import_params, ReportList *reports)
blender::Set< pxr::SdfPath > UsdPathSet
static void decref(USDPrimReader *reader)
void build_material_map(const Main *bmain, blender::Map< std::string, Material * > &r_mat_map)
Material * find_existing_material(const pxr::SdfPath &usd_mat_path, const USDImportParams ¶ms, const blender::Map< std::string, Material * > &mat_map, const blender::Map< pxr::SdfPath, Material * > &usd_path_to_mat)
static void convert_to_z_up(pxr::UsdStageRefPtr stage, ImportSettings &settings)
static Collection * create_collection(Main *bmain, Collection *parent, const char *name)
static void set_instance_collection(USDInstanceReader *instance_reader, const blender::Map< pxr::SdfPath, Collection * > &proto_collection_map)
bool call_material_import_hooks(pxr::UsdStageRefPtr stage, Material *material, const pxr::UsdShadeMaterial &usd_material, const USDImportParams &import_params, ReportList *reports)
static void find_prefix_to_skip(pxr::UsdStageRefPtr stage, ImportSettings &settings)
@ USD_MTL_NAME_COLLISION_MAKE_UNIQUE
static void determine_blender_compat(pxr::UsdStageRefPtr stage, ImportSettings &settings)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
float conversion_mat[4][4]
bool blender_stage_version_prior_44