USD: Import UsdNurbsCurves as Curves instead of old Curve
Refactor and revamp import and export of `UsdGeomNurbsCurves` prim objects. Fixes #130056, among other things. Summary of changes and enhancements: - Export: - Write out `nurb_weight` attribute as the USD `pointWeights` primvar - Properly write out cyclic NURBS curves data (* see notes) - Import: - Import using the new `Curves` datablock rather than the old `Curve` - Properly read in cyclic NURBS curves data (* see notes) - Tries harder to match incoming knot vector to standard `knots_mode`, will use Custom otherwise - Support import of all custom primvars and data attached to the prim (for use with Geometry Nodes etc.) (* see notes) Tests were added which check a variety of point count, order, knot_mode, and cyclic combinations (generated through Geometry Nodes). A small number of hand-crafted curves were used to test the Custom knots_mode support on import. Additionally, the tests cover the case when there are multiple curves defined for a single object. Notes: - Cyclic NURBS support is reliant on the current, under-spec'd, USD documentation. Changes may be required in the future if/when the USD spec is clarified: https://github.com/PixarAnimationStudios/OpenUSD/issues/3740 - Some Cyclic x knots_mode combinations are not correct and would require more research to determine how to properly address. - Custom attributes are not imported for Cyclic NURBS curves yet. Those will require additional work to function correctly and are also reliant on seeing how the USD spec changes. Pull Request: https://projects.blender.org/blender/blender/pulls/143970
This commit is contained in:
committed by
Jesse Yurkovich
parent
c61d958872
commit
7111e95527
@@ -895,9 +895,10 @@ class USDExportTest(AbstractUSDTest):
|
||||
self.assertEqual(self.round_vector(usd_extent[0]), extent[0])
|
||||
self.assertEqual(self.round_vector(usd_extent[1]), extent[1])
|
||||
|
||||
def check_nurbs_curve(prim, cyclic, orders, vert_counts, knots_count, extent):
|
||||
def check_nurbs_curve(prim, cyclic, orders, vert_counts, weights, knots_count, extent):
|
||||
self.assertEqual(prim.GetOrderAttr().Get(), orders)
|
||||
self.assertEqual(prim.GetCurveVertexCountsAttr().Get(), vert_counts)
|
||||
self.assertEqual(self.round_vector(prim.GetPointWeightsAttr().Get()), weights)
|
||||
self.assertEqual(prim.GetWidthsInterpolation(), "vertex")
|
||||
knots = prim.GetKnotsAttr().Get()
|
||||
usd_extent = prim.GetExtentAttr().Get()
|
||||
@@ -936,11 +937,14 @@ class USDExportTest(AbstractUSDTest):
|
||||
|
||||
# Contains 2 NURBS curves
|
||||
curve = UsdGeom.NurbsCurves(stage.GetPrimAtPath("/root/NurbsCurve/NurbsCurve"))
|
||||
check_nurbs_curve(curve, False, [4, 4], [6, 6], 10, [[-1.75, -2.6891, -1.0117], [3.0896, 1.9583, 1.0293]])
|
||||
weights = [1] * 12
|
||||
check_nurbs_curve(
|
||||
curve, False, [4, 4], [6, 6], weights, 10, [[-1.75, -2.6891, -1.0117], [3.0896, 1.9583, 1.0293]])
|
||||
|
||||
# Contains 1 NURBS curve
|
||||
curve = UsdGeom.NurbsCurves(stage.GetPrimAtPath("/root/NurbsCircle/NurbsCircle"))
|
||||
check_nurbs_curve(curve, True, [3], [8], 13, [[-2.0, -2.0, -1.0], [2.0, 2.0, 1.0]])
|
||||
weights = self.round_vector([1, math.sqrt(2) / 2] * 5)
|
||||
check_nurbs_curve(curve, True, [3], [10], weights, 13, [[-2, -2, -1], [2, 2, 1]])
|
||||
|
||||
def test_export_animation(self):
|
||||
bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "usd_anim_test.blend"))
|
||||
|
||||
@@ -2018,9 +2018,23 @@ class USDImportComparisonTest(unittest.TestCase):
|
||||
|
||||
from modules import io_report
|
||||
report = io_report.Report("USD Import", self.output_dir, comparisondir, comparisondir.joinpath("reference"))
|
||||
io_report.Report.context_lines = 8
|
||||
|
||||
bpy.utils.register_class(CompareTestSupportHook)
|
||||
|
||||
for input_file in input_files:
|
||||
with self.subTest(pathlib.Path(input_file).stem):
|
||||
input_file_path = pathlib.Path(input_file)
|
||||
|
||||
io_report.Report.side_to_print_single_line = 5
|
||||
io_report.Report.side_to_print_multi_line = 3
|
||||
|
||||
CompareTestSupportHook.reset_config()
|
||||
if input_file_path.name in ("nurbs-gen-single.usda", "nurbs-gen-multiple.usda", "nurbs-custom.usda"):
|
||||
CompareTestSupportHook.do_curve_rename = True
|
||||
io_report.Report.side_to_print_single_line = 10
|
||||
io_report.Report.side_to_print_multi_line = 10
|
||||
|
||||
with self.subTest(input_file_path.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(
|
||||
@@ -2028,9 +2042,32 @@ class USDImportComparisonTest(unittest.TestCase):
|
||||
if not ok:
|
||||
self.fail(f"{input_file.stem} import result does not match expectations")
|
||||
|
||||
bpy.utils.unregister_class(CompareTestSupportHook)
|
||||
report.finish("io_usd_import")
|
||||
|
||||
|
||||
class CompareTestSupportHook(bpy.types.USDHook):
|
||||
bl_idname = "CompareTestSupportHook"
|
||||
bl_label = "Support some Comparison "
|
||||
|
||||
do_curve_rename = False
|
||||
|
||||
@staticmethod
|
||||
def reset_config():
|
||||
CompareTestSupportHook.do_curve_rename = False
|
||||
|
||||
@staticmethod
|
||||
def on_import(context):
|
||||
prim_map = context.get_prim_map()
|
||||
|
||||
if CompareTestSupportHook.do_curve_rename:
|
||||
for prim_path, objects in prim_map.items():
|
||||
if isinstance(objects[0], bpy.types.Object):
|
||||
objects[0].name = prim_path.name
|
||||
elif isinstance(objects[0], bpy.types.Curves):
|
||||
objects[0].name = prim_path.GetParentPath().name
|
||||
|
||||
|
||||
class GetPrimMapUsdImportHook(bpy.types.USDHook):
|
||||
bl_idname = "get_prim_map_usd_import_hook"
|
||||
bl_label = "Get Prim Map Usd Import Hook"
|
||||
|
||||
Reference in New Issue
Block a user