@@ -812,26 +812,37 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
812812}
813813
814814template <typename Spline>
815- void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters )
815+ void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters, const std::string shaderType = " " , const std::string shaderName = " " )
816816{
817817 const char *basis = " catmull-rom" ;
818+ // For Renderman see https://rmanwiki-26.pixar.com/space/REN26/19661691/PxrRamp
819+ const char *riBasis = " catmull-rom" ;
820+ // For Arnold see https://help.autodesk.com/view/ARNOL/ENU/?guid=arnold_user_guide_ac_texture_shaders_ac_texture_ramp_html
821+ int aiBasisIdx = 2 ;
822+ const bool isArnold = boost::starts_with ( shaderType, " ai:" );
823+
818824 if ( spline.basis == Spline::Basis::bezier () )
819825 {
820826 basis = " bezier" ;
821827 }
822828 else if ( spline.basis == Spline::Basis::bSpline () )
823829 {
824830 basis = " bspline" ;
831+ riBasis = " bspline" ;
825832 }
826833 else if ( spline.basis == Spline::Basis::linear () )
827834 {
828835 basis = " linear" ;
836+ riBasis = " linear" ;
837+ aiBasisIdx = 1 ;
829838 }
830839 else if ( spline.basis == Spline::Basis::constant () )
831840 {
832841 // Also, "To maintain consistency", "constant splines ignore the first and the two last
833842 // data values."
834843 basis = " constant" ;
844+ riBasis = " constant" ;
845+ aiBasisIdx = 0 ;
835846 }
836847 auto [ duplicateStartPoints, duplicateEndPoints ] = getEndPointDuplication ( spline.basis );
837848
@@ -844,7 +855,7 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
844855 auto &values = valuesData->writable ();
845856 values.reserve ( spline.points .size () + duplicateStartPoints + duplicateEndPoints );
846857
847- if ( spline.points .size () )
858+ if ( spline.points .size () && !isArnold )
848859 {
849860 for ( size_t i = 0 ; i < duplicateStartPoints; i++ )
850861 {
@@ -857,7 +868,7 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
857868 positions.push_back ( it->first );
858869 values.push_back ( it->second );
859870 }
860- if ( spline.points .size () )
871+ if ( spline.points .size () && !isArnold )
861872 {
862873 for ( size_t i = 0 ; i < duplicateEndPoints; i++ )
863874 {
@@ -866,16 +877,50 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
866877 }
867878 }
868879
869- newParameters[ name.string () + " Positions" ] = positionsData;
870- newParameters[ name.string () + " Values" ] = valuesData;
871- newParameters[ name.string () + " Basis" ] = new StringData ( basis );
880+ if ( isArnold && ( shaderName == " ramp_float" || shaderName == " ramp_rgb" ) )
881+ {
882+ newParameters[ " position" ] = positionsData;
883+ if constexpr ( std::is_same_v<Spline, SplinefColor3f> )
884+ {
885+ newParameters[ " color" ] = valuesData;
886+ }
887+ else
888+ {
889+ newParameters[ " value" ] = valuesData;
890+ }
891+ std::vector<int > interp;
892+ interp.resize ( spline.points .size () );
893+ std::fill ( interp.begin (), interp.end (), aiBasisIdx );
894+ newParameters[ " interpolation" ] = new IntVectorData ( interp );
895+ }
896+ // Intentionally OR'd here as many Renderman shaders are OSL so search for the 'Pxr' prefix.
897+ else if ( boost::starts_with ( shaderType, " ri:" ) || ( boost::starts_with ( shaderName, " Pxr" ) ) )
898+ {
899+ newParameters[ name.string () + " _Knots" ] = positionsData;
900+ if constexpr ( std::is_same_v<Spline, SplinefColor3f> )
901+ {
902+ newParameters[ name.string () + " _Colors" ] = valuesData;
903+ }
904+ else
905+ {
906+ newParameters[ name.string () + " _Floats" ] = valuesData;
907+ }
908+ newParameters[ name.string () + " _Interpolation" ] = new StringData ( riBasis );
909+ }
910+ else
911+ {
912+ newParameters[ name.string () + " Positions" ] = positionsData;
913+ newParameters[ name.string () + " Values" ] = valuesData;
914+ newParameters[ name.string () + " Basis" ] = new StringData ( basis );
915+ }
872916}
873917
874918template <typename SplineData>
875919IECore::DataPtr loadSpline (
876920 const StringData *basisData,
877921 const IECore::TypedData< std::vector< typename SplineData::ValueType::XType > > *positionsData,
878- const IECore::TypedData< std::vector< typename SplineData::ValueType::YType > > *valuesData
922+ const IECore::TypedData< std::vector< typename SplineData::ValueType::YType > > *valuesData,
923+ const bool unduplicatePoints = true
879924)
880925{
881926 typename SplineData::Ptr resultData = new SplineData ();
@@ -896,15 +941,21 @@ IECore::DataPtr loadSpline(
896941 else if ( basis == " linear" )
897942 {
898943 // Reverse the duplication we do when expanding splines
899- unduplicateStartPoints = 1 ;
900- unduplicateEndPoints = 1 ;
944+ if ( unduplicatePoints )
945+ {
946+ unduplicateStartPoints = 1 ;
947+ unduplicateEndPoints = 1 ;
948+ }
901949 result.basis = SplineData::ValueType::Basis::linear ();
902950 }
903951 else if ( basis == " constant" )
904952 {
905953 // Reverse the duplication we do when expanding splines
906- unduplicateStartPoints = 1 ;
907- unduplicateEndPoints = 2 ;
954+ if ( unduplicatePoints )
955+ {
956+ unduplicateStartPoints = 1 ;
957+ unduplicateEndPoints = 2 ;
958+ }
908959 result.basis = SplineData::ValueType::Basis::constant ();
909960 }
910961 else
@@ -1040,7 +1091,7 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
10401091 }
10411092
10421093 // For nodes which aren't spline adapters, we just need to deal with any parameters that are splines
1043- ConstCompoundDataPtr collapsed = collapseSplineParameters ( shader->parametersData () );
1094+ ConstCompoundDataPtr collapsed = collapseSplineParameters ( shader->parametersData (), shader-> getType (), shader-> getName () );
10441095 if ( collapsed != shader->parametersData () )
10451096 {
10461097 // \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameters
@@ -1167,13 +1218,13 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
11671218 {
11681219 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11691220 newParameters->erase ( name );
1170- expandSpline ( name, colorSpline->readable (), *newParameters );
1221+ expandSpline ( name, colorSpline->readable (), *newParameters, s. second -> getType (), s. second -> getName () );
11711222 }
11721223 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get () ) )
11731224 {
11741225 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11751226 newParameters->erase ( name );
1176- expandSpline ( name, floatSpline->readable (), *newParameters );
1227+ expandSpline ( name, floatSpline->readable (), *newParameters, s. second -> getType (), s. second -> getName () );
11771228 }
11781229 }
11791230
@@ -1289,27 +1340,80 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
12891340 }
12901341}
12911342
1292- IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
1343+ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData, const std::string shaderType, const std::string shaderName )
12931344{
12941345 const CompoundDataMap ¶meters ( parametersData->readable () );
12951346 CompoundDataPtr newParametersData;
12961347 CompoundDataMap *newParameters = nullptr ;
12971348
1349+ std::string basisStr = " Basis" ;
1350+ std::string positionsStr = " Positions" ;
1351+ std::string valuesStr = " Values" ;
1352+
1353+ const bool isArnold = boost::starts_with ( shaderType, " ai:" );
1354+ const bool isRenderman = boost::starts_with ( shaderType, " ri:" ) || boost::starts_with ( shaderName, " Pxr" );
1355+ const bool unduplicatePoints = !isArnold;
1356+
1357+ if ( isArnold && ( shaderName == " ramp_float" || shaderName == " ramp_rgb" ) )
1358+ {
1359+ basisStr = " interpolation" ;
1360+ positionsStr = " position" ;
1361+ if ( shaderName == " ramp_rgb" )
1362+ {
1363+ valuesStr = " color" ;
1364+ }
1365+ else
1366+ {
1367+ valuesStr = " value" ;
1368+ }
1369+ }
1370+ else if ( isRenderman )
1371+ {
1372+ basisStr = " _Interpolation" ;
1373+ positionsStr = " _Knots" ;
1374+ valuesStr = " _Floats" ;
1375+ }
1376+
12981377 for ( const auto &maybeBasis : parameters )
12991378 {
1300- if ( !boost::ends_with ( maybeBasis.first .string (), " Basis " ) )
1379+ if ( !boost::ends_with ( maybeBasis.first .string (), basisStr ) )
13011380 {
13021381 continue ;
13031382 }
1304- const StringData *basis = runTimeCast<const StringData>( maybeBasis.second .get () );
1383+ StringDataPtr basisPtr;
1384+ const StringData *basis = runTimeCast<StringData>( maybeBasis.second .get () );
13051385 if ( !basis )
13061386 {
1307- continue ;
1387+ const IntVectorData *intBasis = runTimeCast<const IntVectorData>( maybeBasis.second .get () );
1388+ if ( !intBasis )
1389+ {
1390+ continue ;
1391+ }
1392+ // Do int to string conversion here, using the first value of the interpolation array
1393+ if ( intBasis->readable ().front () == 0 )
1394+ {
1395+ basisPtr = new StringData ( " constant" );
1396+ }
1397+ else if ( intBasis->readable ().front () == 1 )
1398+ {
1399+ basisPtr = new StringData ( " linear" );
1400+ }
1401+ else if ( intBasis->readable ().front () == 3 )
1402+ {
1403+ basisPtr = new StringData ( " monotonecubic" );
1404+ }
1405+ else
1406+ {
1407+ basisPtr = new StringData ( " catmull-rom" );
1408+ }
1409+ }
1410+ else
1411+ {
1412+ basisPtr = basis->copy ();
13081413 }
13091414
1310-
1311- std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - 5 );
1312- IECore::InternedString positionsName = prefix + " Positions" ;
1415+ std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - basisStr.size () );
1416+ IECore::InternedString positionsName = prefix + positionsStr;
13131417 const auto positionsIter = parameters.find ( positionsName );
13141418 const FloatVectorData *floatPositions = nullptr ;
13151419
@@ -1323,30 +1427,41 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
13231427 continue ;
13241428 }
13251429
1326- IECore::InternedString valuesName = prefix + " Values" ;
1327- const auto valuesIter = parameters.find ( valuesName );
1430+ IECore::InternedString valuesName = prefix + valuesStr;
1431+ auto valuesIter = parameters.find ( valuesName );
1432+ if ( valuesIter == parameters.end () && isRenderman )
1433+ {
1434+ valuesName = prefix + " _Colors" ;
1435+ valuesIter = parameters.find ( valuesName );
1436+ }
13281437
13291438 IECore::DataPtr foundSpline;
13301439 if ( valuesIter != parameters.end () )
13311440 {
13321441 if ( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second .get () ) )
13331442 {
1334- foundSpline = loadSpline<SplineffData>( basis , floatPositions, floatValues );
1443+ foundSpline = loadSpline<SplineffData>( basisPtr. get () , floatPositions, floatValues, unduplicatePoints );
13351444 }
13361445 else if ( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second .get () ) )
13371446 {
1338- foundSpline = loadSpline<SplinefColor3fData>( basis , floatPositions, color3Values );
1447+ foundSpline = loadSpline<SplinefColor3fData>( basisPtr. get () , floatPositions, color3Values, unduplicatePoints );
13391448 }
13401449 else if ( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second .get () ) )
13411450 {
1342- foundSpline = loadSpline<SplinefColor4fData>( basis , floatPositions, color4Values );
1451+ foundSpline = loadSpline<SplinefColor4fData>( basisPtr. get () , floatPositions, color4Values, unduplicatePoints );
13431452 }
13441453 }
13451454
13461455 if ( foundSpline )
13471456 {
13481457 ensureParametersCopy ( parameters, newParametersData, newParameters );
1349- (*newParameters)[prefix] = foundSpline;
1458+ // Arnold ramp_rgb/ramp_float has no prefix so ensure we have a parameter name to set
1459+ std::string newParamName ( " ramp" );
1460+ if ( !prefix.empty () )
1461+ {
1462+ newParamName = prefix;
1463+ }
1464+ (*newParameters)[newParamName] = foundSpline;
13501465 newParameters->erase ( maybeBasis.first );
13511466 newParameters->erase ( positionsName );
13521467 newParameters->erase ( valuesName );
@@ -1363,7 +1478,7 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
13631478 }
13641479}
13651480
1366- IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
1481+ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData, const std::string shaderType, const std::string shaderName )
13671482{
13681483 const CompoundDataMap ¶meters ( parametersData->readable () );
13691484
@@ -1376,13 +1491,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
13761491 {
13771492 ensureParametersCopy ( parameters, newParametersData, newParameters );
13781493 newParameters->erase ( i.first );
1379- expandSpline ( i.first , colorSpline->readable (), *newParameters );
1494+ expandSpline ( i.first , colorSpline->readable (), *newParameters, shaderType, shaderName );
13801495 }
13811496 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second .get () ) )
13821497 {
13831498 ensureParametersCopy ( parameters, newParametersData, newParameters );
13841499 newParameters->erase ( i.first );
1385- expandSpline ( i.first , floatSpline->readable (), *newParameters );
1500+ expandSpline ( i.first , floatSpline->readable (), *newParameters, shaderType, shaderName );
13861501 }
13871502 }
13881503
0 commit comments