USD: speed up large USD imports by not rebuilding material name map for each object

Previous code was rebuilding "name to material" map for each object
being imported. Which means O(N*M) complexity (N=object count,
M=material count). There was already a TODO comment suggesting that
a single map that's maintained for the whole import would be enough.
This commit does exactly that.

While importing Moana USD scene (260k objects, 18k materials) this
saves about 6 minutes of import time.

Reviewed By: Bastien Montagne
Differential Revision: https://developer.blender.org/D15222
This commit is contained in:
Aras Pranckevicius 2022-06-17 22:28:22 +03:00
parent 230f72347a
commit 5b5811c97b
2 changed files with 13 additions and 6 deletions

View File

@ -111,6 +111,7 @@ static void assign_materials(Main *bmain,
const std::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)
{
if (!(stage && bmain && ob)) {
@ -132,16 +133,12 @@ static void assign_materials(Main *bmain,
return;
}
/* TODO(kevin): use global map? */
std::map<std::string, Material *> mat_map;
build_mat_map(bmain, &mat_map);
blender::io::usd::USDMaterialReader mat_reader(params, bmain);
for (it = mat_index_map.begin(); it != mat_index_map.end(); ++it) {
Material *assigned_mat = find_existing_material(
it->first, params, mat_map, usd_path_to_mat_name);
it->first, params, mat_name_to_mat, usd_path_to_mat_name);
if (!assigned_mat) {
/* Blender material doesn't exist, so create it now. */
@ -165,7 +162,7 @@ static void assign_materials(Main *bmain,
}
const std::string mat_name = pxr::TfMakeValidIdentifier(assigned_mat->id.name + 2);
mat_map[mat_name] = assigned_mat;
mat_name_to_mat[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
@ -805,11 +802,16 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
std::map<pxr::SdfPath, int> mat_map;
assign_facesets_to_mpoly(motionSampleTime, mesh->mpoly, mesh->totpoly, &mat_map);
/* 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);
}
utils::assign_materials(bmain,
object_,
mat_map,
this->import_params_,
this->prim_.GetStage(),
this->settings_->mat_name_to_mat,
this->settings_->usd_path_to_mat_name);
}

View File

@ -11,6 +11,7 @@
#include <string>
struct Main;
struct Material;
struct Object;
namespace blender::io::usd {
@ -42,6 +43,10 @@ struct ImportSettings {
* 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;
/* 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;
ImportSettings()
: do_convert_mat(false),