Cleanup: Use blender C++ containers for USD

Use Vector, Map, and Set as appropriate.

The remaining uses of the std:: types come from USD APIs.

Pull Request: https://projects.blender.org/blender/blender/pulls/116801
This commit is contained in:
Jesse Yurkovich 2024-01-05 20:35:55 +01:00 committed by Jesse Yurkovich
parent 0a8129e0cf
commit b0db5363fa
12 changed files with 190 additions and 221 deletions

@ -16,9 +16,6 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "WM_api.hh"
#include "WM_types.hh"
static const char UDIM_PATTERN[] = "<UDIM>";
static const char UDIM_PATTERN2[] = "%3CUDIM%3E";
@ -39,16 +36,14 @@ namespace blender::io::usd {
*/
static std::pair<std::string, std::string> split_udim_pattern(const std::string &path)
{
static const std::vector<std::string> patterns = {UDIM_PATTERN, UDIM_PATTERN2};
for (const std::string &pattern : patterns) {
for (const std::string &pattern : {UDIM_PATTERN, UDIM_PATTERN2}) {
const std::string::size_type pos = path.find(pattern);
if (pos != std::string::npos) {
return {path.substr(0, pos), path.substr(pos + pattern.size())};
}
}
return {std::string(), std::string()};
return {};
}
/* Return the asset file base name, with special handling of

@ -255,9 +255,8 @@ static void import_startjob(void *customdata, wmJobWorkerStatus *worker_status)
std::string prim_path_mask(data->params.prim_path_mask);
pxr::UsdStagePopulationMask pop_mask;
if (!prim_path_mask.empty()) {
const std::vector<std::string> mask_tokens = pxr::TfStringTokenize(prim_path_mask, ",;");
for (const std::string &tok : mask_tokens) {
pxr::SdfPath prim_path(tok);
for (const std::string &mask_token : pxr::TfStringTokenize(prim_path_mask, ",;")) {
pxr::SdfPath prim_path(mask_token);
if (!prim_path.IsEmpty()) {
pop_mask.Add(prim_path);
}

@ -16,6 +16,7 @@
#include "BKE_report.h"
#include "BLI_fileops.h"
#include "BLI_map.hh"
#include "BLI_math_vector.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
@ -31,7 +32,6 @@
#include <pxr/usd/usdShade/shader.h>
#include <iostream>
#include <vector>
namespace usdtokens {
@ -112,10 +112,7 @@ using blender::io::usd::ShaderToNodeMap;
static bNode *get_cached_node(const ShaderToNodeMap &node_cache,
const pxr::UsdShadeShader &usd_shader)
{
if (bNode *const *node_ptr = node_cache.lookup_ptr(usd_shader.GetPath().GetAsString())) {
return *node_ptr;
}
return nullptr;
return node_cache.lookup_default(usd_shader.GetPath().GetAsString(), nullptr);
}
/* Cache the Blender node translated from the given USD shader
@ -431,7 +428,7 @@ void compute_node_loc(const int column, float *r_locx, float *r_locy, NodePlacem
(*r_locx) = r_ctx->origx - column * r_ctx->horizontal_step;
if (column >= r_ctx->column_offsets.size()) {
r_ctx->column_offsets.push_back(0.0f);
r_ctx->column_offsets.append(0.0f);
}
(*r_locy) = r_ctx->origy - r_ctx->column_offsets[column];
@ -1088,45 +1085,35 @@ void USDMaterialReader::convert_usd_primvar_reader_float2(const pxr::UsdShadeSha
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)
void build_material_map(const Main *bmain, blender::Map<std::string, Material *> *r_mat_map)
{
BLI_assert_msg(r_mat_map, "...");
LISTBASE_FOREACH (Material *, material, &bmain->materials) {
std::string usd_name = pxr::TfMakeValidIdentifier(material->id.name + 2);
(*r_mat_map)[usd_name] = material;
r_mat_map->lookup_or_add_default(usd_name) = material;
}
}
Material *find_existing_material(const pxr::SdfPath &usd_mat_path,
const USDImportParams &params,
const std::map<std::string, Material *> &mat_map,
const std::map<std::string, std::string> &usd_path_to_mat_name)
Material *find_existing_material(
const pxr::SdfPath &usd_mat_path,
const USDImportParams &params,
const blender::Map<std::string, Material *> &mat_map,
const blender::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()) {
const std::string *mat_name = usd_path_to_mat_name.lookup_ptr(usd_mat_path.GetAsString());
if (mat_name == nullptr) {
return nullptr;
}
std::string mat_name = path_to_name_iter->second;
std::map<std::string, Material *>::const_iterator mat_iter = mat_map.find(mat_name);
BLI_assert_msg(mat_iter != mat_map.end(),
"Previously created material cannot be found any more");
return mat_iter->second;
Material *mat = mat_map.lookup_default(*mat_name, nullptr);
BLI_assert_msg(mat != nullptr, "Previously created material cannot be found any more");
return mat;
}
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 nullptr;
}
return mat_iter->second;
return mat_map.lookup_default(usd_mat_path.GetName(), nullptr);
}
} // namespace blender::io::usd

@ -8,6 +8,7 @@
#include "WM_types.hh"
#include "BLI_map.hh"
#include "BLI_vector.hh"
#include <pxr/usd/usdShade/material.h>
@ -29,7 +30,7 @@ using ShaderToNodeMap = blender::Map<std::string, bNode *>;
struct NodePlacementContext {
float origx;
float origy;
std::vector<float> column_offsets;
blender::Vector<float, 0> column_offsets;
const float horizontal_step;
const float vertical_step;
@ -170,7 +171,7 @@ class USDMaterialReader {
* might be modified to be a valid USD identifier, to match material
* names in the imported USD.
*/
void build_material_map(const Main *bmain, std::map<std::string, Material *> *r_mat_map);
void build_material_map(const Main *bmain, blender::Map<std::string, Material *> *r_mat_map);
/**
* Returns an existing Blender material that corresponds to the USD material with the given path.
@ -185,9 +186,10 @@ void build_material_map(const Main *bmain, std::map<std::string, Material *> *r_
* 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 &params,
const std::map<std::string, Material *> &mat_map,
const std::map<std::string, std::string> &usd_path_to_mat_name);
Material *find_existing_material(
const pxr::SdfPath &usd_mat_path,
const USDImportParams &params,
const blender::Map<std::string, Material *> &mat_map,
const blender::Map<std::string, std::string> &usd_path_to_mat_name);
} // namespace blender::io::usd

@ -6,6 +6,7 @@
* NVIDIA Corporation. All rights reserved. */
#include "usd_reader_mesh.h"
#include "usd_hash_types.h"
#include "usd_reader_material.h"
#include "usd_skel_convert.h"
@ -17,14 +18,12 @@
#include "BKE_object.hh"
#include "BKE_report.h"
#include "BLI_map.hh"
#include "BLI_math_color.hh"
#include "BLI_math_geom.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "usd_hash_types.h"
#include "DNA_customdata_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
@ -80,11 +79,11 @@ static pxr::UsdShadeMaterial compute_bound_material(const pxr::UsdPrim &prim)
static void assign_materials(Main *bmain,
Object *ob,
const std::map<pxr::SdfPath, int> &mat_index_map,
const blender::Map<pxr::SdfPath, int> &mat_index_map,
const USDImportParams &params,
pxr::UsdStageRefPtr stage,
std::map<std::string, Material *> &mat_name_to_mat,
std::map<std::string, std::string> &usd_path_to_mat_name)
blender::Map<std::string, Material *> &mat_name_to_mat,
blender::Map<std::string, std::string> &usd_path_to_mat_name)
{
if (!(stage && bmain && ob)) {
return;
@ -96,22 +95,18 @@ static void assign_materials(Main *bmain,
blender::io::usd::USDMaterialReader mat_reader(params, bmain);
for (std::map<pxr::SdfPath, int>::const_iterator it = mat_index_map.begin();
it != mat_index_map.end();
++it)
{
for (const auto item : mat_index_map.items()) {
Material *assigned_mat = blender::io::usd::find_existing_material(
it->first, params, mat_name_to_mat, usd_path_to_mat_name);
item.key, params, mat_name_to_mat, usd_path_to_mat_name);
if (!assigned_mat) {
/* Blender material doesn't exist, so create it now. */
/* Look up the USD material. */
pxr::UsdPrim prim = stage->GetPrimAtPath(it->first);
pxr::UsdPrim prim = stage->GetPrimAtPath(item.key);
pxr::UsdShadeMaterial usd_mat(prim);
if (!usd_mat) {
std::cout << "WARNING: Couldn't construct USD material from prim " << it->first
std::cout << "WARNING: Couldn't construct USD material from prim " << item.key
<< std::endl;
continue;
}
@ -120,27 +115,27 @@ static void assign_materials(Main *bmain,
assigned_mat = mat_reader.add_material(usd_mat);
if (!assigned_mat) {
std::cout << "WARNING: Couldn't create Blender material from USD material " << it->first
std::cout << "WARNING: Couldn't create Blender material from USD material " << item.key
<< std::endl;
continue;
}
const std::string mat_name = pxr::TfMakeValidIdentifier(assigned_mat->id.name + 2);
mat_name_to_mat[mat_name] = assigned_mat;
mat_name_to_mat.lookup_or_add_default(mat_name) = assigned_mat;
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. */
usd_path_to_mat_name[it->first.GetAsString()] = mat_name;
usd_path_to_mat_name.lookup_or_add_default(item.key.GetAsString()) = mat_name;
}
}
if (assigned_mat) {
BKE_object_material_assign_single_obdata(bmain, ob, assigned_mat, it->second);
BKE_object_material_assign_single_obdata(bmain, ob, assigned_mat, item.value);
}
else {
/* This shouldn't happen. */
std::cout << "WARNING: Couldn't assign material " << it->first << std::endl;
std::cout << "WARNING: Couldn't assign material " << item.key << std::endl;
}
}
if (ob->totcol > 0) {
@ -919,9 +914,8 @@ void USDMeshReader::read_custom_data(const ImportSettings *settings,
/* To avoid unnecessarily reloading static primvars during animation,
* early out if not first load and this primvar isn't animated. */
if (!new_mesh && primvar_varying_map_.find(name) != primvar_varying_map_.end() &&
!primvar_varying_map_.at(name))
{
const bool is_time_varying = primvar_varying_map_.lookup_default(name, false);
if (!new_mesh && !is_time_varying) {
continue;
}
@ -975,9 +969,9 @@ void USDMeshReader::read_custom_data(const ImportSettings *settings,
}
/* Record whether the primvar attribute might be time varying. */
if (primvar_varying_map_.find(name) == primvar_varying_map_.end()) {
if (!primvar_varying_map_.contains(name)) {
bool might_be_time_varying = pv.ValueMightBeTimeVarying();
primvar_varying_map_.insert(std::make_pair(name, might_be_time_varying));
primvar_varying_map_.add(name, might_be_time_varying);
if (might_be_time_varying) {
is_time_varying_ = true;
}
@ -1001,7 +995,7 @@ void USDMeshReader::read_custom_data(const ImportSettings *settings,
void USDMeshReader::assign_facesets_to_material_indices(double motionSampleTime,
MutableSpan<int> material_indices,
std::map<pxr::SdfPath, int> *r_mat_map)
blender::Map<pxr::SdfPath, int> *r_mat_map)
{
if (r_mat_map == nullptr) {
return;
@ -1031,30 +1025,26 @@ void USDMeshReader::assign_facesets_to_material_indices(double motionSampleTime,
continue;
}
if (r_mat_map->find(subset_mtl_path) == r_mat_map->end()) {
(*r_mat_map)[subset_mtl_path] = 1 + current_mat++;
}
const int mat_idx = (*r_mat_map)[subset_mtl_path] - 1;
const int mat_idx = r_mat_map->lookup_or_add(subset_mtl_path, 1 + current_mat++);
pxr::UsdAttribute indicesAttribute = subset.GetIndicesAttr();
pxr::VtIntArray indices;
indicesAttribute.Get(&indices, motionSampleTime);
for (const int i : indices) {
material_indices[i] = mat_idx;
material_indices[i] = mat_idx - 1;
}
}
}
if (r_mat_map->empty()) {
if (r_mat_map->is_empty()) {
pxr::UsdShadeMaterial mtl = utils::compute_bound_material(prim_);
if (mtl) {
pxr::SdfPath mtl_path = mtl.GetPath();
if (!mtl_path.IsEmpty()) {
r_mat_map->insert(std::make_pair(mtl.GetPath(), 1));
r_mat_map->add(mtl.GetPath(), 1);
}
}
}
@ -1066,7 +1056,7 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
return;
}
std::map<pxr::SdfPath, int> mat_map;
blender::Map<pxr::SdfPath, int> mat_map;
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
@ -1074,7 +1064,7 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
this->assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
material_indices.finish();
/* 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.is_empty()) {
build_material_map(bmain, &this->settings_->mat_name_to_mat);
}
utils::assign_materials(bmain,
@ -1122,7 +1112,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
* the material slots that were created when the object was loaded from
* USD are still valid now. */
if (active_mesh->faces_num != 0 && import_params_.import_materials) {
std::map<pxr::SdfPath, int> mat_map;
blender::Map<pxr::SdfPath, int> mat_map;
bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices =
attributes.lookup_or_add_for_write_span<int>("material_index", bke::AttrDomain::Face);

@ -5,6 +5,7 @@
* Modifications Copyright 2021 Tangent Animation and. NVIDIA Corporation. All rights reserved. */
#pragma once
#include "BLI_map.hh"
#include "BLI_span.hh"
#include "usd.h"
@ -18,8 +19,8 @@ class USDMeshReader : public USDGeomReader {
private:
pxr::UsdGeomMesh mesh_prim_;
std::unordered_map<std::string, pxr::TfToken> uv_token_map_;
std::map<const pxr::TfToken, bool> primvar_varying_map_;
blender::Map<std::string, pxr::TfToken> uv_token_map_;
blender::Map<const pxr::TfToken, bool> primvar_varying_map_;
/* TODO(makowalski): Is it the best strategy to cache the
* mesh geometry in the following members? It appears these
@ -73,7 +74,7 @@ class USDMeshReader : public USDGeomReader {
void readFaceSetsSample(Main *bmain, Mesh *mesh, double motionSampleTime);
void assign_facesets_to_material_indices(double motionSampleTime,
MutableSpan<int> material_indices,
std::map<pxr::SdfPath, int> *r_mat_map);
blender::Map<pxr::SdfPath, int> *r_mat_map);
void read_mpolys(Mesh *mesh);
void read_vertex_creases(Mesh *mesh, double motionSampleTime);

@ -9,12 +9,13 @@
#include "usd.h"
#include "BLI_map.hh"
#include "WM_types.hh"
#include <pxr/usd/sdf/path.h>
#include <pxr/usd/usd/prim.h>
#include <map>
#include <string>
struct CacheFile;
@ -50,11 +51,11 @@ struct ImportSettings {
* This field is mutable because it is used to keep track
* of what the importer is doing. This is necessary even
* when all the other import settings are to remain const. */
mutable std::map<std::string, std::string> usd_path_to_mat_name;
mutable blender::Map<std::string, std::string> usd_path_to_mat_name;
/* Map a material name to Blender material.
* This map is updated by readers during stage traversal,
* and is mutable similar to the map above. */
mutable std::map<std::string, Material *> mat_name_to_mat;
mutable blender::Map<std::string, Material *> mat_name_to_mat;
/* We use the stage metersPerUnit to convert camera properties from USD scene units to the
* correct millimeter scale that Blender uses for camera parameters. */

@ -38,8 +38,7 @@
# include <pxr/usd/usdLux/light.h>
#endif
#include <iostream>
#include "BLI_map.hh"
#include "BLI_sort.hh"
#include "BLI_string.h"
@ -78,7 +77,7 @@ static Collection *create_collection(Main *bmain, Collection *parent, const char
*/
static void set_instance_collection(
USDInstanceReader *instance_reader,
const std::map<pxr::SdfPath, Collection *> &proto_collection_map)
const blender::Map<pxr::SdfPath, Collection *> &proto_collection_map)
{
if (!instance_reader) {
return;
@ -86,10 +85,9 @@ static void set_instance_collection(
pxr::SdfPath proto_path = instance_reader->proto_path();
std::map<pxr::SdfPath, Collection *>::const_iterator it = proto_collection_map.find(proto_path);
if (it != proto_collection_map.end()) {
instance_reader->set_instance_collection(it->second);
Collection *collection = proto_collection_map.lookup_default(proto_path, nullptr);
if (collection != nullptr) {
instance_reader->set_instance_collection(collection);
}
else {
CLOG_WARN(
@ -304,7 +302,7 @@ static bool merge_with_parent(USDPrimReader *reader)
USDPrimReader *USDStageReader::collect_readers(Main *bmain,
const pxr::UsdPrim &prim,
std::vector<USDPrimReader *> &r_readers)
blender::Vector<USDPrimReader *> &r_readers)
{
if (prim.IsA<pxr::UsdGeomImageable>()) {
pxr::UsdGeomImageable imageable(prim);
@ -326,11 +324,11 @@ USDPrimReader *USDStageReader::collect_readers(Main *bmain,
pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_predicate);
std::vector<USDPrimReader *> child_readers;
blender::Vector<USDPrimReader *> child_readers;
for (const auto &childPrim : children) {
if (USDPrimReader *child_reader = collect_readers(bmain, childPrim, r_readers)) {
child_readers.push_back(child_reader);
child_readers.append(child_reader);
}
}
@ -349,7 +347,7 @@ USDPrimReader *USDStageReader::collect_readers(Main *bmain,
/* Check if we can merge an Xform with its child prim. */
if (child_readers.size() == 1) {
USDPrimReader *child_reader = child_readers.front();
USDPrimReader *child_reader = child_readers.first();
if (merge_with_parent(child_reader)) {
return child_reader;
@ -359,7 +357,7 @@ USDPrimReader *USDStageReader::collect_readers(Main *bmain,
if (prim.IsA<pxr::UsdShadeMaterial>()) {
/* Record material path for later processing, if needed,
* e.g., when importing all materials. */
material_paths_.push_back(prim.GetPath().GetAsString());
material_paths_.append(prim.GetPath().GetAsString());
/* We don't create readers for materials, so return early. */
return nullptr;
@ -371,7 +369,7 @@ USDPrimReader *USDStageReader::collect_readers(Main *bmain,
return nullptr;
}
r_readers.push_back(reader);
r_readers.append(reader);
reader->incref();
/* Set each child reader's parent. */
@ -402,12 +400,12 @@ void USDStageReader::collect_readers(Main *bmain)
std::vector<pxr::UsdPrim> protos = stage_->GetPrototypes();
for (const pxr::UsdPrim &proto_prim : protos) {
std::vector<USDPrimReader *> proto_readers;
blender::Vector<USDPrimReader *> proto_readers;
collect_readers(bmain, proto_prim, proto_readers);
proto_readers_.insert(std::make_pair(proto_prim.GetPath(), proto_readers));
proto_readers_.add(proto_prim.GetPath(), proto_readers);
for (USDPrimReader *reader : proto_readers) {
readers_.push_back(reader);
readers_.append(reader);
reader->incref();
}
}
@ -419,10 +417,10 @@ void USDStageReader::process_armature_modifiers() const
/* Iterate over the skeleton readers to create the
* armature object map, which maps a USD skeleton prim
* path to the corresponding armature object. */
std::map<std::string, Object *> usd_path_to_armature;
blender::Map<std::string, Object *> usd_path_to_armature;
for (const USDPrimReader *reader : readers_) {
if (dynamic_cast<const USDSkeletonReader *>(reader) && reader->object()) {
usd_path_to_armature.insert(std::make_pair(reader->prim_path(), reader->object()));
usd_path_to_armature.add(reader->prim_path(), reader->object());
}
}
@ -445,15 +443,15 @@ void USDStageReader::process_armature_modifiers() const
/* Assign the armature based on the bound USD skeleton path of the skinned mesh. */
std::string skel_path = mesh_reader->get_skeleton_path();
std::map<std::string, Object *>::const_iterator it = usd_path_to_armature.find(skel_path);
if (it == usd_path_to_armature.end()) {
Object *object = usd_path_to_armature.lookup_default(skel_path, nullptr);
if (object == nullptr) {
BKE_reportf(reports(),
RPT_WARNING,
"%s: Couldn't find armature object corresponding to USD skeleton %s",
__func__,
skel_path.c_str());
}
amd->object = it->second;
amd->object = object;
}
}
@ -462,7 +460,7 @@ void USDStageReader::import_all_materials(Main *bmain)
BLI_assert(valid());
/* Build the material name map if it's not built yet. */
if (settings_.mat_name_to_mat.empty()) {
if (settings_.mat_name_to_mat.is_empty()) {
build_material_map(bmain, &settings_.mat_name_to_mat);
}
@ -488,13 +486,14 @@ void USDStageReader::import_all_materials(Main *bmain)
BLI_assert_msg(new_mtl, "Failed to create material");
const std::string mtl_name = pxr::TfMakeValidIdentifier(new_mtl->id.name + 2);
settings_.mat_name_to_mat[mtl_name] = new_mtl;
settings_.mat_name_to_mat.lookup_or_add_default(mtl_name) = new_mtl;
if (params_.mtl_name_collision_mode == USD_MTL_NAME_COLLISION_MAKE_UNIQUE) {
/* Record the unique name of the Blender material we created for the USD material
* with the given path, so we don't import the material again when assigning
* materials to objects elsewhere in the code. */
settings_.usd_path_to_mat_name[prim.GetPath().GetAsString()] = mtl_name;
settings_.usd_path_to_mat_name.lookup_or_add_default(
prim.GetPath().GetAsString()) = mtl_name;
}
}
}
@ -503,18 +502,12 @@ void USDStageReader::fake_users_for_unused_materials()
{
/* Iterate over the imported materials and set a fake user for any unused
* materials. */
for (const std::pair<const std::string, std::string> &path_mat_pair :
settings_.usd_path_to_mat_name)
{
std::map<std::string, Material *>::iterator mat_it = settings_.mat_name_to_mat.find(
path_mat_pair.second);
if (mat_it == settings_.mat_name_to_mat.end()) {
for (const auto path_mat_pair : settings_.usd_path_to_mat_name.items()) {
Material *mat = settings_.mat_name_to_mat.lookup_default(path_mat_pair.value, nullptr);
if (mat == nullptr) {
continue;
}
Material *mat = mat_it->second;
if (mat->id.us == 0) {
id_fake_user_set(&mat->id);
}
@ -540,9 +533,9 @@ void USDStageReader::clear_readers()
void USDStageReader::clear_proto_readers()
{
for (auto &pair : proto_readers_) {
for (const auto item : proto_readers_.items()) {
for (USDPrimReader *reader : pair.second) {
for (USDPrimReader *reader : item.value) {
if (!reader) {
continue;
@ -571,7 +564,7 @@ void USDStageReader::sort_readers()
void USDStageReader::create_proto_collections(Main *bmain, Collection *parent_collection)
{
if (proto_readers_.empty()) {
if (proto_readers_.is_empty()) {
return;
}
@ -585,12 +578,12 @@ void USDStageReader::create_proto_collections(Main *bmain, Collection *parent_co
}
}
std::map<pxr::SdfPath, Collection *> proto_collection_map;
blender::Map<pxr::SdfPath, Collection *> proto_collection_map;
for (const auto &pair : proto_readers_) {
for (const pxr::SdfPath &path : proto_readers_.keys()) {
Collection *proto_collection = create_collection(bmain, all_protos_collection, "proto");
proto_collection_map.insert(std::make_pair(pair.first, proto_collection));
proto_collection_map.add(path, proto_collection);
}
/* Set the instance collections on the readers, including the prototype
@ -603,30 +596,23 @@ void USDStageReader::create_proto_collections(Main *bmain, Collection *parent_co
}
/* Add the prototype objects to the collections. */
for (const auto &pair : proto_readers_) {
std::map<pxr::SdfPath, Collection *>::const_iterator it = proto_collection_map.find(
pair.first);
if (it == proto_collection_map.end()) {
std::cerr << "WARNING: Couldn't find collection when adding objects for prototype "
<< pair.first << std::endl;
for (const auto &item : proto_readers_.items()) {
Collection *collection = proto_collection_map.lookup_default(item.key, nullptr);
if (collection == nullptr) {
CLOG_WARN(&LOG,
"Couldn't find collection when adding objects for prototype %s",
pair.first.GetAsString().c_str());
item.key.GetAsString().c_str());
continue;
}
for (USDPrimReader *reader : pair.second) {
for (USDPrimReader *reader : item.value) {
Object *ob = reader->object();
if (!ob) {
continue;
}
Collection *coll = it->second;
BKE_collection_object_add(bmain, coll, ob);
BKE_collection_object_add(bmain, collection, ob);
}
}
}

@ -8,12 +8,13 @@ struct Main;
#include "WM_types.hh"
#include "usd.h"
#include "usd_hash_types.h"
#include "usd_reader_prim.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usdGeom/imageable.h>
#include <vector>
#include <string>
struct ImportSettings;
@ -23,7 +24,7 @@ namespace blender::io::usd {
* Map a USD prototype prim path to the list of readers that convert
* the prototype data.
*/
using ProtoReaderMap = std::map<pxr::SdfPath, std::vector<USDPrimReader *>>;
using ProtoReaderMap = blender::Map<pxr::SdfPath, blender::Vector<USDPrimReader *>>;
class USDStageReader {
@ -32,11 +33,11 @@ class USDStageReader {
USDImportParams params_;
ImportSettings settings_;
std::vector<USDPrimReader *> readers_;
blender::Vector<USDPrimReader *> readers_;
/* USD material prim paths encountered during stage
* traversal, for importing unused materials. */
std::vector<std::string> material_paths_;
blender::Vector<std::string> material_paths_;
/* Readers for scenegraph instance prototypes. */
ProtoReaderMap proto_readers_;
@ -98,7 +99,7 @@ class USDStageReader {
void clear_proto_readers();
const std::vector<USDPrimReader *> &readers() const
const blender::Vector<USDPrimReader *> &readers() const
{
return readers_;
};
@ -113,7 +114,7 @@ class USDStageReader {
private:
USDPrimReader *collect_readers(Main *bmain,
const pxr::UsdPrim &prim,
std::vector<USDPrimReader *> &r_readers);
blender::Vector<USDPrimReader *> &r_readers);
/**
* Returns true if the given prim should be included in the

@ -39,9 +39,12 @@
#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BLI_map.hh"
#include "BLI_math_vector.h"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_vector.hh"
#include "ED_armature.hh"
#include "ED_keyframing.hh"
@ -120,7 +123,7 @@ void add_bezt(FCurve *fcu,
void import_skeleton_curves(Main *bmain,
Object *arm_obj,
const pxr::UsdSkelSkeletonQuery &skel_query,
const std::map<pxr::TfToken, std::string> &joint_to_bone_map,
const blender::Map<pxr::TfToken, std::string> &joint_to_bone_map,
ReportList *reports)
{
@ -128,7 +131,7 @@ void import_skeleton_curves(Main *bmain,
return;
}
if (joint_to_bone_map.empty()) {
if (joint_to_bone_map.is_empty()) {
return;
}
@ -156,50 +159,50 @@ void import_skeleton_curves(Main *bmain,
/* Get the joint paths. */
pxr::VtTokenArray joint_order = skel_query.GetJointOrder();
std::vector<FCurve *> loc_curves;
std::vector<FCurve *> rot_curves;
std::vector<FCurve *> scale_curves;
blender::Vector<FCurve *> loc_curves;
blender::Vector<FCurve *> rot_curves;
blender::Vector<FCurve *> scale_curves;
/* Iterate over the joints and create the corresponding curves for the bones. */
for (const pxr::TfToken &joint : joint_order) {
std::map<pxr::TfToken, std::string>::const_iterator it = joint_to_bone_map.find(joint);
const std::string *name = joint_to_bone_map.lookup_ptr(joint);
if (it == joint_to_bone_map.end()) {
if (name == nullptr) {
/* This joint doesn't correspond to any bone we created.
* Add null placeholders for the channel curves. */
loc_curves.push_back(nullptr);
loc_curves.push_back(nullptr);
loc_curves.push_back(nullptr);
rot_curves.push_back(nullptr);
rot_curves.push_back(nullptr);
rot_curves.push_back(nullptr);
rot_curves.push_back(nullptr);
scale_curves.push_back(nullptr);
scale_curves.push_back(nullptr);
scale_curves.push_back(nullptr);
loc_curves.append(nullptr);
loc_curves.append(nullptr);
loc_curves.append(nullptr);
rot_curves.append(nullptr);
rot_curves.append(nullptr);
rot_curves.append(nullptr);
rot_curves.append(nullptr);
scale_curves.append(nullptr);
scale_curves.append(nullptr);
scale_curves.append(nullptr);
continue;
}
bActionGroup *grp = action_groups_add_new(act, it->second.c_str());
bActionGroup *grp = action_groups_add_new(act, name->c_str());
/* Add translation curves. */
std::string rna_path = "pose.bones[\"" + it->second + "\"].location";
loc_curves.push_back(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
loc_curves.push_back(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
loc_curves.push_back(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
std::string rna_path = "pose.bones[\"" + *name + "\"].location";
loc_curves.append(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
loc_curves.append(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
loc_curves.append(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
/* Add rotation curves. */
rna_path = "pose.bones[\"" + it->second + "\"].rotation_quaternion";
rot_curves.push_back(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
rot_curves.push_back(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
rot_curves.push_back(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
rot_curves.push_back(create_chan_fcurve(act, grp, 3, rna_path, num_samples));
rna_path = "pose.bones[\"" + *name + "\"].rotation_quaternion";
rot_curves.append(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
rot_curves.append(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
rot_curves.append(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
rot_curves.append(create_chan_fcurve(act, grp, 3, rna_path, num_samples));
/* Add scale curves. */
rna_path = "pose.bones[\"" + it->second + "\"].scale";
scale_curves.push_back(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
scale_curves.push_back(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
scale_curves.push_back(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
rna_path = "pose.bones[\"" + *name + "\"].scale";
scale_curves.append(create_chan_fcurve(act, grp, 0, rna_path, num_samples));
scale_curves.append(create_chan_fcurve(act, grp, 1, rna_path, num_samples));
scale_curves.append(create_chan_fcurve(act, grp, 2, rna_path, num_samples));
}
/* Sanity checks: make sure we have a curve entry for each joint. */
@ -469,7 +472,7 @@ void import_blendshapes(Main *bmain,
/* Keep track of the shape-keys we're adding,
* for validation when creating curves later. */
std::set<pxr::TfToken> shapekey_names;
blender::Set<pxr::TfToken> shapekey_names;
for (int i = 0; i < targets.size(); ++i) {
/* Get USD path to blend shape. */
@ -505,7 +508,7 @@ void import_blendshapes(Main *bmain,
continue;
}
shapekey_names.insert(blendshapes[i]);
shapekey_names.add(blendshapes[i]);
/* Add the key block. */
kb = BKE_keyblock_add(key, blendshapes[i].GetString().c_str());
@ -629,13 +632,13 @@ void import_blendshapes(Main *bmain,
/* Create the animation and curves. */
bAction *act = blender::animrig::id_action_ensure(bmain, (ID *)&key->id);
std::vector<FCurve *> curves;
blender::Vector<FCurve *> curves;
for (auto blendshape_name : blendshapes) {
if (shapekey_names.find(blendshape_name) == shapekey_names.end()) {
if (!shapekey_names.contains(blendshape_name)) {
/* We didn't create a shape-key for this blend-shape, so we don't
* create a curve and insert a null placeholder in the curve array. */
curves.push_back(nullptr);
curves.append(nullptr);
continue;
}
@ -643,7 +646,7 @@ void import_blendshapes(Main *bmain,
std::string rna_path = "key_blocks[\"" + blendshape_name.GetString() + "\"].value";
FCurve *fcu = create_fcurve(0, rna_path);
fcu->totvert = num_samples;
curves.push_back(fcu);
curves.append(fcu);
BLI_addtail(&act->curves, fcu);
}
@ -715,12 +718,12 @@ void import_skeleton(Main *bmain,
ED_armature_to_edit(arm);
/* The bones we create, stored in the skeleton's joint order. */
std::vector<EditBone *> edit_bones;
blender::Vector<EditBone *> edit_bones;
/* Keep track of the bones we create for each joint.
* We'll need this when creating animation curves
* later. */
std::map<pxr::TfToken, std::string> joint_to_bone_map;
blender::Map<pxr::TfToken, std::string> joint_to_bone_map;
/* Create the bones. */
for (const pxr::TfToken &joint : joint_order) {
@ -732,11 +735,11 @@ void import_skeleton(Main *bmain,
"%s: Couldn't add bone for joint %s",
__func__,
joint.GetString().c_str());
edit_bones.push_back(nullptr);
edit_bones.append(nullptr);
continue;
}
joint_to_bone_map.insert(std::make_pair(joint, bone->name));
edit_bones.push_back(bone);
joint_to_bone_map.add(joint, bone->name);
edit_bones.append(bone);
}
/* Sanity check: we should have created a bone for each joint. */
@ -829,7 +832,7 @@ void import_skeleton(Main *bmain,
/* This will record the child bone indices per parent bone,
* to simplify accessing children when computing lengths. */
std::vector<std::vector<int>> child_bones(num_joints);
blender::Vector<blender::Vector<int>> child_bones(num_joints);
for (size_t i = 0; i < num_joints; ++i) {
const int parent_idx = skel_topology.GetParent(i);
@ -842,7 +845,7 @@ void import_skeleton(Main *bmain,
continue;
}
child_bones[parent_idx].push_back(i);
child_bones[parent_idx].append(i);
if (edit_bones[i] && edit_bones[parent_idx]) {
edit_bones[i]->parent = edit_bones[parent_idx];
}
@ -855,7 +858,7 @@ void import_skeleton(Main *bmain,
* by the distance between this bone's head
* and the average head location of its children. */
if (child_bones[i].empty()) {
if (child_bones[i].is_empty()) {
continue;
}
@ -893,7 +896,7 @@ void import_skeleton(Main *bmain,
avg_len_scale /= num_joints;
for (size_t i = 0; i < num_joints; ++i) {
if (!child_bones[i].empty()) {
if (!child_bones[i].is_empty()) {
/* Not a terminal bone. */
continue;
}
@ -1042,7 +1045,7 @@ void import_mesh_skel_bindings(Main *bmain,
}
/* Determine which joint indices are used for skinning this prim. */
std::vector<int> used_indices;
blender::Vector<int> used_indices;
for (int index : joint_indices) {
if (std::find(used_indices.begin(), used_indices.end(), index) == used_indices.end()) {
/* We haven't accounted for this index yet. */
@ -1050,11 +1053,11 @@ void import_mesh_skel_bindings(Main *bmain,
std::cerr << "Out of bound joint index " << index << std::endl;
continue;
}
used_indices.push_back(index);
used_indices.append(index);
}
}
if (used_indices.empty()) {
if (used_indices.is_empty()) {
return;
}
@ -1074,7 +1077,7 @@ void import_mesh_skel_bindings(Main *bmain,
}
/* Create a deform group per joint. */
std::vector<bDeformGroup *> joint_def_grps(joints.size(), nullptr);
blender::Vector<bDeformGroup *> joint_def_grps(joints.size(), nullptr);
for (int idx : used_indices) {
std::string joint_name = pxr::SdfPath(joints[idx]).GetName();

@ -8,7 +8,6 @@
#include "DNA_windowmanager_types.h"
#include <map>
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usdGeom/xformCache.h>
#include <pxr/usd/usdSkel/bindingAPI.h>

@ -20,6 +20,7 @@
#include "BLI_fileops.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_memory_utils.hh"
#include "BLI_path_util.h"
#include "BLI_string.h"
@ -103,7 +104,7 @@ struct InputSpec {
};
/* Map Blender socket names to USD Preview Surface InputSpec structs. */
using InputSpecMap = std::map<std::string, InputSpec>;
using InputSpecMap = blender::Map<std::string, InputSpec>;
/* Static function forward declarations. */
static pxr::UsdShadeShader create_usd_preview_shader(const USDExporterContext &usd_export_context,
@ -124,7 +125,7 @@ static bNode *find_bsdf_node(Material *material);
static void get_absolute_path(Image *ima, char *r_path);
static std::string get_tex_image_asset_filepath(const USDExporterContext &usd_export_context,
bNode *node);
static InputSpecMap &preview_surface_input_map();
static const InputSpecMap &preview_surface_input_map();
static bNodeLink *traverse_channel(bNodeSocket *input, short target_type);
void set_normal_texture_range(pxr::UsdShadeShader &usd_shader, const InputSpec &input_spec);
@ -174,16 +175,15 @@ static void create_usd_preview_surface_material(const USDExporterContext &usd_ex
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
/* Check if this socket is mapped to a USD preview shader input. */
const InputSpecMap::const_iterator it = input_map.find(sock->name);
if (it == input_map.end()) {
const InputSpec *spec = input_map.lookup_ptr(sock->name);
if (spec == nullptr) {
continue;
}
/* Allow scaling inputs. */
float scale = 1.0;
const InputSpec &input_spec = it->second;
const InputSpec &input_spec = *spec;
bNodeLink *input_link = traverse_channel(sock, SH_NODE_TEX_IMAGE);
if (input_spec.input_name == usdtokens::emissive_color) {
@ -336,22 +336,27 @@ static void create_usd_viewport_material(const USDExporterContext &usd_export_co
}
/* Return USD Preview Surface input map singleton. */
static InputSpecMap &preview_surface_input_map()
static const InputSpecMap &preview_surface_input_map()
{
static InputSpecMap input_map = {
{"Base Color", {usdtokens::diffuse_color, pxr::SdfValueTypeNames->Color3f, true}},
{"Emission Color", {usdtokens::emissive_color, pxr::SdfValueTypeNames->Color3f, true}},
{"Color", {usdtokens::diffuse_color, pxr::SdfValueTypeNames->Color3f, true}},
{"Roughness", {usdtokens::roughness, pxr::SdfValueTypeNames->Float, true}},
{"Metallic", {usdtokens::metallic, pxr::SdfValueTypeNames->Float, true}},
{"Specular IOR Level", {usdtokens::specular, pxr::SdfValueTypeNames->Float, true}},
{"Alpha", {usdtokens::opacity, pxr::SdfValueTypeNames->Float, true}},
{"IOR", {usdtokens::ior, pxr::SdfValueTypeNames->Float, true}},
/* Note that for the Normal input set_default_value is false. */
{"Normal", {usdtokens::normal, pxr::SdfValueTypeNames->Float3, false}},
{"Coat Weight", {usdtokens::clearcoat, pxr::SdfValueTypeNames->Float, true}},
{"Coat Roughness", {usdtokens::clearcoatRoughness, pxr::SdfValueTypeNames->Float, true}},
};
static const InputSpecMap input_map = []() {
InputSpecMap map;
map.add_new("Base Color", {usdtokens::diffuse_color, pxr::SdfValueTypeNames->Color3f, true});
map.add_new("Emission Color",
{usdtokens::emissive_color, pxr::SdfValueTypeNames->Color3f, true});
map.add_new("Color", {usdtokens::diffuse_color, pxr::SdfValueTypeNames->Color3f, true});
map.add_new("Roughness", {usdtokens::roughness, pxr::SdfValueTypeNames->Float, true});
map.add_new("Metallic", {usdtokens::metallic, pxr::SdfValueTypeNames->Float, true});
map.add_new("Specular IOR Level", {usdtokens::specular, pxr::SdfValueTypeNames->Float, true});
map.add_new("Alpha", {usdtokens::opacity, pxr::SdfValueTypeNames->Float, true});
map.add_new("IOR", {usdtokens::ior, pxr::SdfValueTypeNames->Float, true});
/* Note that for the Normal input set_default_value is false. */
map.add_new("Normal", {usdtokens::normal, pxr::SdfValueTypeNames->Float3, false});
map.add_new("Coat Weight", {usdtokens::clearcoat, pxr::SdfValueTypeNames->Float, true});
map.add_new("Coat Roughness",
{usdtokens::clearcoatRoughness, pxr::SdfValueTypeNames->Float, true});
return map;
}();
return input_map;
}
@ -990,13 +995,13 @@ static void export_texture(const USDExporterContext &usd_export_context, bNode *
const pxr::TfToken token_for_input(const char *input_name)
{
const InputSpecMap &input_map = preview_surface_input_map();
const InputSpecMap::const_iterator it = input_map.find(input_name);
const InputSpec *spec = input_map.lookup_ptr(input_name);
if (it == input_map.end()) {
return pxr::TfToken();
if (spec == nullptr) {
return {};
}
return it->second.input_name;
return spec->input_name;
}
pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_context,