Fix #125184: Guard against incorrect material subsets during USD import
USD Meshes and their UsdGeomSubset prims only support "face" element types but our importer was not checking to ensure this was the case. Additionally, we should guard against out of range indices being used in general. Both situations will now also print an obvious warning level log statement allowing technical users to better toubleshoot on their own. Test coverage will be added separately in the near future to ensure multi-material scenarios are handled correctly. Pull Request: https://projects.blender.org/blender/blender/pulls/126714
This commit is contained in:
committed by
Jesse Yurkovich
parent
43f5b1b5fc
commit
3a81bde896
@@ -44,6 +44,8 @@
|
||||
#include <pxr/usd/usdShade/materialBindingAPI.h>
|
||||
#include <pxr/usd/usdSkel/bindingAPI.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "CLG_log.h"
|
||||
static CLG_LogRef LOG = {"io.usd"};
|
||||
|
||||
@@ -745,26 +747,46 @@ void USDMeshReader::assign_facesets_to_material_indices(double motionSampleTime,
|
||||
int current_mat = 0;
|
||||
if (!subsets.empty()) {
|
||||
for (const pxr::UsdGeomSubset &subset : subsets) {
|
||||
|
||||
pxr::UsdShadeMaterial subset_mtl = utils::compute_bound_material(subset.GetPrim());
|
||||
pxr::UsdPrim subset_prim = subset.GetPrim();
|
||||
pxr::UsdShadeMaterial subset_mtl = utils::compute_bound_material(subset_prim);
|
||||
if (!subset_mtl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pxr::SdfPath subset_mtl_path = subset_mtl.GetPath();
|
||||
|
||||
if (subset_mtl_path.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pxr::TfToken element_type;
|
||||
subset.GetElementTypeAttr().Get(&element_type, motionSampleTime);
|
||||
if (element_type != pxr::UsdGeomTokens->face) {
|
||||
CLOG_WARN(&LOG,
|
||||
"UsdGeomSubset '%s' uses unsupported elementType: %s",
|
||||
subset_prim.GetName().GetText(),
|
||||
element_type.GetText());
|
||||
continue;
|
||||
}
|
||||
|
||||
const int mat_idx = r_mat_map->lookup_or_add(subset_mtl_path, 1 + current_mat++);
|
||||
const int max_element_idx = std::max(0, int(material_indices.size() - 1));
|
||||
|
||||
pxr::UsdAttribute indicesAttribute = subset.GetIndicesAttr();
|
||||
pxr::VtIntArray indices;
|
||||
indicesAttribute.Get(&indices, motionSampleTime);
|
||||
subset.GetIndicesAttr().Get(&indices, motionSampleTime);
|
||||
|
||||
for (const int i : indices) {
|
||||
material_indices[i] = mat_idx - 1;
|
||||
int bad_element_count = 0;
|
||||
for (const int element_idx : indices) {
|
||||
const int safe_element_idx = std::clamp(element_idx, 0, max_element_idx);
|
||||
bad_element_count += (safe_element_idx != element_idx) ? 1 : 0;
|
||||
material_indices[safe_element_idx] = mat_idx - 1;
|
||||
}
|
||||
|
||||
if (bad_element_count > 0) {
|
||||
CLOG_WARN(&LOG,
|
||||
"UsdGeomSubset '%s' contains invalid indices; material assignment may be "
|
||||
"incorrect (%d were out of range)",
|
||||
subset_prim.GetName().GetText(),
|
||||
bad_element_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user