Skip to content

Commit 6e7f9fd

Browse files
author
Alex Fuller
committed
IECoreScene : Spline ramp conversions for Arnold and Renderman native shaders.
1 parent af7fe11 commit 6e7f9fd

File tree

4 files changed

+218
-36
lines changed

4 files changed

+218
-36
lines changed

include/IECoreScene/ShaderNetworkAlgo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,10 @@ IECORESCENE_API void expandSplines( ShaderNetwork *network, std::string targetPr
149149

150150

151151
/// \deprecated: Use collapseSplines on the whole network, which can handle input connections
152-
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
152+
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parametersData, const std::string shaderType = "", const std::string shaderName = "" );
153153

154154
/// \deprecated: Use expandSplines on the whole network, which can handle input connections
155-
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
155+
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData, const std::string shaderType = "", const std::string shaderName = "" );
156156

157157

158158
} // namespace ShaderNetworkAlgo

src/IECoreScene/ShaderNetworkAlgo.cpp

Lines changed: 145 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -811,26 +811,37 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
811811
}
812812

813813
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 = "" )
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

873917
template<typename SplineData>
874918
IECore::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 &parametersData )
1342+
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const IECore::ConstCompoundDataPtr &parametersData, const std::string shaderType, const std::string shaderName )
12921343
{
12931344
const CompoundDataMap &parameters( 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 &parametersData )
1480+
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IECore::ConstCompoundDataPtr &parametersData, const std::string shaderType, const std::string shaderName )
13661481
{
13671482
const CompoundDataMap &parameters( 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

src/IECoreScene/bindings/ShaderNetworkAlgoBinding.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ void convertOSLComponentConnectionsWrapper( ShaderNetwork *network, int oslVersi
7070
ShaderNetworkAlgo::convertOSLComponentConnections( network, oslVersion );
7171
}
7272

73-
CompoundDataPtr collapseSplineParametersWrapper( CompoundDataPtr parameters )
73+
CompoundDataPtr collapseSplineParametersWrapper( CompoundDataPtr parameters, const std::string shaderType, const std::string shaderName )
7474
{
75-
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::collapseSplineParameters( parameters ) );
75+
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::collapseSplineParameters( parameters, shaderType, shaderName ) );
7676
}
7777

78-
CompoundDataPtr expandSplineParametersWrapper( CompoundDataPtr parameters )
78+
CompoundDataPtr expandSplineParametersWrapper( CompoundDataPtr parameters, const std::string shaderType, const std::string shaderName )
7979
{
80-
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::expandSplineParameters( parameters ) );
80+
return boost::const_pointer_cast< CompoundData >( ShaderNetworkAlgo::expandSplineParameters( parameters, shaderType, shaderName ) );
8181
}
8282

8383
std::string componentConnectionAdapterLabelWrapper()

0 commit comments

Comments
 (0)