USD: Animated camera property import

Imports in the following animated data from UsdGeomCameras:
- Focal length
- DOF distance
- DOF fstop
- Clip start, Clip end
- Tilt shift x, Tilt shift y
- Aperture sizes (with caveats)

Implementation wise, it's more complicated than I'd like due to needing
to read in both non-animated and animated data for each property. And
because I've tried to reduce the duplication of various transforms we
have to do on each value. E.g. scaling values by "tenth of scene units"
or the extraction of the USD clipping range from a GfVec2f into 2
separate properties, and 2 separate fcurves, in Blender etc. The current
approach was the best I could come up with so far.

Aperture sizes remain problematic for import, with animation data and
without, due to how Blender selects the largest sensor dimension to base
downstream calculations on and for which there's no concept in USD to
strictly dictate which dimension to use. Additionally, changing the
sensor size will impact the Tilt values as well. This means that if the
Aperture sizes are animated, we must also animate the tilt values; leads
to more fcurves being created than perhaps expected.

The `projection` attribute (perspective and orthographic) remains
unchanged (non animated only) due to differences in how USD<>Blender
interoperate with the Orthographic projection method. Note: Blender only
exports perspective cameras due to the same reason.

Pull Request: https://projects.blender.org/blender/blender/pulls/137487
This commit is contained in:
Jesse Yurkovich
2025-04-25 19:57:12 +02:00
committed by Jesse Yurkovich
parent 90644b30b2
commit ba60868477
7 changed files with 374 additions and 76 deletions

View File

@@ -1847,6 +1847,34 @@ class USDImportTest(AbstractUSDTest):
bpy.utils.unregister_class(ImportMtlxTextureUSDHook)
class USDImportComparisonTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.testdir = args.testdir
cls.output_dir = args.outdir
def test_import_usd(self):
comparisondir = self.testdir.joinpath("compare")
input_files = sorted(pathlib.Path(comparisondir).glob("*.usd*"))
self.passed_tests = []
self.failed_tests = []
self.updated_tests = []
from modules import io_report
report = io_report.Report("USD Import", self.output_dir, comparisondir, comparisondir.joinpath("reference"))
for input_file in input_files:
with self.subTest(pathlib.Path(input_file).stem):
bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "empty.blend"))
ok = report.import_and_check(
input_file, lambda filepath, params: bpy.ops.wm.usd_import(
filepath=str(input_file), import_subdiv=True, **params))
if not ok:
self.fail(f"{input_file.stem} import result does not match expectations")
report.finish("io_usd_import")
class GetPrimMapUsdImportHook(bpy.types.USDHook):
bl_idname = "get_prim_map_usd_import_hook"
bl_label = "Get Prim Map Usd Import Hook"
@@ -1962,6 +1990,7 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('--testdir', required=True, type=pathlib.Path)
parser.add_argument('--outdir', required=True, type=pathlib.Path)
args, remaining = parser.parse_known_args(argv)
unittest.main(argv=remaining, verbosity=0)