Skip to content

Commit 43a91b0

Browse files
ShaderNetworkAlgo::expand/collapseSpline : Support Prman convention for shaders prefixed with "Pxr"
1 parent 0577ecc commit 43a91b0

File tree

2 files changed

+181
-93
lines changed

2 files changed

+181
-93
lines changed

include/IECoreScene/ShaderNetworkAlgo.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,12 @@ IECORESCENE_API void collapseSplines( ShaderNetwork *network, std::string target
148148
IECORESCENE_API void expandSplines( ShaderNetwork *network, std::string targetPrefix = "" );
149149

150150

151-
/// \deprecated: Use collapseSplines on the whole network, which can handle input connections
151+
/// \deprecated: Use collapseSplines on the whole network, which can handle input connections, and supports
152+
/// different spline conventions for different renderers' shader libraries
152153
IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
153154

154-
/// \deprecated: Use expandSplines on the whole network, which can handle input connections
155+
/// \deprecated: Use expandSplines on the whole network, which can handle input connections, and supports
156+
/// different spline conventions for different renderers' shader libraries
155157
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );
156158

157159

src/IECoreScene/ShaderNetworkAlgo.cpp

Lines changed: 177 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "boost/regex.hpp"
5151

5252
#include <array>
53+
#include <filesystem>
5354
#include <unordered_map>
5455
#include <unordered_set>
5556

@@ -811,8 +812,31 @@ std::pair< size_t, size_t > getEndPointDuplication( const T &basis )
811812
return std::make_pair( 0, 0 );
812813
}
813814

815+
std::tuple< const std::string*, const std::string*, const std::string*, const std::string*, const std::string* >
816+
lookupSplinePlugSuffixes( const std::string &shaderBaseName )
817+
{
818+
// We seem to be able to identify shaders that should use the PRMan convention by whether they start
819+
// with one of the PRMan prefixes
820+
if( boost::starts_with( shaderBaseName, "Pxr" ) || boost::starts_with( shaderBaseName, "Lama" ) )
821+
{
822+
static const std::string positions( "_Knots" );
823+
static const std::string floatValues( "_Floats" );
824+
static const std::string colorValues( "_Colors" );
825+
static const std::string basis( "_Interpolation" );
826+
static const std::string count( "" );
827+
return { &positions, &floatValues, &colorValues, &basis, &count };
828+
}
829+
else
830+
{
831+
static const std::string positions( "Positions" );
832+
static const std::string values( "Values" );
833+
static const std::string basis( "Basis" );
834+
return { &positions, &values, &values, &basis, nullptr };
835+
}
836+
}
837+
814838
template<typename Spline>
815-
void expandSpline( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters )
839+
void expandSpline( const InternedString &name, const Spline &spline, CompoundDataMap &newParameters, const std::string &shaderBaseName )
816840
{
817841
const char *basis = "catmull-rom";
818842
if( spline.basis == Spline::Basis::bezier() )
@@ -866,9 +890,23 @@ void expandSpline( const InternedString &name, const Spline &spline, CompoundDat
866890
}
867891
}
868892

869-
newParameters[ name.string() + "Positions" ] = positionsData;
870-
newParameters[ name.string() + "Values" ] = valuesData;
871-
newParameters[ name.string() + "Basis" ] = new StringData( basis );
893+
auto [ positionsSuffix, floatValuesSuffix, colorValuesSuffix, basisSuffix, countSuffix ] = lookupSplinePlugSuffixes( shaderBaseName );
894+
895+
newParameters[ name.string() + *positionsSuffix ] = positionsData;
896+
if constexpr( std::is_same_v< typename Spline::YType, float > )
897+
{
898+
newParameters[ name.string() + *floatValuesSuffix ] = valuesData;
899+
}
900+
else
901+
{
902+
newParameters[ name.string() + *colorValuesSuffix ] = valuesData;
903+
}
904+
newParameters[ name.string() + *basisSuffix ] = new StringData( basis );
905+
906+
if( countSuffix )
907+
{
908+
newParameters[ name.string() + *countSuffix ] = new IntData( positionsData->readable().size() );
909+
}
872910
}
873911

874912
template<typename SplineData>
@@ -929,6 +967,131 @@ IECore::DataPtr loadSpline(
929967
return resultData;
930968
}
931969

970+
void ensureParametersCopy(
971+
const IECore::CompoundDataMap &parameters,
972+
IECore::CompoundDataPtr &parametersDataCopy, CompoundDataMap *&parametersCopy
973+
)
974+
{
975+
if( !parametersDataCopy )
976+
{
977+
parametersDataCopy = new CompoundData();
978+
parametersCopy = &parametersDataCopy->writable();
979+
*parametersCopy = parameters;
980+
}
981+
}
982+
983+
IECore::ConstCompoundDataPtr collapseSplineParametersInternal( const IECore::ConstCompoundDataPtr &parametersData, const std::string &shaderBaseName )
984+
{
985+
986+
auto [ positionsSuffix, floatValuesSuffix, colorValuesSuffix, basisSuffix, countSuffix ] = lookupSplinePlugSuffixes( shaderBaseName );
987+
988+
const CompoundDataMap &parameters( parametersData->readable() );
989+
CompoundDataPtr newParametersData;
990+
CompoundDataMap *newParameters = nullptr;
991+
992+
for( const auto &maybeBasis : parameters )
993+
{
994+
if( !boost::ends_with( maybeBasis.first.string(), *basisSuffix ) )
995+
{
996+
continue;
997+
}
998+
const StringData *basis = runTimeCast<const StringData>( maybeBasis.second.get() );
999+
if( !basis )
1000+
{
1001+
continue;
1002+
}
1003+
1004+
1005+
std::string prefix = maybeBasis.first.string().substr( 0, maybeBasis.first.string().size() - basisSuffix->size() );
1006+
IECore::InternedString positionsName = prefix + *positionsSuffix;
1007+
const auto positionsIter = parameters.find( positionsName );
1008+
const FloatVectorData *floatPositions = nullptr;
1009+
1010+
if( positionsIter != parameters.end() )
1011+
{
1012+
floatPositions = runTimeCast<const FloatVectorData>( positionsIter->second.get() );
1013+
}
1014+
1015+
if( !floatPositions )
1016+
{
1017+
continue;
1018+
}
1019+
1020+
if( countSuffix )
1021+
{
1022+
IECore::InternedString countName = prefix + *countSuffix;
1023+
const auto countIter = parameters.find( countName );
1024+
const IntData *countData = nullptr;
1025+
if( countIter == parameters.end() )
1026+
{
1027+
countData = runTimeCast<const IntData>( countIter->second.get() );
1028+
}
1029+
1030+
if( !countData )
1031+
{
1032+
IECore::msg(
1033+
Msg::Error, "ShaderNetworkAlgo",
1034+
"Using spline format that expects count plug, but no int count plug found matching \"" + countName.string() + "\""
1035+
);
1036+
}
1037+
else
1038+
{
1039+
if( (int)floatPositions->readable().size() != countData->readable() )
1040+
{
1041+
IECore::msg(
1042+
Msg::Error, "ShaderNetworkAlgo",
1043+
"Spline count \"" + countName.string() + "\" does not match length of data: " + std::to_string( countData->readable() ) + " != " + std::to_string( floatPositions->readable().size() ) + "\""
1044+
);
1045+
}
1046+
}
1047+
}
1048+
1049+
IECore::InternedString floatValuesName = prefix + *floatValuesSuffix;
1050+
auto valuesIter = parameters.find( floatValuesName );
1051+
if( valuesIter == parameters.end() )
1052+
{
1053+
IECore::InternedString colorValuesName = prefix + *colorValuesSuffix;
1054+
valuesIter = parameters.find( colorValuesName );
1055+
}
1056+
1057+
1058+
IECore::DataPtr foundSpline;
1059+
if( valuesIter != parameters.end() )
1060+
{
1061+
if( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second.get() ) )
1062+
{
1063+
foundSpline = loadSpline<SplineffData>( basis, floatPositions, floatValues );
1064+
}
1065+
else if( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second.get() ) )
1066+
{
1067+
foundSpline = loadSpline<SplinefColor3fData>( basis, floatPositions, color3Values );
1068+
}
1069+
else if( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second.get() ) )
1070+
{
1071+
foundSpline = loadSpline<SplinefColor4fData>( basis, floatPositions, color4Values );
1072+
}
1073+
}
1074+
1075+
if( foundSpline )
1076+
{
1077+
ensureParametersCopy( parameters, newParametersData, newParameters );
1078+
(*newParameters)[prefix] = foundSpline;
1079+
newParameters->erase( maybeBasis.first );
1080+
newParameters->erase( positionsName );
1081+
newParameters->erase( valuesIter->first );
1082+
}
1083+
}
1084+
1085+
if( newParametersData )
1086+
{
1087+
return newParametersData;
1088+
}
1089+
else
1090+
{
1091+
return parametersData;
1092+
}
1093+
}
1094+
9321095
const std::string g_oslShader( "osl:shader" );
9331096

9341097
const std::string g_colorToArrayAdapter( "Utility/__ColorToArray" );
@@ -1003,17 +1166,9 @@ std::pair< InternedString, int > createSplineInputAdapter(
10031166
return std::make_pair( adapterHandle, getEndPointDuplication( splineData->readable().basis ).first );
10041167
}
10051168

1006-
void ensureParametersCopy(
1007-
const IECore::CompoundDataMap &parameters,
1008-
IECore::CompoundDataPtr &parametersDataCopy, CompoundDataMap *&parametersCopy
1009-
)
1169+
std::string shaderBaseNameFromPath( const std::string shaderName )
10101170
{
1011-
if( !parametersDataCopy )
1012-
{
1013-
parametersDataCopy = new CompoundData();
1014-
parametersCopy = &parametersDataCopy->writable();
1015-
*parametersCopy = parameters;
1016-
}
1171+
return std::filesystem::path( shaderName ).filename().string();
10171172
}
10181173

10191174
} // namespace
@@ -1040,12 +1195,12 @@ void ShaderNetworkAlgo::collapseSplines( ShaderNetwork *network, std::string tar
10401195
}
10411196

10421197
// For nodes which aren't spline adapters, we just need to deal with any parameters that are splines
1043-
ConstCompoundDataPtr collapsed = collapseSplineParameters( shader->parametersData() );
1198+
ConstCompoundDataPtr collapsed = collapseSplineParametersInternal( shader->parametersData(), shaderBaseNameFromPath( shader->getName() ) );
10441199
if( collapsed != shader->parametersData() )
10451200
{
1046-
// \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameters
1201+
// \todo - this const_cast is ugly, although safe because if the return from collapseSplineParameterInternals
10471202
// doesn't match the input, it is freshly allocated. Once collapseSplineParameters is fully
1048-
// deprecated, and no longer visible publicly, an internal version of collapseSplineParameters could
1203+
// deprecated, and no longer visible publicly, an internal version of collapseSplineParametersInternal could
10491204
// just return a non-const new parameter data, or nullptr if no changes are needed.
10501205
network->setShader( name, std::move( new Shader( shader->getName(), shader->getType(), const_cast< CompoundData *>( collapsed.get() ) ) ) );
10511206
}
@@ -1167,13 +1322,13 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
11671322
{
11681323
ensureParametersCopy( origParameters, newParametersData, newParameters );
11691324
newParameters->erase( name );
1170-
expandSpline( name, colorSpline->readable(), *newParameters );
1325+
expandSpline( name, colorSpline->readable(), *newParameters, shaderBaseNameFromPath( s.second->getName() ) );
11711326
}
11721327
else if( const SplineffData *floatSpline = runTimeCast<const SplineffData>( value.get() ) )
11731328
{
11741329
ensureParametersCopy( origParameters, newParametersData, newParameters );
11751330
newParameters->erase( name );
1176-
expandSpline( name, floatSpline->readable(), *newParameters );
1331+
expandSpline( name, floatSpline->readable(), *newParameters, shaderBaseNameFromPath( s.second->getName() ) );
11771332
}
11781333
}
11791334

@@ -1291,76 +1446,7 @@ void ShaderNetworkAlgo::expandSplines( ShaderNetwork *network, std::string targe
12911446

12921447
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::collapseSplineParameters( const IECore::ConstCompoundDataPtr &parametersData )
12931448
{
1294-
const CompoundDataMap &parameters( parametersData->readable() );
1295-
CompoundDataPtr newParametersData;
1296-
CompoundDataMap *newParameters = nullptr;
1297-
1298-
for( const auto &maybeBasis : parameters )
1299-
{
1300-
if( !boost::ends_with( maybeBasis.first.string(), "Basis" ) )
1301-
{
1302-
continue;
1303-
}
1304-
const StringData *basis = runTimeCast<const StringData>( maybeBasis.second.get() );
1305-
if( !basis )
1306-
{
1307-
continue;
1308-
}
1309-
1310-
1311-
std::string prefix = maybeBasis.first.string().substr( 0, maybeBasis.first.string().size() - 5 );
1312-
IECore::InternedString positionsName = prefix + "Positions";
1313-
const auto positionsIter = parameters.find( positionsName );
1314-
const FloatVectorData *floatPositions = nullptr;
1315-
1316-
if( positionsIter != parameters.end() )
1317-
{
1318-
floatPositions = runTimeCast<const FloatVectorData>( positionsIter->second.get() );
1319-
}
1320-
1321-
if( !floatPositions )
1322-
{
1323-
continue;
1324-
}
1325-
1326-
IECore::InternedString valuesName = prefix + "Values";
1327-
const auto valuesIter = parameters.find( valuesName );
1328-
1329-
IECore::DataPtr foundSpline;
1330-
if( valuesIter != parameters.end() )
1331-
{
1332-
if( const FloatVectorData *floatValues = runTimeCast<const FloatVectorData>( valuesIter->second.get() ) )
1333-
{
1334-
foundSpline = loadSpline<SplineffData>( basis, floatPositions, floatValues );
1335-
}
1336-
else if( const Color3fVectorData *color3Values = runTimeCast<const Color3fVectorData>( valuesIter->second.get() ) )
1337-
{
1338-
foundSpline = loadSpline<SplinefColor3fData>( basis, floatPositions, color3Values );
1339-
}
1340-
else if( const Color4fVectorData *color4Values = runTimeCast<const Color4fVectorData>( valuesIter->second.get() ) )
1341-
{
1342-
foundSpline = loadSpline<SplinefColor4fData>( basis, floatPositions, color4Values );
1343-
}
1344-
}
1345-
1346-
if( foundSpline )
1347-
{
1348-
ensureParametersCopy( parameters, newParametersData, newParameters );
1349-
(*newParameters)[prefix] = foundSpline;
1350-
newParameters->erase( maybeBasis.first );
1351-
newParameters->erase( positionsName );
1352-
newParameters->erase( valuesName );
1353-
}
1354-
}
1355-
1356-
if( newParametersData )
1357-
{
1358-
return newParametersData;
1359-
}
1360-
else
1361-
{
1362-
return parametersData;
1363-
}
1449+
return collapseSplineParametersInternal( parametersData, "" );
13641450
}
13651451

13661452
IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IECore::ConstCompoundDataPtr &parametersData )
@@ -1376,13 +1462,13 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
13761462
{
13771463
ensureParametersCopy( parameters, newParametersData, newParameters );
13781464
newParameters->erase( i.first );
1379-
expandSpline( i.first, colorSpline->readable(), *newParameters );
1465+
expandSpline( i.first, colorSpline->readable(), *newParameters, "" );
13801466
}
13811467
else if( const SplineffData *floatSpline = runTimeCast<const SplineffData>( i.second.get() ) )
13821468
{
13831469
ensureParametersCopy( parameters, newParametersData, newParameters );
13841470
newParameters->erase( i.first );
1385-
expandSpline( i.first, floatSpline->readable(), *newParameters );
1471+
expandSpline( i.first, floatSpline->readable(), *newParameters, "" );
13861472
}
13871473
}
13881474

0 commit comments

Comments
 (0)