@@ -811,26 +811,37 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
811
811
}
812
812
813
813
template <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 = " " )
815
815
{
816
816
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
+
817
823
if ( spline.basis == Spline::Basis::bezier () )
818
824
{
819
825
basis = " bezier" ;
820
826
}
821
827
else if ( spline.basis == Spline::Basis::bSpline () )
822
828
{
823
829
basis = " bspline" ;
830
+ riBasis = " bspline" ;
824
831
}
825
832
else if ( spline.basis == Spline::Basis::linear () )
826
833
{
827
834
basis = " linear" ;
835
+ riBasis = " linear" ;
836
+ aiBasisIdx = 1 ;
828
837
}
829
838
else if ( spline.basis == Spline::Basis::constant () )
830
839
{
831
840
// Also, "To maintain consistency", "constant splines ignore the first and the two last
832
841
// data values."
833
842
basis = " constant" ;
843
+ riBasis = " constant" ;
844
+ aiBasisIdx = 0 ;
834
845
}
835
846
auto [ duplicateStartPoints, duplicateEndPoints ] = getEndPointDuplication ( spline.basis );
836
847
@@ -843,7 +854,7 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
843
854
auto &values = valuesData->writable ();
844
855
values.reserve ( spline.points .size () + duplicateStartPoints + duplicateEndPoints );
845
856
846
- if ( spline.points .size () )
857
+ if ( spline.points .size () && !isArnold )
847
858
{
848
859
for ( size_t i = 0 ; i < duplicateStartPoints; i++ )
849
860
{
@@ -856,7 +867,7 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
856
867
positions.push_back ( it->first );
857
868
values.push_back ( it->second );
858
869
}
859
- if ( spline.points .size () )
870
+ if ( spline.points .size () && !isArnold )
860
871
{
861
872
for ( size_t i = 0 ; i < duplicateEndPoints; i++ )
862
873
{
@@ -865,16 +876,50 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
865
876
}
866
877
}
867
878
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
+ }
871
915
}
872
916
873
917
template <typename SplineData>
874
918
IECore::DataPtr loadSpline (
875
919
const StringData *basisData,
876
920
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
878
923
)
879
924
{
880
925
typename SplineData::Ptr resultData = new SplineData ();
@@ -895,15 +940,21 @@ IECore::DataPtr loadSpline(
895
940
else if ( basis == " linear" )
896
941
{
897
942
// 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
+ }
900
948
result.basis = SplineData::ValueType::Basis::linear ();
901
949
}
902
950
else if ( basis == " constant" )
903
951
{
904
952
// 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
+ }
907
958
result.basis = SplineData::ValueType::Basis::constant ();
908
959
}
909
960
else
@@ -1039,7 +1090,7 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
1039
1090
}
1040
1091
1041
1092
// 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 () );
1043
1094
if ( collapsed != shader->parametersData () )
1044
1095
{
1045
1096
// \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
1166
1217
{
1167
1218
ensureParametersCopy ( origParameters, newParametersData, newParameters );
1168
1219
newParameters->erase ( name );
1169
- expandSpline ( name, colorSpline->readable (), *newParameters );
1220
+ expandSpline ( name, colorSpline->readable (), *newParameters, s. second -> getType (), s. second -> getName () );
1170
1221
}
1171
1222
else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get () ) )
1172
1223
{
1173
1224
ensureParametersCopy ( origParameters, newParametersData, newParameters );
1174
1225
newParameters->erase ( name );
1175
- expandSpline ( name, floatSpline->readable (), *newParameters );
1226
+ expandSpline ( name, floatSpline->readable (), *newParameters, s. second -> getType (), s. second -> getName () );
1176
1227
}
1177
1228
}
1178
1229
@@ -1288,27 +1339,80 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
1288
1339
}
1289
1340
}
1290
1341
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 )
1292
1343
{
1293
1344
const CompoundDataMap ¶meters ( parametersData->readable () );
1294
1345
CompoundDataPtr newParametersData;
1295
1346
CompoundDataMap *newParameters = nullptr ;
1296
1347
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
+
1297
1376
for ( const auto &maybeBasis : parameters )
1298
1377
{
1299
- if ( !boost::ends_with ( maybeBasis.first .string (), " Basis " ) )
1378
+ if ( !boost::ends_with ( maybeBasis.first .string (), basisStr ) )
1300
1379
{
1301
1380
continue ;
1302
1381
}
1303
- const StringData *basis = runTimeCast<const StringData>( maybeBasis.second .get () );
1382
+ StringDataPtr basisPtr;
1383
+ const StringData *basis = runTimeCast<StringData>( maybeBasis.second .get () );
1304
1384
if ( !basis )
1305
1385
{
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 ();
1307
1412
}
1308
1413
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;
1312
1416
const auto positionsIter = parameters.find ( positionsName );
1313
1417
const FloatVectorData *floatPositions = nullptr ;
1314
1418
@@ -1322,30 +1426,41 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
1322
1426
continue ;
1323
1427
}
1324
1428
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
+ }
1327
1436
1328
1437
IECore::DataPtr foundSpline;
1329
1438
if ( valuesIter != parameters.end () )
1330
1439
{
1331
1440
if ( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second .get () ) )
1332
1441
{
1333
- foundSpline = loadSpline<SplineffData>( basis , floatPositions, floatValues );
1442
+ foundSpline = loadSpline<SplineffData>( basisPtr. get () , floatPositions, floatValues, unduplicatePoints );
1334
1443
}
1335
1444
else if ( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second .get () ) )
1336
1445
{
1337
- foundSpline = loadSpline<SplinefColor3fData>( basis , floatPositions, color3Values );
1446
+ foundSpline = loadSpline<SplinefColor3fData>( basisPtr. get () , floatPositions, color3Values, unduplicatePoints );
1338
1447
}
1339
1448
else if ( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second .get () ) )
1340
1449
{
1341
- foundSpline = loadSpline<SplinefColor4fData>( basis , floatPositions, color4Values );
1450
+ foundSpline = loadSpline<SplinefColor4fData>( basisPtr. get () , floatPositions, color4Values, unduplicatePoints );
1342
1451
}
1343
1452
}
1344
1453
1345
1454
if ( foundSpline )
1346
1455
{
1347
1456
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;
1349
1464
newParameters->erase ( maybeBasis.first );
1350
1465
newParameters->erase ( positionsName );
1351
1466
newParameters->erase ( valuesName );
@@ -1362,7 +1477,7 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const
1362
1477
}
1363
1478
}
1364
1479
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 )
1366
1481
{
1367
1482
const CompoundDataMap ¶meters ( parametersData->readable () );
1368
1483
@@ -1375,13 +1490,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
1375
1490
{
1376
1491
ensureParametersCopy ( parameters, newParametersData, newParameters );
1377
1492
newParameters->erase ( i.first );
1378
- expandSpline ( i.first , colorSpline->readable (), *newParameters );
1493
+ expandSpline ( i.first , colorSpline->readable (), *newParameters, shaderType, shaderName );
1379
1494
}
1380
1495
else if ( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second .get () ) )
1381
1496
{
1382
1497
ensureParametersCopy ( parameters, newParametersData, newParameters );
1383
1498
newParameters->erase ( i.first );
1384
- expandSpline ( i.first , floatSpline->readable (), *newParameters );
1499
+ expandSpline ( i.first , floatSpline->readable (), *newParameters, shaderType, shaderName );
1385
1500
}
1386
1501
}
1387
1502
0 commit comments