Compare commits
4 Commits
temp-ui-cp
...
tmp_usd_im
Author | SHA1 | Date | |
---|---|---|---|
8703e17ace | |||
689e6a1be7 | |||
092fe1ef29 | |||
05e8eeda3c |
@@ -381,6 +381,8 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
|
||||
const bool import_proxy = RNA_boolean_get(op->ptr, "import_proxy");
|
||||
const bool import_render = RNA_boolean_get(op->ptr, "import_render");
|
||||
|
||||
const bool import_unbound_materials = RNA_boolean_get(op->ptr, "import_unbound_materials");
|
||||
|
||||
const bool import_usd_preview = RNA_boolean_get(op->ptr, "import_usd_preview");
|
||||
const bool set_material_blend = RNA_boolean_get(op->ptr, "set_material_blend");
|
||||
|
||||
@@ -427,7 +429,8 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
|
||||
.import_usd_preview = import_usd_preview,
|
||||
.set_material_blend = set_material_blend,
|
||||
.light_intensity_scale = light_intensity_scale,
|
||||
.mtl_name_collision_mode = mtl_name_collision_mode};
|
||||
.mtl_name_collision_mode = mtl_name_collision_mode,
|
||||
.import_unbound_materials = import_unbound_materials};
|
||||
|
||||
STRNCPY(params.prim_path_mask, prim_path_mask);
|
||||
|
||||
@@ -471,6 +474,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
uiItemR(col, ptr, "import_guide", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "import_proxy", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "import_render", 0, NULL, ICON_NONE);
|
||||
uiItemR(col, ptr, "import_unbound_materials", 0, NULL, ICON_NONE);
|
||||
|
||||
col = uiLayoutColumnWithHeading(box, true, IFACE_("Options"));
|
||||
uiItemR(col, ptr, "set_frame_range", 0, NULL, ICON_NONE);
|
||||
@@ -579,6 +583,12 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
|
||||
|
||||
RNA_def_boolean(ot->srna, "import_render", true, "Render", "Import final render geometry");
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"import_unbound_materials",
|
||||
false,
|
||||
"Unbound Materials",
|
||||
"Include materials not bound to any geometry");
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"import_usd_preview",
|
||||
false,
|
||||
|
@@ -225,6 +225,10 @@ static void import_startjob(void *customdata, short *stop, short *do_update, flo
|
||||
|
||||
data->archive = archive;
|
||||
|
||||
if (data->params.import_unbound_materials) {
|
||||
archive->import_all_materials(data->bmain);
|
||||
}
|
||||
|
||||
archive->collect_readers(data->bmain);
|
||||
|
||||
*data->do_update = true;
|
||||
@@ -355,6 +359,10 @@ static void import_endjob(void *customdata)
|
||||
|
||||
DEG_id_tag_update(&data->scene->id, ID_RECALC_BASE_FLAGS);
|
||||
DEG_relations_tag_update(data->bmain);
|
||||
|
||||
if (data->params.import_unbound_materials) {
|
||||
data->archive->fake_users_for_unbound_materials();
|
||||
}
|
||||
}
|
||||
|
||||
WM_set_locked_interface(data->wm, false);
|
||||
|
@@ -757,4 +757,50 @@ void USDMaterialReader::convert_usd_primvar_reader_float2(
|
||||
link_nodes(ntree, uv_map, "UV", dest_node, dest_socket_name);
|
||||
}
|
||||
|
||||
void build_material_map(const Main *bmain, std::map<std::string, Material *> *r_mat_map)
|
||||
{
|
||||
if (r_mat_map == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material *material = static_cast<Material *>(bmain->materials.first);
|
||||
|
||||
for (; material; material = static_cast<Material *>(material->id.next)) {
|
||||
(*r_mat_map)[pxr::TfMakeValidIdentifier(material->id.name + 2)] = material;
|
||||
}
|
||||
}
|
||||
|
||||
Material *find_existing_material(const pxr::SdfPath &usd_mat_path,
|
||||
const USDImportParams ¶ms,
|
||||
const std::map<std::string, Material *> &mat_map,
|
||||
const std::map<std::string, std::string> &usd_path_to_mat_name)
|
||||
{
|
||||
if (params.mtl_name_collision_mode == USD_MTL_NAME_COLLISION_MAKE_UNIQUE) {
|
||||
/* Check if we've already created the Blender material with a modified name. */
|
||||
std::map<std::string, std::string>::const_iterator path_to_name_iter =
|
||||
usd_path_to_mat_name.find(usd_mat_path.GetAsString());
|
||||
|
||||
if (path_to_name_iter != usd_path_to_mat_name.end()) {
|
||||
std::string mat_name = path_to_name_iter->second;
|
||||
std::map<std::string, Material *>::const_iterator mat_iter = mat_map.find(mat_name);
|
||||
if (mat_iter != mat_map.end()) {
|
||||
return mat_iter->second;
|
||||
}
|
||||
/* We can't find the Blender material which was previously created for this USD
|
||||
* material, which should never happen. */
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string mat_name = usd_mat_path.GetName();
|
||||
std::map<std::string, Material *>::const_iterator mat_iter = mat_map.find(mat_name);
|
||||
|
||||
if (mat_iter != mat_map.end()) {
|
||||
return mat_iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace blender::io::usd
|
||||
|
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <pxr/usd/usdShade/material.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
struct Main;
|
||||
struct Material;
|
||||
struct bNode;
|
||||
@@ -129,4 +131,30 @@ class USDMaterialReader {
|
||||
NodePlacementContext *r_ctx) const;
|
||||
};
|
||||
|
||||
/* Utility functions. */
|
||||
|
||||
/**
|
||||
* Returns a map containing all the Blender materials which allows a fast
|
||||
* lookup of the material object by name. Note that the material name key
|
||||
* might be modified to be a valid USD identifier, to match materials
|
||||
* imported from USD.
|
||||
*/
|
||||
void build_material_map(const Main *bmain, std::map<std::string, Material *> *r_mat_map);
|
||||
|
||||
/**
|
||||
* Returns an existing Blender material that corresponds to the USD material with the given path.
|
||||
* Returns null if no such material exists.
|
||||
*
|
||||
* \param mat_map Map a Blender material name to the material object.
|
||||
* \param usd_path_to_mat_name Map a USD material path to the imported Blender material name.
|
||||
*
|
||||
* The usd_path_to_mat_name is needed to determine the name of the Blender
|
||||
* material imported from a USD path in the case when a unique name was generated
|
||||
* for the material due to a name collision.
|
||||
*/
|
||||
Material *find_existing_material(const pxr::SdfPath &usd_mat_path,
|
||||
const USDImportParams ¶ms,
|
||||
const std::map<std::string, Material *> &mat_map,
|
||||
const std::map<std::string, std::string> &usd_path_to_mat_name);
|
||||
|
||||
} // namespace blender::io::usd
|
||||
|
@@ -48,20 +48,6 @@ static const pxr::TfToken normalsPrimvar("normals", pxr::TfToken::Immortal);
|
||||
} // namespace usdtokens
|
||||
|
||||
namespace utils {
|
||||
/* Very similar to #blender::io::alembic::utils. */
|
||||
static void build_mat_map(const Main *bmain, std::map<std::string, Material *> *r_mat_map)
|
||||
{
|
||||
if (r_mat_map == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material *material = static_cast<Material *>(bmain->materials.first);
|
||||
|
||||
for (; material; material = static_cast<Material *>(material->id.next)) {
|
||||
/* We have to do this because the stored material name is coming directly from USD. */
|
||||
(*r_mat_map)[pxr::TfMakeValidIdentifier(material->id.name + 2)] = material;
|
||||
}
|
||||
}
|
||||
|
||||
static pxr::UsdShadeMaterial compute_bound_material(const pxr::UsdPrim &prim)
|
||||
{
|
||||
@@ -83,42 +69,6 @@ static pxr::UsdShadeMaterial compute_bound_material(const pxr::UsdPrim &prim)
|
||||
return mtl;
|
||||
}
|
||||
|
||||
/* Returns an existing Blender material that corresponds to the USD material with the given path.
|
||||
* Returns null if no such material exists. */
|
||||
static Material *find_existing_material(
|
||||
const pxr::SdfPath &usd_mat_path,
|
||||
const USDImportParams ¶ms,
|
||||
const std::map<std::string, Material *> &mat_map,
|
||||
const std::map<std::string, std::string> &usd_path_to_mat_name)
|
||||
{
|
||||
if (params.mtl_name_collision_mode == USD_MTL_NAME_COLLISION_MAKE_UNIQUE) {
|
||||
/* Check if we've already created the Blender material with a modified name. */
|
||||
std::map<std::string, std::string>::const_iterator path_to_name_iter =
|
||||
usd_path_to_mat_name.find(usd_mat_path.GetAsString());
|
||||
|
||||
if (path_to_name_iter != usd_path_to_mat_name.end()) {
|
||||
std::string mat_name = path_to_name_iter->second;
|
||||
std::map<std::string, Material *>::const_iterator mat_iter = mat_map.find(mat_name);
|
||||
if (mat_iter != mat_map.end()) {
|
||||
return mat_iter->second;
|
||||
}
|
||||
/* We can't find the Blender material which was previously created for this USD
|
||||
* material, which should never happen. */
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string mat_name = usd_mat_path.GetName();
|
||||
std::map<std::string, Material *>::const_iterator mat_iter = mat_map.find(mat_name);
|
||||
|
||||
if (mat_iter != mat_map.end()) {
|
||||
return mat_iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void assign_materials(Main *bmain,
|
||||
Object *ob,
|
||||
const std::map<pxr::SdfPath, int> &mat_index_map,
|
||||
@@ -141,7 +91,7 @@ static void assign_materials(Main *bmain,
|
||||
it != mat_index_map.end();
|
||||
++it) {
|
||||
|
||||
Material *assigned_mat = find_existing_material(
|
||||
Material *assigned_mat = blender::io::usd::find_existing_material(
|
||||
it->first, params, mat_name_to_mat, usd_path_to_mat_name);
|
||||
if (!assigned_mat) {
|
||||
/* Blender material doesn't exist, so create it now. */
|
||||
@@ -810,7 +760,7 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
|
||||
material_indices.finish();
|
||||
/* Build material name map if it's not built yet. */
|
||||
if (this->settings_->mat_name_to_mat.empty()) {
|
||||
utils::build_mat_map(bmain, &this->settings_->mat_name_to_mat);
|
||||
build_material_map(bmain, &this->settings_->mat_name_to_mat);
|
||||
}
|
||||
utils::assign_materials(bmain,
|
||||
object_,
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include "usd_reader_camera.h"
|
||||
#include "usd_reader_curve.h"
|
||||
#include "usd_reader_light.h"
|
||||
#include "usd_reader_material.h"
|
||||
#include "usd_reader_mesh.h"
|
||||
#include "usd_reader_nurbs.h"
|
||||
#include "usd_reader_prim.h"
|
||||
@@ -12,12 +13,14 @@
|
||||
#include "usd_reader_xform.h"
|
||||
|
||||
#include <pxr/pxr.h>
|
||||
#include <pxr/usd/usd/primRange.h>
|
||||
#include <pxr/usd/usdGeom/camera.h>
|
||||
#include <pxr/usd/usdGeom/curves.h>
|
||||
#include <pxr/usd/usdGeom/mesh.h>
|
||||
#include <pxr/usd/usdGeom/nurbsCurves.h>
|
||||
#include <pxr/usd/usdGeom/scope.h>
|
||||
#include <pxr/usd/usdGeom/xform.h>
|
||||
#include <pxr/usd/usdShade/material.h>
|
||||
|
||||
#if PXR_VERSION >= 2111
|
||||
# include <pxr/usd/usdLux/boundableLightBase.h>
|
||||
@@ -31,6 +34,10 @@
|
||||
#include "BLI_sort.hh"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BKE_lib_id.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
USDStageReader::USDStageReader(pxr::UsdStageRefPtr stage,
|
||||
@@ -294,6 +301,72 @@ void USDStageReader::collect_readers(Main *bmain)
|
||||
collect_readers(bmain, root);
|
||||
}
|
||||
|
||||
/* Iterate through stage and import each material prim. */
|
||||
void USDStageReader::import_all_materials(Main *bmain)
|
||||
{
|
||||
if (!valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build the material name map if it's not built yet. */
|
||||
if (settings_.mat_name_to_mat.empty()) {
|
||||
build_material_map(bmain, &settings_.mat_name_to_mat);
|
||||
}
|
||||
|
||||
USDMaterialReader mtl_reader(params_, bmain);
|
||||
|
||||
PXR_NS::UsdPrimRange range = stage_->TraverseAll();
|
||||
for (const auto &prim : range) {
|
||||
if (prim.IsA<pxr::UsdShadeMaterial>()) {
|
||||
pxr::UsdShadeMaterial usd_mtl(prim);
|
||||
if (!usd_mtl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Material *blend_mtl = blender::io::usd::find_existing_material(
|
||||
prim.GetPath(), params_, settings_.mat_name_to_mat, settings_.usd_path_to_mat_name);
|
||||
|
||||
if (blend_mtl) {
|
||||
/* The material already exists. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the material now. */
|
||||
blend_mtl = mtl_reader.add_material(usd_mtl);
|
||||
if (blend_mtl) {
|
||||
if (params_.mtl_name_collision_mode == USD_MTL_NAME_COLLISION_MAKE_UNIQUE) {
|
||||
/* Record the name of the Blender material we created for the USD material
|
||||
* with the given path, so we don't import the material again if the
|
||||
* material is shared. */
|
||||
const std::string mtl_name = pxr::TfMakeValidIdentifier(blend_mtl->id.name + 2);
|
||||
settings_.mat_name_to_mat[mtl_name] = blend_mtl;
|
||||
|
||||
settings_.usd_path_to_mat_name[prim.GetPath().GetAsString()] = mtl_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add fake users for any imported materials with
|
||||
* no users. This is typically required for unbound
|
||||
* materials. */
|
||||
void USDStageReader::fake_users_for_unbound_materials()
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator mat_name_it =
|
||||
settings_.usd_path_to_mat_name.begin();
|
||||
for (; mat_name_it != settings_.usd_path_to_mat_name.end(); ++mat_name_it) {
|
||||
std::map<std::string, Material *>::iterator mat_it = settings_.mat_name_to_mat.find(
|
||||
mat_name_it->second);
|
||||
if (mat_it != settings_.mat_name_to_mat.end()) {
|
||||
Material *mat = mat_it->second;
|
||||
if (mat->id.us == 0) {
|
||||
id_fake_user_set(&mat->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void USDStageReader::clear_readers()
|
||||
{
|
||||
for (USDPrimReader *reader : readers_) {
|
||||
|
@@ -40,6 +40,10 @@ class USDStageReader {
|
||||
|
||||
void collect_readers(struct Main *bmain);
|
||||
|
||||
void import_all_materials(struct Main *bmain);
|
||||
|
||||
void fake_users_for_unbound_materials();
|
||||
|
||||
bool valid() const;
|
||||
|
||||
pxr::UsdStageRefPtr stage()
|
||||
|
@@ -65,6 +65,7 @@ struct USDImportParams {
|
||||
bool set_material_blend;
|
||||
float light_intensity_scale;
|
||||
eUSDMtlNameCollisionMode mtl_name_collision_mode;
|
||||
bool import_unbound_materials;
|
||||
};
|
||||
|
||||
/* The USD_export takes a as_background_job parameter, and returns a boolean.
|
||||
|
Reference in New Issue
Block a user