@@ -811,26 +811,37 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
811811}
812812
813813template <typename Spline>
814- void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters )
814+ void expandSpline ( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters, const std::string shaderType = " " , const std::string shaderName = " " )
815815{
816816 const char *basis = " catmull-rom" ;
817+ // For Renderman see https://rmanwiki-26.pixar.com/space/REN26/19661691/PxrRamp
818+ const char *riBasis = " catmull-rom" ;
819+ // For Arnold see https://help.autodesk.com/view/ARNOL/ENU/?guid=arnold_user_guide_ac_texture_shaders_ac_texture_ramp_html
820+ int aiBasisIdx = 2 ;
821+ const bool isArnold = boost::starts_with ( shaderType, " ai:" );
822+
817823 if ( spline.basis == Spline::Basis::bezier () )
818824 {
819825 basis = " bezier" ;
820826 }
821827 else if ( spline.basis == Spline::Basis::bSpline () )
822828 {
823829 basis = " bspline" ;
830+ riBasis = " bspline" ;
824831 }
825832 else if ( spline.basis == Spline::Basis::linear () )
826833 {
827834 basis = " linear" ;
835+ riBasis = " linear" ;
836+ aiBasisIdx = 1 ;
828837 }
829838 else if ( spline.basis == Spline::Basis::constant () )
830839 {
831840 // Also, "To maintain consistency", "constant splines ignore the first and the two last
832841 // data values."
833842 basis = " constant" ;
843+ riBasis = " constant" ;
844+ aiBasisIdx = 0 ;
834845 }
835846 auto [ duplicateStartPoints, duplicateEndPoints ] = getEndPointDuplication ( spline.basis );
836847
@@ -843,7 +854,7 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
843854 auto &values = valuesData->writable ();
844855 values.reserve ( spline.points .size () + duplicateStartPoints + duplicateEndPoints );
845856
846- if ( spline.points .size () )
857+ if ( spline.points .size () && !isArnold )
847858 {
848859 for ( size_t i = 0 ; i < duplicateStartPoints; i++ )
849860 {
@@ -856,7 +867,7 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
856867 positions.push_back ( it->first );
857868 values.push_back ( it->second );
858869 }
859- if ( spline.points .size () )
870+ if ( spline.points .size () && !isArnold )
860871 {
861872 for ( size_t i = 0 ; i < duplicateEndPoints; i++ )
862873 {
@@ -865,16 +876,50 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
865876 }
866877 }
867878
868- newParameters[ name.string () + " Positions" ] = positionsData;
869- newParameters[ name.string () + " Values" ] = valuesData;
870- newParameters[ name.string () + " Basis" ] = new StringData ( basis );
879+ if ( isArnold && ( shaderName == " ramp_float" || shaderName == " ramp_rgb" ) )
880+ {
881+ newParameters[ " position" ] = positionsData;
882+ if constexpr ( std::is_same_v<Spline, SplinefColor3f> )
883+ {
884+ newParameters[ " color" ] = valuesData;
885+ }
886+ else
887+ {
888+ newParameters[ " value" ] = valuesData;
889+ }
890+ std::vector<int > interp;
891+ interp.resize ( spline.points .size () );
892+ std::fill ( interp.begin (), interp.end (), aiBasisIdx );
893+ newParameters[ " interpolation" ] = new IntVectorData ( interp );
894+ }
895+ // Intentionally OR'd here as many Renderman shaders are OSL so search for the 'Pxr' prefix.
896+ else if ( boost::starts_with ( shaderType, " ri:" ) || ( boost::starts_with ( shaderName, " Pxr" ) ) )
897+ {
898+ newParameters[ name.string () + " _Knots" ] = positionsData;
899+ if constexpr ( std::is_same_v<Spline, SplinefColor3f> )
900+ {
901+ newParameters[ name.string () + " _Colors" ] = valuesData;
902+ }
903+ else
904+ {
905+ newParameters[ name.string () + " _Floats" ] = valuesData;
906+ }
907+ newParameters[ name.string () + " _Interpolation" ] = new StringData ( riBasis );
908+ }
909+ else
910+ {
911+ newParameters[ name.string () + " Positions" ] = positionsData;
912+ newParameters[ name.string () + " Values" ] = valuesData;
913+ newParameters[ name.string () + " Basis" ] = new StringData ( basis );
914+ }
871915}
872916
873917template <typename SplineData>
874918IECore::DataPtr loadSpline (
875919 const StringData *basisData,
876920 const IECore::TypedData< std::vector< typename SplineData::ValueType::XType > > *positionsData,
877- const IECore::TypedData< std::vector< typename SplineData::ValueType::YType > > *valuesData
921+ const IECore::TypedData< std::vector< typename SplineData::ValueType::YType > > *valuesData,
922+ const bool unduplicatePoints = true
878923)
879924{
880925 typename SplineData::Ptr resultData = new SplineData ();
@@ -895,15 +940,21 @@ IECore::DataPtr loadSpline(
895940 else if ( basis == " linear" )
896941 {
897942 // Reverse the duplication we do when expanding splines
898- unduplicateStartPoints = 1 ;
899- unduplicateEndPoints = 1 ;
943+ if ( unduplicatePoints )
944+ {
945+ unduplicateStartPoints = 1 ;
946+ unduplicateEndPoints = 1 ;
947+ }
900948 result.basis = SplineData::ValueType::Basis::linear ();
901949 }
902950 else if ( basis == " constant" )
903951 {
904952 // Reverse the duplication we do when expanding splines
905- unduplicateStartPoints = 1 ;
906- unduplicateEndPoints = 2 ;
953+ if ( unduplicatePoints )
954+ {
955+ unduplicateStartPoints = 1 ;
956+ unduplicateEndPoints = 2 ;
957+ }
907958 result.basis = SplineData::ValueType::Basis::constant ();
908959 }
909960 else
@@ -1039,7 +1090,7 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
10391090 }
10401091
10411092 // For nodes which aren't spline adapters, we just need to deal with any parameters that are splines
1042- ConstCompoundDataPtr collapsed = collapseSplineParameters ( shader->parametersData () );
1093+ ConstCompoundDataPtr collapsed = collapseSplineParameters ( shader->parametersData (), shader-> getType (), shader-> getName () );
10431094 if ( collapsed != shader->parametersData () )
10441095 {
10451096 // \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameters
@@ -1166,13 +1217,13 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
11661217 {
11671218 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11681219 newParameters->erase ( name );
1169- expandSpline ( name, colorSpline->readable (), *newParameters );
1220+ expandSpline ( name, colorSpline->readable (), *newParameters, s. second -> getType (), s. second -> getName () );
11701221 }
11711222 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get () ) )
11721223 {
11731224 ensureParametersCopy ( origParameters, newParametersData, newParameters );
11741225 newParameters->erase ( name );
1175- expandSpline ( name, floatSpline->readable (), *newParameters );
1226+ expandSpline ( name, floatSpline->readable (), *newParameters, s. second -> getType (), s. second -> getName () );
11761227 }
11771228 }
11781229
@@ -1288,27 +1339,80 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
12881339 }
12891340}
12901341
1291- IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
1342+ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData, const std::string shaderType, const std::string shaderName )
12921343{
12931344 const CompoundDataMap ¶meters ( parametersData->readable () );
12941345 CompoundDataPtr newParametersData;
12951346 CompoundDataMap *newParameters = nullptr ;
12961347
1348+ std::string basisStr = " Basis" ;
1349+ std::string positionsStr = " Positions" ;
1350+ std::string valuesStr = " Values" ;
1351+
1352+ const bool isArnold = boost::starts_with ( shaderType, " ai:" );
1353+ const bool isRenderman = boost::starts_with ( shaderType, " ri:" ) || boost::starts_with ( shaderName, " Pxr" );
1354+ const bool unduplicatePoints = !isArnold;
1355+
1356+ if ( isArnold && ( shaderName == " ramp_float" || shaderName == " ramp_rgb" ) )
1357+ {
1358+ basisStr = " interpolation" ;
1359+ positionsStr = " position" ;
1360+ if ( shaderName == " ramp_rgb" )
1361+ {
1362+ valuesStr = " color" ;
1363+ }
1364+ else
1365+ {
1366+ valuesStr = " value" ;
1367+ }
1368+ }
1369+ else if ( isRenderman )
1370+ {
1371+ basisStr = " _Interpolation" ;
1372+ positionsStr = " _Knots" ;
1373+ valuesStr = " _Floats" ;
1374+ }
1375+
12971376 for ( const auto &maybeBasis : parameters )
12981377 {
1299- if ( !boost::ends_with ( maybeBasis.first .string (), " Basis " ) )
1378+ if ( !boost::ends_with ( maybeBasis.first .string (), basisStr ) )
13001379 {
13011380 continue ;
13021381 }
1303- const StringData *basis = runTimeCast<const StringData>( maybeBasis.second .get () );
1382+ StringDataPtr basisPtr;
1383+ const StringData *basis = runTimeCast<StringData>( maybeBasis.second .get () );
13041384 if ( !basis )
13051385 {
1306- continue ;
1386+ const IntVectorData *intBasis = runTimeCast<const IntVectorData>( maybeBasis.second .get () );
1387+ if ( !intBasis )
1388+ {
1389+ continue ;
1390+ }
1391+ // Do int to string conversion here, using the first value of the interpolation array
1392+ if ( intBasis->readable ().front () == 0 )
1393+ {
1394+ basisPtr = new StringData ( " constant" );
1395+ }
1396+ else if ( intBasis->readable ().front () == 1 )
1397+ {
1398+ basisPtr = new StringData ( " linear" );
1399+ }
1400+ else if ( intBasis->readable ().front () == 3 )
1401+ {
1402+ basisPtr = new StringData ( " monotonecubic" );
1403+ }
1404+ else
1405+ {
1406+ basisPtr = new StringData ( " catmull-rom" );
1407+ }
1408+ }
1409+ else
1410+ {
1411+ basisPtr = basis->copy ();
13071412 }
13081413
1309-
1310- std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - 5 );
1311- IECore::InternedString positionsName = prefix + " Positions" ;
1414+ std::string prefix = maybeBasis.first .string ().substr ( 0 , maybeBasis.first .string ().size () - basisStr.size () );
1415+ IECore::InternedString positionsName = prefix + positionsStr;
13121416 const auto positionsIter = parameters.find ( positionsName );
13131417 const FloatVectorData *floatPositions = nullptr ;
13141418
@@ -1322,30 +1426,41 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
13221426 continue ;
13231427 }
13241428
1325- IECore::InternedString valuesName = prefix + " Values" ;
1326- const auto valuesIter = parameters.find ( valuesName );
1429+ IECore::InternedString valuesName = prefix + valuesStr;
1430+ auto valuesIter = parameters.find ( valuesName );
1431+ if ( valuesIter == parameters.end () && isRenderman )
1432+ {
1433+ valuesName = prefix + " _Colors" ;
1434+ valuesIter = parameters.find ( valuesName );
1435+ }
13271436
13281437 IECore::DataPtr foundSpline;
13291438 if ( valuesIter != parameters.end () )
13301439 {
13311440 if ( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second .get () ) )
13321441 {
1333- foundSpline = loadSpline<SplineffData>( basis , floatPositions, floatValues );
1442+ foundSpline = loadSpline<SplineffData>( basisPtr. get () , floatPositions, floatValues, unduplicatePoints );
13341443 }
13351444 else if ( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second .get () ) )
13361445 {
1337- foundSpline = loadSpline<SplinefColor3fData>( basis , floatPositions, color3Values );
1446+ foundSpline = loadSpline<SplinefColor3fData>( basisPtr. get () , floatPositions, color3Values, unduplicatePoints );
13381447 }
13391448 else if ( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second .get () ) )
13401449 {
1341- foundSpline = loadSpline<SplinefColor4fData>( basis , floatPositions, color4Values );
1450+ foundSpline = loadSpline<SplinefColor4fData>( basisPtr. get () , floatPositions, color4Values, unduplicatePoints );
13421451 }
13431452 }
13441453
13451454 if ( foundSpline )
13461455 {
13471456 ensureParametersCopy ( parameters, newParametersData, newParameters );
1348- (*newParameters)[prefix] = foundSpline;
1457+ // Arnold ramp_rgb/ramp_float has no prefix so ensure we have a parameter name to set
1458+ std::string newParamName ( " ramp" );
1459+ if ( !prefix.empty () )
1460+ {
1461+ newParamName = prefix;
1462+ }
1463+ (*newParameters)[newParamName] = foundSpline;
13491464 newParameters->erase ( maybeBasis.first );
13501465 newParameters->erase ( positionsName );
13511466 newParameters->erase ( valuesName );
@@ -1362,7 +1477,7 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
13621477 }
13631478}
13641479
1365- IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData )
1480+ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters ( const IECore::ConstCompoundDataPtr ¶metersData, const std::string shaderType, const std::string shaderName )
13661481{
13671482 const CompoundDataMap ¶meters ( parametersData->readable () );
13681483
@@ -1375,13 +1490,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
13751490 {
13761491 ensureParametersCopy ( parameters, newParametersData, newParameters );
13771492 newParameters->erase ( i.first );
1378- expandSpline ( i.first , colorSpline->readable (), *newParameters );
1493+ expandSpline ( i.first , colorSpline->readable (), *newParameters, shaderType, shaderName );
13791494 }
13801495 else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second .get () ) )
13811496 {
13821497 ensureParametersCopy ( parameters, newParametersData, newParameters );
13831498 newParameters->erase ( i.first );
1384- expandSpline ( i.first , floatSpline->readable (), *newParameters );
1499+ expandSpline ( i.first , floatSpline->readable (), *newParameters, shaderType, shaderName );
13851500 }
13861501 }
13871502
0 commit comments