From 0b9fde1992a733b80bcfdd855dc01271af0caabe Mon Sep 17 00:00:00 2001 From: Alex Fuller Date: Wed, 1 Apr 2026 05:16:18 +1100 Subject: [PATCH 1/9] Cycles : Octahedrally encoded normals and face-varying support. --- .../IECoreCyclesPreviewTest/RendererTest.py | 31 +++++++++++++++- .../IECoreCyclesPreview/GeometryAlgo.cpp | 37 ++++++++++++++++++- .../IECoreCyclesPreview/MeshAlgo.cpp | 13 +++---- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py b/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py index f57d25481c3..fbad5a47d76 100644 --- a/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py +++ b/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py @@ -970,7 +970,6 @@ def testNoMeshNormals( self ) : def testFaceVaryingMeshNormals( self ) : - # These are treated like non-existent normals, since Cycles doesn't support them. cube = IECoreScene.MeshPrimitive.createBox( imath.Box3f( imath.V3f( -0.5 ), imath.V3f( 0.5 ) ) ) self.__testMeshSmoothing( cube, smoothingExpected = False ) @@ -980,6 +979,36 @@ def testVertexMeshNormals( self ) : cube["N"] = IECoreScene.MeshAlgo.calculateVertexNormals( cube, IECoreScene.MeshAlgo.NormalWeighting.Equal ) self.__testMeshSmoothing( cube, smoothingExpected = True ) + def testUnsupportedMeshNormals( self ) : + + renderer = self.createRenderer() + attributes = renderer.attributes( IECore.CompoundObject() ) + + cube = IECoreScene.MeshPrimitive.createBox( imath.Box3f( imath.V3f( -0.5 ), imath.V3f( 0.5 ) ) ) + + for interpolation in ( + IECoreScene.PrimitiveVariable.Interpolation.Uniform, + IECoreScene.PrimitiveVariable.Interpolation.Vertex, + IECoreScene.PrimitiveVariable.Interpolation.FaceVarying, + ) : + with self.subTest( interpolation = interpolation ) : + + cube = cube.copy() + cube["N"] = IECoreScene.PrimitiveVariable( + interpolation, + IECore.V3iVectorData( [ imath.V3i( 0, 1, 0 ) ] * cube.variableSize( interpolation ), IECore.GeometricData.Interpretation.Normal ) + ) + + with IECore.CapturingMessageHandler() as mh : + + renderer.object( str( interpolation ), cube, attributes ) + + self.assertEqual( len( mh.messages ), 1 ) + self.assertEqual( + mh.messages[0].message, + "Primitive variable \"N\" has unsupported type \"V3iVectorData\" (expected V3fVectorData)." + ) + def testUnsupportedPrimitiveVariables( self ) : renderer = self.createRenderer() diff --git a/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp index b5be028382e..a20eb535040 100644 --- a/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp @@ -142,6 +142,13 @@ ccl::Attribute *convertTypedPrimitiveVariable( const std::string &name, const Pr data = static_cast( primitiveVariable.data.get() ); } + // Special case for normals as they need to be octahedrally encoded. + const bool isNormal = typeDesc == ccl::TypeNormal; + if( isNormal ) + { + attributeElement = attributeElement == ccl::ATTR_ELEMENT_CORNER ? ccl::ATTR_ELEMENT_CORNER_NORMAL : ccl::ATTR_ELEMENT_VERTEX_NORMAL; + } + // Create attribute. Cycles will allocate a buffer based on `attributeElement` and the information // `attributes.geometry` contains. @@ -167,7 +174,29 @@ ccl::Attribute *convertTypedPrimitiveVariable( const std::string &name, const Pr // Copy data into buffer. - if constexpr( std::is_same_v || std::is_same_v ) + if( isNormal ) + { + if constexpr( std::is_same_v ) + { + ccl::packed_normal *pn = attribute->data_normal(); + for( const auto &v : data->readable() ) + { + *pn++ = ccl::packed_normal( ccl::make_float3( v.x, v.y, v.z ) ); + } + } + else + { + msg( + Msg::Warning, "IECoreCyles::GeometryAlgo::convertPrimitiveVariable", + fmt::format( + "Primitive variable \"{}\" has unsupported type \"{}\" (expected V3fVectorData).", + name, primitiveVariable.data->typeName() + ) + ); + return nullptr; + } + } + else if constexpr( std::is_same_v || std::is_same_v ) { // Special case for arrays of `float3`, where each element actually contains 4 floats for alignment purposes. ccl::float3 *f3 = attribute->data_float3(); @@ -374,10 +403,14 @@ void convertPrimitiveVariable( const std::string &name, const IECoreScene::Primi /// use `convertPrimitiveVariable()` for most data, instead of having /// custom code paths for `P`, `uv` etc? - if( name == "N" && attr->element == ccl::ATTR_ELEMENT_VERTEX && attr->type == ccl::TypeNormal ) + if( name == "N" && attr->element == ccl::ATTR_ELEMENT_VERTEX_NORMAL && attr->type == ccl::TypeNormal ) { attr->std = ccl::ATTR_STD_VERTEX_NORMAL; } + else if( name == "N" && attr->element == ccl::ATTR_ELEMENT_CORNER_NORMAL && attr->type == ccl::TypeNormal ) + { + attr->std = ccl::ATTR_STD_CORNER_NORMAL; + } else if( name == "uv" && attr->type == ccl::TypeFloat2 ) { attr->std = ccl::ATTR_STD_UV; diff --git a/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp index 5341311ed82..d3323de81be 100644 --- a/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp @@ -70,10 +70,13 @@ namespace // - Which normal is actually used for shading is determined on a // triangle-by-triangle basis using the `smooth` flag passed // to `Mesh::add_triangle()`. -// - Cycles does not support facevarying normals. +// - Cycles as of 5.1 now supports face-varying normals as +// ("N", ATTR_STD_CORNER_NORMAL) // // Also see `GeometryAlgo::convertPrimitiveVariable()` where we handle the -// tagging of normal attributes with ATTR_STD_VERTEX_NORMAL. +// tagging of normal attributes with ATTR_STD_VERTEX_NORMAL or +// ATTR_STD_CORNER_NORMAL. This also handles octahedral packing of normals +// via the `ccl::packed_normal()` utility function. bool hasSmoothNormals( const IECoreScene::MeshPrimitive *mesh ) { auto it = mesh->variables.find( "N" ); @@ -88,12 +91,6 @@ bool hasSmoothNormals( const IECoreScene::MeshPrimitive *mesh ) case PrimitiveVariable::Uniform : // These are definitely intended to be faceted. return false; - case PrimitiveVariable::FaceVarying : - // Could be a mix of faceted and non-faceted triangles, including - // triangles with a mix of soft and hard edges, which aren't - // representable in Cycles. Plump for faceted, among other things - // because the native Cortex cube geometry has FaceVarying normals. - return false; default : return true; } From b9d60b4055d3972d67419f80bc605347d96e7cd6 Mon Sep 17 00:00:00 2001 From: Alex Fuller Date: Wed, 1 Apr 2026 05:18:18 +1100 Subject: [PATCH 2/9] Cycles : API changes when reflecting node types. --- .../IECoreCyclesPreview/IECoreCycles.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/GafferCycles/IECoreCyclesPreview/IECoreCycles.cpp b/src/GafferCycles/IECoreCyclesPreview/IECoreCycles.cpp index bdbf538a525..f338e08fdbe 100644 --- a/src/GafferCycles/IECoreCyclesPreview/IECoreCycles.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/IECoreCycles.cpp @@ -146,9 +146,9 @@ IECore::CompoundDataPtr nodeData() IECore::CompoundDataPtr result = new IECore::CompoundData(); IECore::CompoundDataMap &nodes = result->writable(); - for( const auto& nodeType : ccl::NodeType::types() ) + for( const auto& nodeType : ccl::NodeType::type_names() ) { - const ccl::NodeType *cNodeType = ccl::NodeType::find( nodeType.first ); + const ccl::NodeType *cNodeType = ccl::NodeType::find( nodeType ); if( cNodeType ) { // We skip "ShaderNode" types here @@ -156,14 +156,14 @@ IECore::CompoundDataPtr nodeData() continue; // The shader node we skip - if( nodeType.first == "shader" ) + if( nodeType == "shader" ) continue; IECore::CompoundDataPtr node = new IECore::CompoundData(); IECore::CompoundDataMap &n = node->writable(); n["in"] = getSockets( cNodeType, false ); n["out"] = getSockets( cNodeType, true ); - nodes[nodeType.first.c_str()] = std::move( node ); + nodes[nodeType.c_str()] = std::move( node ); } } return result; @@ -174,14 +174,14 @@ IECore::CompoundDataPtr shaderData() IECore::CompoundDataPtr result = new IECore::CompoundData(); IECore::CompoundDataMap &shaders = result->writable(); - for( const auto& nodeType : ccl::NodeType::types() ) + for( const auto& nodeType : ccl::NodeType::type_names() ) { // Skip over the "output" ShaderNode, as this is a part of the main // "shader" node. - if( std::string( nodeType.first.c_str() ) == "output" ) + if( std::string( nodeType.c_str() ) == "output" ) continue; - const ccl::NodeType *cNodeType = ccl::NodeType::find( nodeType.first ); + const ccl::NodeType *cNodeType = ccl::NodeType::find( nodeType ); if( cNodeType ) { if( cNodeType->type == ccl::NodeType::SHADER ) @@ -191,7 +191,7 @@ IECore::CompoundDataPtr shaderData() s["in"] = getSockets( cNodeType, false ); s["out"] = getSockets( cNodeType, true ); - std::string type( nodeType.first.c_str() ); + std::string type( nodeType.c_str() ); if( boost::ends_with( type, "bsdf" ) ) { From ac783d7c56b915cc5194d8c079aa6476bbbd5bcf Mon Sep 17 00:00:00 2001 From: Alex Fuller Date: Mon, 13 Apr 2026 23:40:05 -0600 Subject: [PATCH 3/9] SConstruct : Remove cycles_kernel as it is no longer in 5.1.0, however cycles_kernel_cpu still needs to link. --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index bf585fe1b8c..746a389f363 100644 --- a/SConstruct +++ b/SConstruct @@ -1390,7 +1390,7 @@ libraries = { "LIBS" : [ "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreImage$CORTEX_LIB_SUFFIX", "IECoreVDB$CORTEX_LIB_SUFFIX", "Gaffer", "GafferScene", "GafferDispatch", "GafferOSL", - "cycles_device", "cycles_session", "cycles_scene", "cycles_graph", "cycles_bvh", "cycles_kernel", "cycles_kernel_osl", + "cycles_device", "cycles_session", "cycles_scene", "cycles_graph", "cycles_bvh", "cycles_kernel_cpu", "cycles_kernel_osl", "cycles_integrator", "cycles_util", "cycles_subd", "extern_sky", "extern_cuew", "OpenImageIO$OIIO_LIB_SUFFIX", "OpenImageIO_Util$OIIO_LIB_SUFFIX", "oslexec$OSL_LIB_SUFFIX", "oslcomp$OSL_LIB_SUFFIX", "oslquery$OSL_LIB_SUFFIX", "openvdb$VDB_LIB_SUFFIX", "Alembic", "osdCPU", "OpenColorIO$OCIO_LIB_SUFFIX", "embree4", "openpgl", "zstd", From 0f1a2c29fc1c67877af4a2fd4bd876c3f3aaf63e Mon Sep 17 00:00:00 2001 From: Alex Fuller Date: Tue, 14 Apr 2026 12:24:48 +1000 Subject: [PATCH 4/9] Cycles : Update to 5.1.0. --- Changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index 9c32fd7fe36..ff67f0a44b0 100644 --- a/Changes.md +++ b/Changes.md @@ -4,7 +4,7 @@ Features -------- -- Cycles : Updated to version 5.0.0. +- Cycles : Updated to version 5.1.0. - CurvesInterpolation : Added node for modifying CurvesPrimitive `basis` and `wrap`. This includes the ability to convert curves with `Pinned` wrap to `NonPeriodic`, adding the appropriate "phantom" points to maintain curve shape. Improvements From 89f0f8ec538d5fd39562097a79158012a95c0e86 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Thu, 30 Apr 2026 18:08:57 -0700 Subject: [PATCH 5/9] CI : Update to GafferHQ/dependencies 11.0.0.0a6 --- .github/workflows/main/installDependencies.py | 2 +- Changes.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main/installDependencies.py b/.github/workflows/main/installDependencies.py index 2d3088c7546..10c5a7f0893 100755 --- a/.github/workflows/main/installDependencies.py +++ b/.github/workflows/main/installDependencies.py @@ -49,7 +49,7 @@ # Determine default archive URL. -defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.7.0.0a9/cortex-10.7.0.0a9-{platform}-{vfxPlatform}.{extension}" +defaultURL = "https://github.com/GafferHQ/dependencies/releases/download/11.0.0a6/gafferDependencies-11.0.0a6-{platform}-{vfxPlatform}.{extension}" # Parse command line arguments. diff --git a/Changes.md b/Changes.md index ff67f0a44b0..651e2e4429c 100644 --- a/Changes.md +++ b/Changes.md @@ -103,7 +103,7 @@ Build - Boost : Updated to version 1.85.0. - Cortex : Updated to version 10.7.0.0a9. -- Cycles : Updated to version 5.0.0. +- Cycles : Updated to version 5.1.0. - Embree : Updated to version 4.4.0. - Imath : Updated to version 3.1.12. - Jemalloc : Removed when building on macOS. @@ -117,6 +117,7 @@ Build - PySide : Updated to version 6.5.8. - Python : Updated to version 3.11.14. - Qt : Updated to version 6.5.8. +- SSE2NEON : Added version 1.9.1 when building on macOS. - TBB : Updated to version 2021.13.0. - USD : Updated to version 26.03. From 1f2351d839803415cb4a6c93fcd36c3148bfe5bd Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Thu, 30 Apr 2026 18:09:04 -0700 Subject: [PATCH 6/9] Cycles RendererTest : Adjust for Cycles 5.1.0 normals behaviour change Cycles now outputs normalized normals, so we can no longer directly compare the result with our non-normalized primitive variable. --- .../GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py b/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py index fbad5a47d76..c60d4be395d 100644 --- a/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py +++ b/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py @@ -900,9 +900,7 @@ def testPointsWithNormals( self ) : self.assertTrue( isinstance( image, IECoreImage.ImagePrimitive ) ) color = self.__colorAtUV( image, imath.V2f( 0.5 ) ) - self.assertEqual( color.r, points["N"].data[0].x ) - self.assertEqual( color.g, points["N"].data[0].y ) - self.assertEqual( color.b, points["N"].data[0].z ) + self.assertEqualWithAbsError( imath.Color3f( color.r, color.g, color.b ), points["N"].data[0].normalize(), 0.0001 ) def __testMeshSmoothing( self, cube, smoothingExpected ) : From 4a9b1f0b2f357c40454c9c44147d56a42471a980 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Tue, 5 May 2026 20:08:29 -0700 Subject: [PATCH 7/9] Cycles MeshAlgo : Resample Uniform "N" to FaceVarying Now that Cycles has support for FaceVarying normals, we can preserve custom Uniform normals by resampling them to FaceVarying. --- Changes.md | 1 + .../IECoreCyclesPreviewTest/RendererTest.py | 6 ++++++ src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp | 11 ++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index 651e2e4429c..71293210777 100644 --- a/Changes.md +++ b/Changes.md @@ -40,6 +40,7 @@ Fixes - Cycles : - Reduced memory usage when rendering a single segment of deformation blur on CPU devices. - Fixed PointsPrimitive motion blur when rendering with even numbers of segments. + - Fixed translation of Uniform `N` primitive variables, these are now resampled to FaceVarying. - USDShader : Fixed value of `type` plug after loading a USDLux light. - CyclesLight, ArnoldLight, LightFilter : Fixed potential hang when loading shaders (GIL management bug in `loadShader()` binding). - StandardNodeGadget : Fixed crash caused by the node emitting `errorSignal()` while the gadget is undergoing construction. diff --git a/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py b/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py index c60d4be395d..e2df1a4d619 100644 --- a/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py +++ b/python/GafferCyclesTest/IECoreCyclesPreviewTest/RendererTest.py @@ -977,6 +977,12 @@ def testVertexMeshNormals( self ) : cube["N"] = IECoreScene.MeshAlgo.calculateVertexNormals( cube, IECoreScene.MeshAlgo.NormalWeighting.Equal ) self.__testMeshSmoothing( cube, smoothingExpected = True ) + def testUniformMeshNormals( self ) : + + cube = IECoreScene.MeshPrimitive.createBox( imath.Box3f( imath.V3f( -0.5 ), imath.V3f( 0.5 ) ) ) + cube["N"] = IECoreScene.MeshAlgo.calculateUniformNormals( cube ) + self.__testMeshSmoothing( cube, smoothingExpected = False ) + def testUnsupportedMeshNormals( self ) : renderer = self.createRenderer() diff --git a/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp index d3323de81be..9d5eb11e421 100644 --- a/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp @@ -66,7 +66,8 @@ namespace // - Cycles meshes store vertex normals as ("N", ATTR_STD_VERTEX_NORMAL) // - If we don't specify vertex normals, they are computed for us // and added to the mesh by Cycles itself by `Mesh::add_vertex_normals()` -// - Face normals are computed on demand in the Cycles kernel. +// - Face normals are always computed on demand in the Cycles kernel, so we +// resample custom uniform normals to face-varying. // - Which normal is actually used for shading is determined on a // triangle-by-triangle basis using the `smooth` flag passed // to `Mesh::add_triangle()`. @@ -217,6 +218,14 @@ ccl::Mesh *convertPrimary( const IECoreScene::MeshPrimitive *mesh, ccl::Scene *s // Converted above already continue; } + if( name == "N" && variable.interpolation == PrimitiveVariable::Uniform ) + { + // Resample "N" to FaceVarying as Cycles doesn't accept custom uniform normals. + PrimitiveVariable resampledN = variable; + IECoreScene::MeshAlgo::resamplePrimitiveVariable( mesh, resampledN, PrimitiveVariable::FaceVarying ); + GeometryAlgo::convertPrimitiveVariable( name, resampledN, attributes, ccl::ATTR_ELEMENT_CORNER ); + continue; + } switch( variable.interpolation ) { case PrimitiveVariable::Constant : From 33dfa2b645281c3feec6630131202036bf00fa59 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Wed, 6 May 2026 10:18:07 -0700 Subject: [PATCH 8/9] Cycles GeometryAlgo : Remove redundant sample creation workaround This removes the workaround added in 916f86044ff496f01edd4f110dd14a4e338d3a9d. Cycles 5.2 will improve support for even numbers of samples, and we've backported that PR to Cycles 5.1 in GafferDependencies. https://projects.blender.org/blender/blender/pulls/157076 --- Changes.md | 2 +- .../IECoreCyclesPreview/GeometryAlgo.h | 2 +- .../IECoreCyclesPreview/GeometryAlgo.cpp | 29 ++----------------- .../IECoreCyclesPreview/Renderer.cpp | 12 ++++---- 4 files changed, 10 insertions(+), 35 deletions(-) diff --git a/Changes.md b/Changes.md index 71293210777..7c36b049dbf 100644 --- a/Changes.md +++ b/Changes.md @@ -38,7 +38,7 @@ Fixes - DeleteCurves : Fixed deletion of periodic curves. - ResamplePrimitiveVariables : Fixed resampling between Vertex and Varying for linear curves. - Cycles : - - Reduced memory usage when rendering a single segment of deformation blur on CPU devices. + - Reduced memory usage when rendering a single segment of deformation blur. - Fixed PointsPrimitive motion blur when rendering with even numbers of segments. - Fixed translation of Uniform `N` primitive variables, these are now resampled to FaceVarying. - USDShader : Fixed value of `type` plug after loading a USDLux light. diff --git a/include/GafferCycles/IECoreCyclesPreview/GeometryAlgo.h b/include/GafferCycles/IECoreCyclesPreview/GeometryAlgo.h index 9138488aa5b..38215f6b8ca 100644 --- a/include/GafferCycles/IECoreCyclesPreview/GeometryAlgo.h +++ b/include/GafferCycles/IECoreCyclesPreview/GeometryAlgo.h @@ -62,7 +62,7 @@ namespace GeometryAlgo { /// Converts animated samples of an `IECore::Object` into an equivalent `ccl::Geometry` object. -IECORECYCLES_API ccl::Geometry *convert( const IECoreScenePreview::Renderer::ObjectSamples &samples, const IECoreScenePreview::Renderer::SampleTimes ×, ccl::Session *session ); +IECORECYCLES_API ccl::Geometry *convert( const IECoreScenePreview::Renderer::ObjectSamples &samples, const IECoreScenePreview::Renderer::SampleTimes ×, ccl::Scene *scene ); /// Converts a primitive variable to a `ccl::Attribute` inside of a `ccl::AttributeSet`. IECORECYCLES_API void convertPrimitiveVariable( const std::string &name, const IECoreScene::PrimitiveVariable &primitiveVariable, ccl::AttributeSet &attributes, ccl::AttributeElement attributeElement ); diff --git a/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp index a20eb535040..9a7b2b9395a 100644 --- a/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/GeometryAlgo.cpp @@ -38,7 +38,6 @@ #include "IECoreScene/PrimitiveVariable.h" -#include "IECore/ObjectInterpolator.h" #include "IECore/SimpleTypedData.h" IECORE_PUSH_DEFAULT_VISIBILITY @@ -240,37 +239,13 @@ namespace IECoreCycles namespace GeometryAlgo { -ccl::Geometry *convert( const IECoreScenePreview::Renderer::ObjectSamples &samples, const IECoreScenePreview::Renderer::SampleTimes ×, ccl::Session *session ) +ccl::Geometry *convert( const IECoreScenePreview::Renderer::ObjectSamples &samples, const IECoreScenePreview::Renderer::SampleTimes ×, ccl::Scene *scene ) { if( samples.empty() ) { return nullptr; } - if( samples.size() % 2 == 0 && session->device->info.type != ccl::DeviceType::DEVICE_CPU ) - { - // Cycles requires an odd number of motion samples for some reason, although - // experimentally this only seems to be the case when using GPU devices. - // Make memory-wasting redundant samples to work around this. Samples are - // expected to be spaced evenly in time, so we have to insert a redundant sample - // in every gap. - IECoreScenePreview::Renderer::ObjectSamples processedSamples; - processedSamples.reserve( samples.size() * 2 - 1 ); - IECoreScenePreview::Renderer::SampleTimes processedTimes; - processedTimes.reserve( samples.size() * 2 - 1 ); - for( size_t i = 0; i < samples.size(); ++i ) - { - processedSamples.push_back( samples[i] ); - processedTimes.push_back( times[i] ); - if( i + 1 < samples.size() ) - { - processedSamples.push_back( linearObjectInterpolation( samples[i].get(), samples[i+1].get(), 0.5f ) ); - processedTimes.push_back( Imath::lerp( times[i], times[i+1], 0.5f ) ); - } - } - return convert( processedSamples, processedTimes, session ); - } - const IECore::Object *firstSample = samples.front().get(); const IECore::TypeId firstSampleTypeId = firstSample->typeId(); for( const auto &sample : samples ) @@ -290,7 +265,7 @@ ccl::Geometry *convert( const IECoreScenePreview::Renderer::ObjectSamples &sampl // Cycles expects the middle sample (rounding down for even numbers of // samples) to be specified as the main sample, and the other samples to // be provided via ATTR_STD_MOTION_VERTEX_POSITION. - return it->second( samples, times, (samples.size() - 1) / 2, session->scene.get() ); + return it->second( samples, times, (samples.size() - 1) / 2, scene ); } void registerConverter( IECore::TypeId fromType, Converter converter ) diff --git a/src/GafferCycles/IECoreCyclesPreview/Renderer.cpp b/src/GafferCycles/IECoreCyclesPreview/Renderer.cpp index de96d2bf755..ee305ada8c3 100644 --- a/src/GafferCycles/IECoreCyclesPreview/Renderer.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/Renderer.cpp @@ -1454,8 +1454,8 @@ class GeometryCache public : - GeometryCache( ccl::Session *session, NodeDeleter *nodeDeleter ) - : m_session( session ), m_nodeDeleter( nodeDeleter ) + GeometryCache( ccl::Scene *scene, NodeDeleter *nodeDeleter ) + : m_scene( scene ), m_nodeDeleter( nodeDeleter ) { } @@ -1527,7 +1527,7 @@ class GeometryCache const std::string &nodeName ) { - auto geometry = SharedGeometryPtr( GeometryAlgo::convert( samples, times, m_session ), NodeDeleter::GeometryDeleter( m_nodeDeleter ) ); + auto geometry = SharedGeometryPtr( GeometryAlgo::convert( samples, times, m_scene ), NodeDeleter::GeometryDeleter( m_nodeDeleter ) ); if( geometry ) { geometry->name = ccl::ustring( nodeName.c_str() ); @@ -1536,13 +1536,13 @@ class GeometryCache if( auto vdb = IECore::runTimeCast( samples.front().get() ) ) { assert( geometry->is_volume() ); - GeometryAlgo::convertVoxelGrids( vdb, static_cast( geometry.get() ), m_session->scene.get(), attributes->getVolumePrecision(), attributes->getVolumeClipping() ); + GeometryAlgo::convertVoxelGrids( vdb, static_cast( geometry.get() ), m_scene, attributes->getVolumePrecision(), attributes->getVolumeClipping() ); } return geometry; } - ccl::Session *m_session; + ccl::Scene *m_scene; NodeDeleter *m_nodeDeleter; using Geometry = tbb::concurrent_hash_map; Geometry m_geometry; @@ -2790,7 +2790,7 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer } m_shaderCache = std::make_unique( m_scene ); - m_geometryCache = std::make_unique( m_session.get(), m_nodeDeleter.get() ); + m_geometryCache = std::make_unique( m_scene, m_nodeDeleter.get() ); m_attributesCache = std::make_unique( m_shaderCache.get() ); } From 98f1233fe2dde84d097d0f6285ca7008e5976df8 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Wed, 6 May 2026 10:44:33 -0700 Subject: [PATCH 9/9] Cycles MeshAlgo : Remove unused includes --- src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp b/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp index 9d5eb11e421..142802709cb 100644 --- a/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp +++ b/src/GafferCycles/IECoreCyclesPreview/MeshAlgo.cpp @@ -39,15 +39,10 @@ #include "IECoreScene/MeshPrimitive.h" #include "IECoreScene/MeshAlgo.h" -#include "IECore/Interpolator.h" -#include "IECore/SimpleTypedData.h" - // Cycles #include "kernel/types.h" #include "scene/geometry.h" #include "scene/mesh.h" -#include "subd/dice.h" -#include "util/param.h" #include "util/types.h" #include "fmt/format.h"