Cleanup: USD: Pass struct by ref and add more tests for scaling options

- There's only a few unit conversion options, just test all of them
- Use reference instead of pointer when passing export settings struct
- Organize scaling struct fields to keep similar options together

Pull Request: https://projects.blender.org/blender/blender/pulls/133774
This commit is contained in:
Jesse Yurkovich
2025-01-29 20:03:36 +01:00
committed by Jesse Yurkovich
parent ca64f2f7e7
commit a6ad8f4fd9
6 changed files with 27 additions and 48 deletions

View File

@@ -943,6 +943,8 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(op->customdata);
const float scale = RNA_float_get(op->ptr, "scale");
const float light_intensity_scale = RNA_float_get(op->ptr, "light_intensity_scale");
const bool apply_unit_conversion_scale = RNA_boolean_get(op->ptr, "apply_unit_conversion_scale");
const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
@@ -993,8 +995,6 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
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 float light_intensity_scale = RNA_float_get(op->ptr, "light_intensity_scale");
const eUSDMtlPurpose mtl_purpose = eUSDMtlPurpose(RNA_enum_get(op->ptr, "mtl_purpose"));
const eUSDMtlNameCollisionMode mtl_name_collision_mode = eUSDMtlNameCollisionMode(
RNA_enum_get(op->ptr, "mtl_name_collision_mode"));
@@ -1023,12 +1023,11 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
const eUSDTexNameCollisionMode tex_name_collision_mode = eUSDTexNameCollisionMode(
RNA_enum_get(op->ptr, "tex_name_collision_mode"));
const bool apply_unit_conversion_scale = RNA_boolean_get(op->ptr, "apply_unit_conversion_scale");
USDImportParams params{};
params.prim_path_mask = prim_path_mask;
params.scale = scale;
params.light_intensity_scale = light_intensity_scale;
params.apply_unit_conversion_scale = apply_unit_conversion_scale;
params.mesh_read_flag = mesh_read_flag;
params.set_frame_range = set_frame_range;
@@ -1075,8 +1074,6 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
STRNCPY(params.import_textures_dir, import_textures_dir);
params.apply_unit_conversion_scale = apply_unit_conversion_scale;
/* Switch out of edit mode to avoid being stuck in it (#54326). */
Object *obedit = CTX_data_edit_object(C);
if (obedit) {

View File

@@ -170,7 +170,7 @@ static void ensure_root_prim(pxr::UsdStageRefPtr stage, const USDExportParams &p
}
if (params.convert_scene_units) {
xf_api.SetScale(pxr::GfVec3f(float(1.0 / get_meters_per_unit(&params))));
xf_api.SetScale(pxr::GfVec3f(float(1.0 / get_meters_per_unit(params))));
}
if (params.convert_orientation) {
@@ -440,7 +440,7 @@ pxr::UsdStageRefPtr export_to_stage(const USDExportParams &params,
usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, upAxis);
const double meters_per_unit = get_meters_per_unit(&params);
const double meters_per_unit = get_meters_per_unit(params);
pxr::UsdGeomSetStageMetersPerUnit(usd_stage, meters_per_unit);
ensure_root_prim(usd_stage, params);
@@ -747,10 +747,10 @@ int USD_get_version()
return PXR_VERSION;
}
double get_meters_per_unit(const USDExportParams *params)
double get_meters_per_unit(const USDExportParams &params)
{
double result;
switch (params->convert_scene_units) {
switch (params.convert_scene_units) {
case USD_SCENE_UNITS_CENTIMETERS:
result = 0.01;
break;
@@ -770,7 +770,7 @@ double get_meters_per_unit(const USDExportParams *params)
result = 0.9144;
break;
case USD_SCENE_UNITS_CUSTOM:
result = double(params->custom_meters_per_unit);
result = double(params.custom_meters_per_unit);
break;
default:
result = 1.0;

View File

@@ -58,7 +58,7 @@ static void camera_sensor_size_for_render(const Camera *camera,
void USDCameraWriter::do_write(HierarchyContext &context)
{
const double meters_per_unit = get_meters_per_unit(&usd_export_context_.export_params);
const double meters_per_unit = get_meters_per_unit(usd_export_context_.export_params);
const float unit_scale = float(1.0 / meters_per_unit);
pxr::UsdTimeCode timecode = get_export_time_code();

View File

@@ -98,7 +98,7 @@ void USDTransformWriter::do_write(HierarchyContext &context)
eUSDSceneUnits::USD_SCENE_UNITS_METERS)
{
float scale_mat[4][4];
scale_m4_fl(scale_mat, float(1.0 / get_meters_per_unit(&usd_export_context_.export_params)));
scale_m4_fl(scale_mat, float(1.0 / get_meters_per_unit(usd_export_context_.export_params)));
mul_m4_m4m4(matrix_world, scale_mat, matrix_world);
}

View File

@@ -192,6 +192,7 @@ struct USDImportParams {
char *prim_path_mask;
float scale;
float light_intensity_scale;
bool apply_unit_conversion_scale;
char mesh_read_flag;
bool set_frame_range;
@@ -237,8 +238,6 @@ struct USDImportParams {
eUSDTexNameCollisionMode tex_name_collision_mode;
eUSDAttrImportMode attr_import_mode;
bool apply_unit_conversion_scale;
/**
* Communication structure between the wmJob management code and the worker code. Currently used
* to generate safely reports from the worker thread.
@@ -336,6 +335,6 @@ void USD_register_hook(std::unique_ptr<USDHook> hook);
void USD_unregister_hook(USDHook *hook);
USDHook *USD_find_hook_name(const char idname[]);
double get_meters_per_unit(const USDExportParams *params);
double get_meters_per_unit(const USDExportParams &params);
}; // namespace blender::io::usd

View File

@@ -1326,40 +1326,23 @@ class USDExportTest(AbstractUSDTest):
"""Test specifying stage meters per unit on export."""
bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "empty.blend"))
export_path = self.tempdir / "usd_export_units_test_cm.usda"
self.export_and_validate(
filepath=str(export_path),
convert_scene_units='CENTIMETERS'
units = (
("mm", 'MILLIMETERS', 0.001), ("cm", 'CENTIMETERS', 0.01), ("km", 'KILOMETERS', 1000),
("in", 'INCHES', 0.0254), ("ft", 'FEET', 0.3048), ("yd", 'YARDS', 0.9144),
("default", "", 1), ("custom", 'CUSTOM', 0.125)
)
for name, unit, value in units:
export_path = self.tempdir / f"usd_export_units_test_{name}.usda"
if name == "default":
self.export_and_validate(filepath=str(export_path))
elif name == "custom":
self.export_and_validate(filepath=str(export_path), convert_scene_units=unit, meters_per_unit=value)
else:
self.export_and_validate(filepath=str(export_path), convert_scene_units=unit)
# Verify that meters per unit were set correctly
stage = Usd.Stage.Open(str(export_path))
mpu = UsdGeom.GetStageMetersPerUnit(stage)
self.assertEqual(mpu, 0.01)
# Export with default meters units.
export_path = self.tempdir / "usd_export_units_test_default.usda"
self.export_and_validate(
filepath=str(export_path)
)
# Verify that meters per unit were set correctly
stage = Usd.Stage.Open(str(export_path))
mpu = UsdGeom.GetStageMetersPerUnit(stage)
self.assertEqual(mpu, 1.0)
# Export with custom meters per unit.
export_path = self.tempdir / "usd_export_units_test_custom.usda"
self.export_and_validate(
filepath=str(export_path),
convert_scene_units='CUSTOM',
meters_per_unit=0.1,
)
# Verify that meters per unit were set correctly
stage = Usd.Stage.Open(str(export_path))
mpu = UsdGeom.GetStageMetersPerUnit(stage)
self.assertAlmostEqual(mpu, 0.1)
# Verify that meters per unit were set correctly
stage = Usd.Stage.Open(str(export_path))
self.assertEqual(UsdGeom.GetStageMetersPerUnit(stage), value)
def test_export_native_instancing_true(self):
"""Test exporting instanced objects to native (scne graph) instances."""