Skip to content

Commit

Permalink
IECOreUSD : support subdiv options
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed Apr 18, 2024
1 parent 2206127 commit 825ee18
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 2 deletions.
34 changes: 32 additions & 2 deletions contrib/IECoreUSD/src/IECoreUSD/MeshAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,30 @@ IECore::ObjectPtr readMesh( pxr::UsdGeomMesh &mesh, pxr::UsdTimeCode time, const

if( subdivScheme == pxr::UsdGeomTokens->catmullClark )
{
newMesh->setInterpolation( "catmullClark" );
newMesh->setInterpolation( IECoreScene::MeshPrimitive::interpolationCatmullClark.string() );
}
else if( subdivScheme == pxr::UsdGeomTokens->loop )
{
newMesh->setInterpolation( IECoreScene::MeshPrimitive::interpolationLoop.string() );
}
else
{
// For "none", we currently use the default value of "linear". It would probably be preferrable if
// we used the name "none", since this is different from "bilinear", which would indicate that
// subdivision is being requested, but without altering the shape of the limit surface.
}

pxr::TfToken interpolateBoundary;
mesh.GetInterpolateBoundaryAttr().Get( &interpolateBoundary, time );
newMesh->setInterpolateBoundary( interpolateBoundary.GetString() );

pxr::TfToken faceVaryingLinearInterpolation;
mesh.GetFaceVaryingLinearInterpolationAttr().Get( &faceVaryingLinearInterpolation, time );
newMesh->setFaceVaryingLinearInterpolation( faceVaryingLinearInterpolation.GetString() );

pxr::TfToken triangleSubdivisionRule;
mesh.GetTriangleSubdivisionRuleAttr().Get( &triangleSubdivisionRule, time );
newMesh->setTriangleSubdivisionRule( triangleSubdivisionRule.GetString() );

// Corners

Expand Down Expand Up @@ -170,15 +192,23 @@ bool writeMesh( const IECoreScene::MeshPrimitive *mesh, const pxr::UsdStagePtr &

// Interpolation

if( mesh->interpolation() == std::string( "catmullClark" ) )
if( mesh->interpolation() == IECoreScene::MeshPrimitive::interpolationCatmullClark.string() )
{
usdMesh.CreateSubdivisionSchemeAttr().Set( pxr::UsdGeomTokens->catmullClark );
}
else if( mesh->interpolation() == IECoreScene::MeshPrimitive::interpolationLoop.string() )
{
usdMesh.CreateSubdivisionSchemeAttr().Set( pxr::UsdGeomTokens->loop );
}
else
{
usdMesh.CreateSubdivisionSchemeAttr().Set( pxr::UsdGeomTokens->none );
}

usdMesh.CreateInterpolateBoundaryAttr().Set( pxr::TfToken( mesh->getInterpolateBoundary().string() ), time );
usdMesh.CreateFaceVaryingLinearInterpolationAttr().Set( pxr::TfToken( mesh->getFaceVaryingLinearInterpolation().string() ), time );
usdMesh.CreateTriangleSubdivisionRuleAttr().Set( pxr::TfToken( mesh->getTriangleSubdivisionRule().string() ), time );

// Corners

if( mesh->cornerIds()->readable().size() )
Expand Down
90 changes: 90 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,96 @@ def testCanWriteSubD( self ):

self.assertEqual(readChild.readObject( 0.0 ).interpolation, "catmullClark")

def testSubdOptions( self ) :

fileName = os.path.join( self.temporaryDirectory(), "test.usda" )
resaveFileName = os.path.join( self.temporaryDirectory(), "resave.usda" )

# We need a list of all the values from USD we should support. There probably should be a
# more direct way to get this, but I have already wasted far, far too much time trying to
# understand which USD API to use.
dummyStage = pxr.Usd.Stage.CreateInMemory()
dummyMesh = pxr.UsdGeom.Mesh.Define( dummyStage, "/mesh" )
allowedSubScheme = dummyMesh.GetSubdivisionSchemeAttr().GetMetadata( "allowedTokens" )
allowedIB = dummyMesh.GetInterpolateBoundaryAttr().GetMetadata( "allowedTokens" )
allowedFVLI = dummyMesh.GetFaceVaryingLinearInterpolationAttr().GetMetadata( "allowedTokens" )
allowedTS = dummyMesh.GetTriangleSubdivisionRuleAttr().GetMetadata( "allowedTokens" )

del dummyMesh
del dummyStage

for property, allowed in [
( "subdivisionScheme", allowedSubScheme ),
( "interpolateBoundary", allowedIB ),
( "faceVaryingLinearInterpolation", allowedFVLI ),
( "triangleSubdivisionRule", allowedTS ),

]:
for value in allowed:

if property == "subdivisionScheme" and value == "bilinear":
# We know we don't support this
continue

stage = pxr.Usd.Stage.CreateNew( fileName )
mesh = pxr.UsdGeom.Mesh.Define( stage, "/mesh" )
if property == "subdivisionScheme":
mesh.CreateSubdivisionSchemeAttr().Set( value )
else:
mesh.CreateSubdivisionSchemeAttr().Set( "catmullClark" )

if property == "interpolateBoundary":
mesh.CreateInterpolateBoundaryAttr().Set( value, 0.0 )

if property == "faceVaryingLinearInterpolation":
mesh.CreateFaceVaryingLinearInterpolationAttr().Set( value, 0.0 )

if property == "triangleSubdivisionRule":
mesh.CreateTriangleSubdivisionRuleAttr().Set( value, 0.0 )

stage.GetRootLayer().Save()
del stage

root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )

cortexMesh = root.child( "mesh" ).readObject( 0.0 )
if property == "subdivisionScheme":
if value == "none":
self.assertEqual( cortexMesh.interpolation, "linear" )
else:
self.assertEqual( cortexMesh.interpolation, value )
elif property == "interpolateBoundary":
self.assertEqual( cortexMesh.getInterpolateBoundary(), value )
elif property == "faceVaryingLinearInterpolation":
self.assertEqual( cortexMesh.getFaceVaryingLinearInterpolation(), value )
elif property == "triangleSubdivisionRule":
self.assertEqual( cortexMesh.getTriangleSubdivisionRule(), value )

sceneWrite = IECoreScene.SceneInterface.create( resaveFileName, IECore.IndexedIO.OpenMode.Write )
root = sceneWrite.createChild( "root" )
child = root.createChild( "mesh" )

child.writeObject ( cortexMesh, 0.0 )

del child
del root
del sceneWrite

rereadFile = pxr.Usd.Stage.Open( resaveFileName )
rereadMesh = pxr.UsdGeom.Mesh.Get( rereadFile, "/root/mesh" )

if property == "subdivisionScheme":
self.assertEqual( rereadMesh.GetSubdivisionSchemeAttr().Get( 0.0 ), value )
elif property == "interpolateBoundary":
self.assertEqual( rereadMesh.GetInterpolateBoundaryAttr().Get( 0.0 ), value )
elif property == "faceVaryingLinearInterpolation":
self.assertEqual( rereadMesh.GetFaceVaryingLinearInterpolationAttr().Get( 0.0 ), value )
elif property == "triangleSubdivisionRule":
self.assertEqual( rereadMesh.GetTriangleSubdivisionRuleAttr().Get( 0.0 ), value )

del rereadMesh
del rereadFile

def testCanWriteAnimatedPrimitiveVariable ( self ):

fileName = os.path.join( self.temporaryDirectory(), "usd_animated_primvar.usda" )
Expand Down

0 comments on commit 825ee18

Please sign in to comment.