From 803176f4553c4786d63e04076d0dc73ec0f9fbd2 Mon Sep 17 00:00:00 2001 From: Sebastien Blaineau-Ortega Date: Thu, 10 Oct 2024 18:36:42 +0200 Subject: [PATCH] Support deform_keys in curves (#2128) * Support deform_keys in curves #2127 * Add changelog --- CHANGELOG.md | 1 + libs/render_delegate/basis_curves.cpp | 7 + testsuite/test_2127/README | 7 + testsuite/test_2127/data/test.usda | 188 ++++++++++++++++++++++++++ testsuite/test_2127/ref/reference.log | 187 +++++++++++++++++++++++++ testsuite/test_2127/ref/reference.tif | Bin 0 -> 4146 bytes 6 files changed, 390 insertions(+) create mode 100644 testsuite/test_2127/README create mode 100644 testsuite/test_2127/data/test.usda create mode 100644 testsuite/test_2127/ref/reference.log create mode 100644 testsuite/test_2127/ref/reference.tif diff --git a/CHANGELOG.md b/CHANGELOG.md index 525bb7310..316b00b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ - [usd#2092](https://github.com/Autodesk/arnold-usd/issues/2092) - Fix interactive update issue when prims visibility is tweaked in the procedural - [usd#2102](https://github.com/Autodesk/arnold-usd/issues/2102) - Remove hydra warning subdiv_iterations: use type BYTE, not INT - [usd#2105](https://github.com/Autodesk/arnold-usd/issues/2105) - Ensure the Arnold scene isn't modified after a Hydra batch render started +- [usd#2127](https://github.com/Autodesk/arnold-usd/issues/2127) - Support deform_keys in curves ### Build - [usd#1969](https://github.com/Autodesk/arnold-usd/issues/1969) - Remove support for USD versions older than 21.05 diff --git a/libs/render_delegate/basis_curves.cpp b/libs/render_delegate/basis_curves.cpp index ffdea4028..9947b0488 100644 --- a/libs/render_delegate/basis_curves.cpp +++ b/libs/render_delegate/basis_curves.cpp @@ -97,6 +97,13 @@ void HdArnoldBasisCurves::Sync( bool dirtyTopology = HdChangeTracker::IsTopologyDirty(*dirtyBits, id); bool dirtyPrimvars = HdArnoldGetComputedPrimvars(sceneDelegate, id, *dirtyBits, _primvars, nullptr, &pointsSample) || (*dirtyBits & HdChangeTracker::DirtyPrimvar); + // We need to set the deform keys first if it is specified + VtValue deformKeysVal = sceneDelegate->Get(id, str::t_deformKeys); + if (deformKeysVal.IsHolding()) { + SetDeformKeys(deformKeysVal.UncheckedGet()); + } else { + SetDeformKeys(-1); + } bool dirtyPoints = HdChangeTracker::IsPrimvarDirty(*dirtyBits, id, HdTokens->points); if (dirtyPrimvars) { // This needs to be called before HdArnoldSetPositionFromPrimvar otherwise diff --git a/testsuite/test_2127/README b/testsuite/test_2127/README new file mode 100644 index 000000000..6be80c5f0 --- /dev/null +++ b/testsuite/test_2127/README @@ -0,0 +1,7 @@ +Curves with acceleration and deform_keys + +Fixes #2127 + +author: sebastien.ortega + +PARAMS: {'scene': 'test.usda', 'kick_params': '-frame 6 '} diff --git a/testsuite/test_2127/data/test.usda b/testsuite/test_2127/data/test.usda new file mode 100644 index 000000000..12a6403c7 --- /dev/null +++ b/testsuite/test_2127/data/test.usda @@ -0,0 +1,188 @@ +#usda 1.0 +( + endTimeCode = 6 + framesPerSecond = 24 + metersPerUnit = 1 + startTimeCode = 6 + timeCodesPerSecond = 24 + upAxis = "Y" +) + +def Xform "curves" ( + kind = "group" +) +{ + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + + def Xform "animated_curve" ( + kind = "component" + ) + { + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + matrix4d xformOp:transform:xform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform:xform"] + + def BasisCurves "curve_0" + { + vector3f[] accelerations ( + interpolation = "vertex" + ) + vector3f[] accelerations.timeSamples = { + 6: [(0, 0, 0), (0, -144, 0), (0, -288, 0), (0, -432, 0), (0, -576, 0)], + } + uniform token basis = "" + int[] curveVertexCounts.timeSamples = { + 6: [5], + } + float3[] extent.timeSamples = { + 6: [(-0.05, -0.05, -0.05), (0.05, 1.05, 0.05)], + } + point3f[] points ( + interpolation = "vertex" + ) + point3f[] points.timeSamples = { + 6: [(0, 0, 0), (0, 0.25, 0), (0, 0.5, 0), (0, 0.75, 0), (0, 1, 0)], + } + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + string primvars:arnold:mode = "1" ( + interpolation = "constant" + ) + uniform token type = "linear" + vector3f[] velocities ( + interpolation = "vertex" + ) + vector3f[] velocities.timeSamples = { + 6: [(0, 0, 0), (-5.196152, 0, 0), (-10.392304, 0, 0), (-15.588457, 0, 0), (-20.784609, 0, 0)], + } + float[] widths ( + interpolation = "vertex" + ) + float[] widths.timeSamples = { + 6: [0.1, 0.1, 0.1, 0.1, 0.1], + } + uniform token wrap = "nonperiodic" + matrix4d xformOp:transform:transform4 = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0.4, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform:transform4"] + } + } +} + +def Xform "cameras" +{ + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + + def Camera "camera" ( + prepend apiSchemas = ["HoudiniCameraPlateAPI", "HoudiniViewportGuideAPI"] + ) + { + float2 clippingRange = (0.00434915, 43491.5) + float exposure = 0 + float focalLength.timeSamples = { + 6: 0.321, + } + float focusDistance = 5 + float fStop = 0 + float horizontalAperture.timeSamples = { + 6: 0.414214, + } + float horizontalApertureOffset.timeSamples = { + 6: 0, + } + asset houdini:backgroundimage = @@ + asset houdini:foregroundimage = @@ + float houdini:guidescale.timeSamples = { + 6: 1, + } + bool houdini:inviewermenu = 1 + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + token projection = "perspective" + double shutter:close = 0.5 + double shutter:open = -0.5 + float verticalAperture.timeSamples = { + 6: 0.23299538, + } + float verticalApertureOffset.timeSamples = { + 6: 0, + } + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 3.113354891187284, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +def Xform "lights" +{ + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + + def DomeLight "domelight8" ( + prepend apiSchemas = ["HoudiniViewportGuideAPI"] + ) + { + custom rel filters = None + float houdini:guidescale.timeSamples = { + 6: 1, + } + bool houdini:inviewermenu = 0 + color3f inputs:color = (1, 1, 1) + float inputs:diffuse = 1 + bool inputs:enableColorTemperature = 0 + float inputs:exposure = 0 + float inputs:intensity = 1 + bool inputs:normalize = 0 + float inputs:specular = 1 + asset inputs:texture:file = @@ + token inputs:texture:format = "latlong" + rel light:filters = None + rel portals = None + float primvars:arnold:camera = 0 ( + interpolation = "constant" + ) + int primvars:arnold:deform_keys = 10 ( + interpolation = "constant" + ) + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +def Scope "Render" +{ + def Scope "Products" + { + def Scope "Vars" + { + def RenderVar "RGBA" + { + custom string arnold:filter = "box_filter" + token dataType = "color4f" + custom int driver:parameters:aov:clearValue = 0 + custom token driver:parameters:aov:format = "color4f" + custom bool driver:parameters:aov:multiSampled = 0 + custom string driver:parameters:aov:name = "RGBA" + string sourceName = "RGBA" + token sourceType = "raw" + } + } + } + + def RenderSettings "rendersettings" + { + custom int arnold:global:AA_samples = 4 + rel camera = + token[] includedPurposes = ["default"] + token[] materialBindingPurposes = ["full", "allPurpose"] + int2 resolution = (160, 120) + } +} + diff --git a/testsuite/test_2127/ref/reference.log b/testsuite/test_2127/ref/reference.log new file mode 100644 index 000000000..2c696d375 --- /dev/null +++ b/testsuite/test_2127/ref/reference.log @@ -0,0 +1,187 @@ +00:00:00 92MB | log started Thu Oct 10 15:13:53 2024 +00:00:00 92MB | Arnold 7.3.5.0 [f94e146d] windows x86_64 clang-15.0.7 oiio-2.4.1 osl-1.13.0 vdb-11.0.0 adlsdk-8.0.7.50 clmhub-3.1.1.43 rlm-14.2.5 optix-8.0.0 2024/10/02 10:23:45 +00:00:00 92MB | running on REMS4QL1726, pid=20996 +00:00:00 92MB | 2 x Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz (32 cores, 64 logical) with 65154MB +00:00:00 106MB | NVIDIA driver version 551.23 +00:00:00 106MB | GPU 0: Quadro RTX 4000 @ 1545MHz (compute 7.5) with 8191MB (5541MB available) (NVLink:0) +00:00:00 106MB | Windows 10 (version 10.0, build 19045) +00:00:00 106MB | soft limit for open files is set at 2048 +00:00:00 106MB | +00:00:00 106MB | Installing system handler with mask 255 +00:00:00 117MB | loading plugins from C:\arnold\arnold-usd\build\windows_x86_64\msvc_opt\usd-0.23.11_arnold-7.3.5.0\plugins\procedural ... +00:00:00 126MB | usd_proc.dll: usd uses Arnold 7.3.5.0 +00:00:00 126MB | loaded 1 plugins from 1 lib(s) in 0:00.10 +00:00:00 126MB | loading plugins from C:\arnold\sdk\latest\bin\..\plugins ... +00:00:00 126MB | alembic_proc.dll: alembic uses Arnold 7.3.5.0 +00:00:00 126MB | skipping already loaded plugin: C:\arnold\sdk\latest\bin\..\plugins\usd_proc.dll ... +00:00:00 126MB | loaded 1 plugins from 1 lib(s) in 0:00.00 +00:00:00 130MB | [kick] command: C:\arnold\sdk\latest\bin\kick test.usda -dw -r 160 120 -sm lambert -bs 16 -sl -o testrender.tif -set driver_tiff.dither false -nocrashpopup -dp -frame 6 -v 6 +00:00:00 130MB | loading plugins from . ... +00:00:00 130MB | no plugins loaded +00:00:00 131MB | ARNOLD_ADP_DISABLE envar passed in -- ADP is disabled for this session +00:00:00 173MB WARNING | USD arnold attribute deform_keys not recognized in skydome_light for /lights/domelight8 +00:00:00 173MB WARNING | USD arnold attribute deform_keys not recognized in persp_camera for /cameras/camera +00:00:00 173MB WARNING | USD arnold attribute deform_keys not recognized in curves for /curves/animated_curve/curve_0 +00:00:00 173MB | [kick] applying 2 attr value overrides +00:00:00 173MB | +00:00:00 173MB WARNING | rendering with watermarks because the skip_license_check option was enabled +00:00:00 173MB | +00:00:00 174MB | [color_manager] using color manager ai_default_color_manager_ocio of type "color_manager_ocio" +00:00:00 175MB | [color_manager_ocio] ai_default_color_manager_ocio : using builtin OCIO configuration file C:\arnold\sdk\latest\bin\../ocio/configs/arnold/config.ocio +00:00:00 175MB | [color_manager] rendering color space is "ACEScg" +00:00:00 228MB | +00:00:00 228MB | there are 1 light and 2 objects: +00:00:00 228MB | 1 persp_camera +00:00:00 228MB | 1 skydome_light +00:00:00 228MB | 2 utility +00:00:00 228MB | 1 standard_surface +00:00:00 228MB | 1 user_data_rgb +00:00:00 228MB | 1 driver_tiff +00:00:00 228MB | 2 box_filter +00:00:00 228MB | 1 gaussian_filter +00:00:00 228MB | 1 curves +00:00:00 228MB | 2 list_aggregate +00:00:00 228MB | 2 color_manager_ocio +00:00:00 228MB | +00:00:00 228MB | rendering image at 160 x 120, 4 AA samples +00:00:00 228MB | AA samples max +00:00:00 228MB | AA sample clamp +00:00:00 228MB | diffuse samples 2 / depth 1 +00:00:00 228MB | specular samples 2 / depth 1 +00:00:00 228MB | transmission samples 2 / depth 2 +00:00:00 228MB | volume indirect +00:00:00 228MB | total depth 10 +00:00:00 228MB | bssrdf samples 2 +00:00:00 228MB | light +00:00:00 228MB | transparency depth 10 +00:00:00 228MB | Full scene init/update requested for final render pass +00:00:00 228MB | full scene initialize (12 nodes) +00:00:00 229MB | creating root object list ... +00:00:00 229MB | full scene initialize done in 0:00.00 (multithreaded) +00:00:00 229MB | full scene update (13 nodes) +00:00:00 229MB | [color_manager_ocio] ai_default_color_manager_ocio : using builtin OCIO configuration file C:\arnold\sdk\latest\bin\../ocio/configs/arnold/config.ocio +00:00:00 229MB | /lights/domelight8: skydome_light using 1 sample, 2 volume samples +00:00:00 229MB | scene bounds: (-0.0830127001 -0.0500000007 -0.0500000007) -> (0.883012712 1.04845679 0.0500000007) +00:00:00 229MB | full scene update done in 0:00.00 (multithreaded) +00:00:00 229MB | [light_sampler] Group 0: Total number of lights 1, sampled lights 0, fixed lights 1 +00:00:00 229MB | [light_sampler] Group 0: Took 0.000000 ms to build the tree +00:00:00 229MB | [aov] parsing 1 output statements ... +00:00:00 229MB | [aov] registered driver: "kick_driver" (driver_tiff) +00:00:00 229MB | [aov] * "RGBA" of type RGBA filtered by "kick_filter" (gaussian_filter) +00:00:00 229MB | [aov] done preparing 2 AOVs for 1 output to 1 driver (0 deep AOVs) +00:00:00 231MB | starting 64 bucket workers of size 16x16 ... +00:00:00 232MB | [accel] curves list done - 0:00.00 - 4 prims, 10 keys +00:00:00 240MB | 1% done - 18 rays/pixel +00:00:00 246MB | 5% done - 34 rays/pixel +00:00:00 248MB | 10% done - 18 rays/pixel +00:00:00 254MB | 15% done - 30 rays/pixel +00:00:00 254MB | 20% done - 29 rays/pixel +00:00:00 260MB | 25% done - 16 rays/pixel +00:00:00 260MB | 30% done - 27 rays/pixel +00:00:00 263MB | 35% done - 33 rays/pixel +00:00:00 264MB | 40% done - 18 rays/pixel +00:00:00 265MB | 45% done - 15 rays/pixel +00:00:00 266MB | 50% done - 12 rays/pixel +00:00:00 266MB | 55% done - 41 rays/pixel +00:00:00 267MB | 60% done - 15 rays/pixel +00:00:00 271MB | 65% done - 30 rays/pixel +00:00:00 273MB | 70% done - 16 rays/pixel +00:00:00 275MB | 75% done - 13 rays/pixel +00:00:00 275MB | 80% done - 16 rays/pixel +00:00:00 276MB | 85% done - 13 rays/pixel +00:00:00 277MB | 90% done - 11 rays/pixel +00:00:00 277MB | 95% done - 4 rays/pixel +00:00:00 277MB | 100% done - 3 rays/pixel +00:00:00 277MB | render done in 0:00.058 +00:00:00 277MB | [driver_tiff] writing file `testrender.tif' +00:00:00 278MB | render done +00:00:00 278MB | +00:00:00 278MB | ----------------------------------------------------------------------------------- +00:00:00 278MB | scene creation time 0:00.39 machine utilization (4.27%) +00:00:00 278MB | unaccounted 0:00.39 +00:00:00 278MB | ----------------------------------------------------------------------------------- +00:00:00 278MB | frame time 0:00.13 machine utilization (11.39%) +00:00:00 278MB | rendering 0:00.05 +00:00:00 278MB | pixel rendering 0:00.05 +00:00:00 279MB | unaccounted 0:00.05 +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | top session self-times by category +00:00:00 279MB | sampleNextBatch 0:00.00 (27.77%) +00:00:00 279MB | accumulateBucketSamples 0:00.00 (19.70%) +00:00:00 279MB | TraceCameraRay 0:00.00 (15.23%) +00:00:00 279MB | ADP 0:00.00 ( 8.86%) +00:00:00 279MB | Plugin loader 0:00.00 ( 6.13%) +00:00:00 279MB | ray traversal+intersection 0:00.00 ( 5.37%) +00:00:00 279MB | AiSceneLoad 0:00.00 ( 5.32%) +00:00:00 279MB | surface closure (_default_arnold_shader) 0:00.00 ( 3.58%) +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | top session self-times by node +00:00:00 279MB | sampleNextBatch 0:00.00 (27.77%) +00:00:00 279MB | accumulateBucketSamples 0:00.00 (19.70%) +00:00:00 279MB | TraceCameraRay 0:00.00 (15.23%) +00:00:00 279MB | ADP 0:00.00 ( 8.86%) +00:00:00 279MB | Plugin loader 0:00.00 ( 6.13%) +00:00:00 279MB | AiSceneLoad 0:00.00 ( 5.32%) +00:00:00 279MB | ray traversal+intersection 0:00.00 ( 4.48%) +00:00:00 279MB | standard_surface:_default_arnold_shader 0:00.00 ( 4.47%) +00:00:00 279MB | surface closure 0:00.00 ( 3.58%) +00:00:00 279MB | ray traversal+intersection 0:00.00 ( 0.90%) +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | peak CPU memory used 278.96MB +00:00:00 279MB | at startup 76.50MB +00:00:00 279MB | plugins 0.06MB +00:00:00 279MB | AOV samples 0.31MB +00:00:00 279MB | output buffers 0.19MB +00:00:00 279MB | framebuffers 0.31MB +00:00:00 279MB | node overhead 0.01MB +00:00:00 279MB | message passing 0.07MB +00:00:00 279MB | memory pools 25.01MB +00:00:00 279MB | geometry 0.00MB +00:00:00 279MB | curves 0.00MB +00:00:00 279MB | accel structs 0.00MB +00:00:00 279MB | strings 24.50MB +00:00:00 279MB | profiler 0.01MB +00:00:00 279MB | backtrace handler 29.85MB +00:00:00 279MB | unaccounted 122.14MB +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | ray counts ( /pixel, /sample) (% total) (avg. hits) (max hits) +00:00:00 279MB | camera 343440 ( 17.89, 1.00) ( 90.14%) ( 0.01) ( 2) +00:00:00 279MB | shadow 25027 ( 1.30, 0.07) ( 6.57%) ( 0.00) ( 0) +00:00:00 279MB | diffuse_reflect 11689 ( 0.61, 0.03) ( 3.07%) ( 0.00) ( 0) +00:00:00 279MB | specular_reflect 838 ( 0.04, 0.00) ( 0.22%) ( 0.00) ( 0) +00:00:00 279MB | total 380994 ( 19.84, 1.11) (100.00%) ( 0.01) ( 2) +00:00:00 279MB | by ray depth: 0 1 +00:00:00 279MB | total 96.7% 3.3% +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | shader calls ( /pixel, /sample) (% total) +00:00:00 279MB | primary 6264 ( 0.33, 0.02) (100.00%) +00:00:00 279MB | total 6264 ( 0.33, 0.02) (100.00%) +00:00:00 279MB | by ray depth: 0 1 +00:00:00 279MB | total 100.0% 0.0% +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | geometry (% hit ) (instances) ( init mem, final mem) +00:00:00 279MB | lists 1 (100.0%) ( 0) ( 0.00, 0.00) +00:00:00 279MB | curves 1 (100.0%) ( 0) ( 0.00, 0.00) +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | geometric elements ( min) ( avg.) ( max) +00:00:00 279MB | curves 1 ( 1) ( 1.0) ( 1) +00:00:00 279MB | curve segments 4 ( 4) ( 4.0) ( 4) +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | acceleration structures: (% total) +00:00:00 279MB | list 2 (100.00%) +00:00:00 279MB | total 2 (100.00%) +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 279MB | number of warnings, warning type: +00:00:00 279MB | 3: USD arnold attribute %s not recognized in %s for %s +00:00:00 279MB | 1: rendering with watermarks because the skip_license_check option was enabled +00:00:00 279MB | ----------------------------------------------------------------------------------- +00:00:00 280MB | +00:00:00 280MB | releasing resources +00:00:00 205MB | +00:00:00 205MB | releasing resources +00:00:00 192MB | unloading 2 plugins +00:00:00 192MB | closing usd_proc.dll ... +00:00:00 192MB | closing alembic_proc.dll ... +00:00:00 192MB | unloading plugins done +00:00:00 192MB | Arnold shutdown +00:00:00 178MB | Installing system handler with mask 0 diff --git a/testsuite/test_2127/ref/reference.tif b/testsuite/test_2127/ref/reference.tif new file mode 100644 index 0000000000000000000000000000000000000000..1cc4b875e0c2496ce35dc5c6571b3c7bdf436b72 GIT binary patch literal 4146 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