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_proxy = RNA_boolean_get(op->ptr, "import_proxy");
|
||||||
const bool import_render = RNA_boolean_get(op->ptr, "import_render");
|
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 import_usd_preview = RNA_boolean_get(op->ptr, "import_usd_preview");
|
||||||
const bool set_material_blend = RNA_boolean_get(op->ptr, "set_material_blend");
|
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,
|
.import_usd_preview = import_usd_preview,
|
||||||
.set_material_blend = set_material_blend,
|
.set_material_blend = set_material_blend,
|
||||||
.light_intensity_scale = light_intensity_scale,
|
.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);
|
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_guide", 0, NULL, ICON_NONE);
|
||||||
uiItemR(col, ptr, "import_proxy", 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_render", 0, NULL, ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "import_unbound_materials", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
col = uiLayoutColumnWithHeading(box, true, IFACE_("Options"));
|
col = uiLayoutColumnWithHeading(box, true, IFACE_("Options"));
|
||||||
uiItemR(col, ptr, "set_frame_range", 0, NULL, ICON_NONE);
|
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_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,
|
RNA_def_boolean(ot->srna,
|
||||||
"import_usd_preview",
|
"import_usd_preview",
|
||||||
false,
|
false,
|
||||||
|
@@ -225,6 +225,10 @@ static void import_startjob(void *customdata, short *stop, short *do_update, flo
|
|||||||
|
|
||||||
data->archive = archive;
|
data->archive = archive;
|
||||||
|
|
||||||
|
if (data->params.import_unbound_materials) {
|
||||||
|
archive->import_all_materials(data->bmain);
|
||||||
|
}
|
||||||
|
|
||||||
archive->collect_readers(data->bmain);
|
archive->collect_readers(data->bmain);
|
||||||
|
|
||||||
*data->do_update = true;
|
*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_id_tag_update(&data->scene->id, ID_RECALC_BASE_FLAGS);
|
||||||
DEG_relations_tag_update(data->bmain);
|
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);
|
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);
|
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
|
} // namespace blender::io::usd
|
||||||
|
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include <pxr/usd/usdShade/material.h>
|
#include <pxr/usd/usdShade/material.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
struct Main;
|
struct Main;
|
||||||
struct Material;
|
struct Material;
|
||||||
struct bNode;
|
struct bNode;
|
||||||
@@ -129,4 +131,30 @@ class USDMaterialReader {
|
|||||||
NodePlacementContext *r_ctx) const;
|
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
|
} // namespace blender::io::usd
|
||||||
|
@@ -48,20 +48,6 @@ static const pxr::TfToken normalsPrimvar("normals", pxr::TfToken::Immortal);
|
|||||||
} // namespace usdtokens
|
} // namespace usdtokens
|
||||||
|
|
||||||
namespace utils {
|
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)
|
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;
|
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,
|
static void assign_materials(Main *bmain,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
const std::map<pxr::SdfPath, int> &mat_index_map,
|
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 != mat_index_map.end();
|
||||||
++it) {
|
++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);
|
it->first, params, mat_name_to_mat, usd_path_to_mat_name);
|
||||||
if (!assigned_mat) {
|
if (!assigned_mat) {
|
||||||
/* Blender material doesn't exist, so create it now. */
|
/* 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();
|
material_indices.finish();
|
||||||
/* Build material name map if it's not built yet. */
|
/* Build material name map if it's not built yet. */
|
||||||
if (this->settings_->mat_name_to_mat.empty()) {
|
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,
|
utils::assign_materials(bmain,
|
||||||
object_,
|
object_,
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include "usd_reader_camera.h"
|
#include "usd_reader_camera.h"
|
||||||
#include "usd_reader_curve.h"
|
#include "usd_reader_curve.h"
|
||||||
#include "usd_reader_light.h"
|
#include "usd_reader_light.h"
|
||||||
|
#include "usd_reader_material.h"
|
||||||
#include "usd_reader_mesh.h"
|
#include "usd_reader_mesh.h"
|
||||||
#include "usd_reader_nurbs.h"
|
#include "usd_reader_nurbs.h"
|
||||||
#include "usd_reader_prim.h"
|
#include "usd_reader_prim.h"
|
||||||
@@ -12,12 +13,14 @@
|
|||||||
#include "usd_reader_xform.h"
|
#include "usd_reader_xform.h"
|
||||||
|
|
||||||
#include <pxr/pxr.h>
|
#include <pxr/pxr.h>
|
||||||
|
#include <pxr/usd/usd/primRange.h>
|
||||||
#include <pxr/usd/usdGeom/camera.h>
|
#include <pxr/usd/usdGeom/camera.h>
|
||||||
#include <pxr/usd/usdGeom/curves.h>
|
#include <pxr/usd/usdGeom/curves.h>
|
||||||
#include <pxr/usd/usdGeom/mesh.h>
|
#include <pxr/usd/usdGeom/mesh.h>
|
||||||
#include <pxr/usd/usdGeom/nurbsCurves.h>
|
#include <pxr/usd/usdGeom/nurbsCurves.h>
|
||||||
#include <pxr/usd/usdGeom/scope.h>
|
#include <pxr/usd/usdGeom/scope.h>
|
||||||
#include <pxr/usd/usdGeom/xform.h>
|
#include <pxr/usd/usdGeom/xform.h>
|
||||||
|
#include <pxr/usd/usdShade/material.h>
|
||||||
|
|
||||||
#if PXR_VERSION >= 2111
|
#if PXR_VERSION >= 2111
|
||||||
# include <pxr/usd/usdLux/boundableLightBase.h>
|
# include <pxr/usd/usdLux/boundableLightBase.h>
|
||||||
@@ -31,6 +34,10 @@
|
|||||||
#include "BLI_sort.hh"
|
#include "BLI_sort.hh"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "BKE_lib_id.h"
|
||||||
|
|
||||||
|
#include "DNA_material_types.h"
|
||||||
|
|
||||||
namespace blender::io::usd {
|
namespace blender::io::usd {
|
||||||
|
|
||||||
USDStageReader::USDStageReader(pxr::UsdStageRefPtr stage,
|
USDStageReader::USDStageReader(pxr::UsdStageRefPtr stage,
|
||||||
@@ -294,6 +301,72 @@ void USDStageReader::collect_readers(Main *bmain)
|
|||||||
collect_readers(bmain, root);
|
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()
|
void USDStageReader::clear_readers()
|
||||||
{
|
{
|
||||||
for (USDPrimReader *reader : readers_) {
|
for (USDPrimReader *reader : readers_) {
|
||||||
|
@@ -40,6 +40,10 @@ class USDStageReader {
|
|||||||
|
|
||||||
void collect_readers(struct Main *bmain);
|
void collect_readers(struct Main *bmain);
|
||||||
|
|
||||||
|
void import_all_materials(struct Main *bmain);
|
||||||
|
|
||||||
|
void fake_users_for_unbound_materials();
|
||||||
|
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
|
||||||
pxr::UsdStageRefPtr stage()
|
pxr::UsdStageRefPtr stage()
|
||||||
|
@@ -65,6 +65,7 @@ struct USDImportParams {
|
|||||||
bool set_material_blend;
|
bool set_material_blend;
|
||||||
float light_intensity_scale;
|
float light_intensity_scale;
|
||||||
eUSDMtlNameCollisionMode mtl_name_collision_mode;
|
eUSDMtlNameCollisionMode mtl_name_collision_mode;
|
||||||
|
bool import_unbound_materials;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The USD_export takes a as_background_job parameter, and returns a boolean.
|
/* The USD_export takes a as_background_job parameter, and returns a boolean.
|
||||||
|
Reference in New Issue
Block a user