Skip to content

Commit ff821fb

Browse files
authored
Merge pull request #1413 from danieldresser-ie/meshBoundary
MeshPrimitive : Add subdivision options
2 parents 5dedde4 + 825ee18 commit ff821fb

File tree

11 files changed

+420
-11
lines changed

11 files changed

+420
-11
lines changed

Changes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
10.5.x.x (relative to 10.5.6.2)
22
========
33

4+
Features
5+
--------
6+
7+
- MeshPrimitive : Added interpolateBoundary, faceVaryingLinearInterpolation and triangleSubdivisionRule properties for controlling the shape of the subdivision limit surface.
8+
9+
Fixes
10+
-----
11+
12+
- MeshPrimitive : Removed `interpolation` from topologyHash. The topologyHash should only include things which affect the layout of primitive variables.
413

514

615
10.5.6.2 (relative to 10.5.6.1)

SConstruct

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ o.Add(
9696
o.Add(
9797
"CXXFLAGS",
9898
"The extra flags to pass to the C++ compiler during compilation.",
99-
[ "-pipe", "-Wall", "-Wextra" ] if Environment()["PLATFORM"] != "win32" else [ "/permissive-", "/D_USE_MATH_DEFINES", "/Zc:externC-", "/DBOOST_ALL_NO_LIB" ],
99+
[ "-pipe", "-Wall", "-Wextra", "-Wsuggest-override" ] if Environment()["PLATFORM"] != "win32" else [ "/permissive-", "/D_USE_MATH_DEFINES", "/Zc:externC-", "/DBOOST_ALL_NO_LIB" ],
100100
)
101101

102102
o.Add(

contrib/IECoreUSD/src/IECoreUSD/MeshAlgo.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,30 @@ IECore::ObjectPtr readMesh( pxr::UsdGeomMesh &mesh, pxr::UsdTimeCode time, const
7676

7777
if( subdivScheme == pxr::UsdGeomTokens->catmullClark )
7878
{
79-
newMesh->setInterpolation( "catmullClark" );
79+
newMesh->setInterpolation( IECoreScene::MeshPrimitive::interpolationCatmullClark.string() );
8080
}
81+
else if( subdivScheme == pxr::UsdGeomTokens->loop )
82+
{
83+
newMesh->setInterpolation( IECoreScene::MeshPrimitive::interpolationLoop.string() );
84+
}
85+
else
86+
{
87+
// For "none", we currently use the default value of "linear". It would probably be preferrable if
88+
// we used the name "none", since this is different from "bilinear", which would indicate that
89+
// subdivision is being requested, but without altering the shape of the limit surface.
90+
}
91+
92+
pxr::TfToken interpolateBoundary;
93+
mesh.GetInterpolateBoundaryAttr().Get( &interpolateBoundary, time );
94+
newMesh->setInterpolateBoundary( interpolateBoundary.GetString() );
95+
96+
pxr::TfToken faceVaryingLinearInterpolation;
97+
mesh.GetFaceVaryingLinearInterpolationAttr().Get( &faceVaryingLinearInterpolation, time );
98+
newMesh->setFaceVaryingLinearInterpolation( faceVaryingLinearInterpolation.GetString() );
99+
100+
pxr::TfToken triangleSubdivisionRule;
101+
mesh.GetTriangleSubdivisionRuleAttr().Get( &triangleSubdivisionRule, time );
102+
newMesh->setTriangleSubdivisionRule( triangleSubdivisionRule.GetString() );
81103

82104
// Corners
83105

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

171193
// Interpolation
172194

173-
if( mesh->interpolation() == std::string( "catmullClark" ) )
195+
if( mesh->interpolation() == IECoreScene::MeshPrimitive::interpolationCatmullClark.string() )
174196
{
175197
usdMesh.CreateSubdivisionSchemeAttr().Set( pxr::UsdGeomTokens->catmullClark );
176198
}
199+
else if( mesh->interpolation() == IECoreScene::MeshPrimitive::interpolationLoop.string() )
200+
{
201+
usdMesh.CreateSubdivisionSchemeAttr().Set( pxr::UsdGeomTokens->loop );
202+
}
177203
else
178204
{
179205
usdMesh.CreateSubdivisionSchemeAttr().Set( pxr::UsdGeomTokens->none );
180206
}
181207

208+
usdMesh.CreateInterpolateBoundaryAttr().Set( pxr::TfToken( mesh->getInterpolateBoundary().string() ), time );
209+
usdMesh.CreateFaceVaryingLinearInterpolationAttr().Set( pxr::TfToken( mesh->getFaceVaryingLinearInterpolation().string() ), time );
210+
usdMesh.CreateTriangleSubdivisionRuleAttr().Set( pxr::TfToken( mesh->getTriangleSubdivisionRule().string() ), time );
211+
182212
// Corners
183213

184214
if( mesh->cornerIds()->readable().size() )

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,96 @@ def testCanWriteSubD( self ):
843843

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

846+
def testSubdOptions( self ) :
847+
848+
fileName = os.path.join( self.temporaryDirectory(), "test.usda" )
849+
resaveFileName = os.path.join( self.temporaryDirectory(), "resave.usda" )
850+
851+
# We need a list of all the values from USD we should support. There probably should be a
852+
# more direct way to get this, but I have already wasted far, far too much time trying to
853+
# understand which USD API to use.
854+
dummyStage = pxr.Usd.Stage.CreateInMemory()
855+
dummyMesh = pxr.UsdGeom.Mesh.Define( dummyStage, "/mesh" )
856+
allowedSubScheme = dummyMesh.GetSubdivisionSchemeAttr().GetMetadata( "allowedTokens" )
857+
allowedIB = dummyMesh.GetInterpolateBoundaryAttr().GetMetadata( "allowedTokens" )
858+
allowedFVLI = dummyMesh.GetFaceVaryingLinearInterpolationAttr().GetMetadata( "allowedTokens" )
859+
allowedTS = dummyMesh.GetTriangleSubdivisionRuleAttr().GetMetadata( "allowedTokens" )
860+
861+
del dummyMesh
862+
del dummyStage
863+
864+
for property, allowed in [
865+
( "subdivisionScheme", allowedSubScheme ),
866+
( "interpolateBoundary", allowedIB ),
867+
( "faceVaryingLinearInterpolation", allowedFVLI ),
868+
( "triangleSubdivisionRule", allowedTS ),
869+
870+
]:
871+
for value in allowed:
872+
873+
if property == "subdivisionScheme" and value == "bilinear":
874+
# We know we don't support this
875+
continue
876+
877+
stage = pxr.Usd.Stage.CreateNew( fileName )
878+
mesh = pxr.UsdGeom.Mesh.Define( stage, "/mesh" )
879+
if property == "subdivisionScheme":
880+
mesh.CreateSubdivisionSchemeAttr().Set( value )
881+
else:
882+
mesh.CreateSubdivisionSchemeAttr().Set( "catmullClark" )
883+
884+
if property == "interpolateBoundary":
885+
mesh.CreateInterpolateBoundaryAttr().Set( value, 0.0 )
886+
887+
if property == "faceVaryingLinearInterpolation":
888+
mesh.CreateFaceVaryingLinearInterpolationAttr().Set( value, 0.0 )
889+
890+
if property == "triangleSubdivisionRule":
891+
mesh.CreateTriangleSubdivisionRuleAttr().Set( value, 0.0 )
892+
893+
stage.GetRootLayer().Save()
894+
del stage
895+
896+
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
897+
898+
cortexMesh = root.child( "mesh" ).readObject( 0.0 )
899+
if property == "subdivisionScheme":
900+
if value == "none":
901+
self.assertEqual( cortexMesh.interpolation, "linear" )
902+
else:
903+
self.assertEqual( cortexMesh.interpolation, value )
904+
elif property == "interpolateBoundary":
905+
self.assertEqual( cortexMesh.getInterpolateBoundary(), value )
906+
elif property == "faceVaryingLinearInterpolation":
907+
self.assertEqual( cortexMesh.getFaceVaryingLinearInterpolation(), value )
908+
elif property == "triangleSubdivisionRule":
909+
self.assertEqual( cortexMesh.getTriangleSubdivisionRule(), value )
910+
911+
sceneWrite = IECoreScene.SceneInterface.create( resaveFileName, IECore.IndexedIO.OpenMode.Write )
912+
root = sceneWrite.createChild( "root" )
913+
child = root.createChild( "mesh" )
914+
915+
child.writeObject ( cortexMesh, 0.0 )
916+
917+
del child
918+
del root
919+
del sceneWrite
920+
921+
rereadFile = pxr.Usd.Stage.Open( resaveFileName )
922+
rereadMesh = pxr.UsdGeom.Mesh.Get( rereadFile, "/root/mesh" )
923+
924+
if property == "subdivisionScheme":
925+
self.assertEqual( rereadMesh.GetSubdivisionSchemeAttr().Get( 0.0 ), value )
926+
elif property == "interpolateBoundary":
927+
self.assertEqual( rereadMesh.GetInterpolateBoundaryAttr().Get( 0.0 ), value )
928+
elif property == "faceVaryingLinearInterpolation":
929+
self.assertEqual( rereadMesh.GetFaceVaryingLinearInterpolationAttr().Get( 0.0 ), value )
930+
elif property == "triangleSubdivisionRule":
931+
self.assertEqual( rereadMesh.GetTriangleSubdivisionRuleAttr().Get( 0.0 ), value )
932+
933+
del rereadMesh
934+
del rereadFile
935+
846936
def testCanWriteAnimatedPrimitiveVariable ( self ):
847937

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

include/IECore/EuclideanToSphericalTransform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class EuclideanToSphericalTransform : public SpaceTransform< F, T >
6262
EuclideanToSphericalTransform();
6363

6464
/// Perform the conversion.
65-
virtual T transform( const F &f );
65+
T transform( const F &f ) override;
6666

6767
/// Returns an instance of a class able to perform the inverse conversion
6868
InverseType inverse() const;

include/IECore/SphericalToEuclideanTransform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class SphericalToEuclideanTransform : public SpaceTransform< F, T >
6262
SphericalToEuclideanTransform();
6363

6464
/// Perform the conversion. The x component should be in the range [0,2*M_PI] and the second [0,M_PI]
65-
virtual T transform( const F &f );
65+
T transform( const F &f ) override;
6666

6767
/// Returns an instance of a class able to perform the inverse conversion
6868
InverseType inverse() const;

include/IECoreScene/MeshPrimitive.h

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "IECoreScene/Export.h"
3939
#include "IECoreScene/Primitive.h"
4040

41+
#include "IECore/InternedString.h"
4142
#include "IECore/VectorTypedData.h"
4243

4344
namespace IECoreScene
@@ -61,12 +62,30 @@ class IECORESCENE_API MeshPrimitive : public Primitive
6162

6263
IE_CORE_DECLAREEXTENSIONOBJECT( MeshPrimitive, MeshPrimitiveTypeId, Primitive );
6364

65+
//! @name Define supported interpolations
66+
/// \todo : In the future, we hope to use InternedStrings whenever we get/set
67+
/// interpolations.
68+
/// \todo : The meaning of "linear" has ended up being somewhat misaligned to
69+
/// what we actually want. The ideal would probably be if "linear" was instead
70+
/// named "none" - indicating that no subdivision is requested, and there was
71+
/// a new value "bilinear", which indicated that the limit surface is simple
72+
/// polygons, but subdivision is still being requested.
73+
/////////////////////////////////////////////////////////////////////////////
74+
//@{
75+
static const IECore::InternedString interpolationLinear;
76+
static const IECore::InternedString interpolationCatmullClark;
77+
static const IECore::InternedString interpolationLoop;
78+
//@}
79+
6480
/// Construct a MeshPrimitive with no faces.
6581
MeshPrimitive();
6682
/// Construct a MeshPrimitive. The number of faces specified by verticesPerFace->readable()->size().
6783
/// Copies of the IntVectorData objects are taken rather than references to the initial data.
6884
MeshPrimitive( IECore::ConstIntVectorDataPtr verticesPerFace, IECore::ConstIntVectorDataPtr vertexIds,
69-
const std::string &interpolation = "linear", IECore::V3fVectorDataPtr p = nullptr );
85+
const std::string &interpolation = interpolationLinear.string(), IECore::V3fVectorDataPtr p = nullptr );
86+
87+
/// Destructor
88+
~MeshPrimitive() override;
7089

7190
//! @name Topology access
7291
/// These functions allow access to get and set topology after construction.
@@ -102,6 +121,35 @@ class IECORESCENE_API MeshPrimitive : public Primitive
102121
void removeCreases();
103122
//@}
104123

124+
//! @name Subdivision options
125+
/// These parameters control various details that affect the shape of the limit surface
126+
/////////////////////////////////////////////////////////////////////////////
127+
//@{
128+
129+
const IECore::InternedString &getInterpolateBoundary() const;
130+
void setInterpolateBoundary( const IECore::InternedString &interpolateBoundary );
131+
132+
static const IECore::InternedString interpolateBoundaryNone;
133+
static const IECore::InternedString interpolateBoundaryEdgeOnly;
134+
static const IECore::InternedString interpolateBoundaryEdgeAndCorner;
135+
136+
const IECore::InternedString &getFaceVaryingLinearInterpolation() const;
137+
void setFaceVaryingLinearInterpolation( const IECore::InternedString &faceVaryingLinearInterpolation );
138+
139+
static const IECore::InternedString faceVaryingLinearInterpolationNone;
140+
static const IECore::InternedString faceVaryingLinearInterpolationCornersOnly;
141+
static const IECore::InternedString faceVaryingLinearInterpolationCornersPlus1;
142+
static const IECore::InternedString faceVaryingLinearInterpolationCornersPlus2;
143+
static const IECore::InternedString faceVaryingLinearInterpolationBoundaries;
144+
static const IECore::InternedString faceVaryingLinearInterpolationAll;
145+
146+
const IECore::InternedString &getTriangleSubdivisionRule() const;
147+
void setTriangleSubdivisionRule( const IECore::InternedString &triangleSubdivisionRule );
148+
149+
static const IECore::InternedString triangleSubdivisionRuleCatmullClark;
150+
static const IECore::InternedString triangleSubdivisionRuleSmooth;
151+
//@}
152+
105153
size_t variableSize( PrimitiveVariable::Interpolation interpolation ) const override;
106154

107155
/// Render the mesh

src/IECorePython/StringAlgoBinding.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ list matchPatternPath( const std::string &path, char separator )
7373
struct VariableProviderWrapper : StringAlgo::VariableProvider, wrapper<StringAlgo::VariableProvider>
7474
{
7575

76-
virtual int frame() const
76+
int frame() const override
7777
{
7878
return this->get_override( "frame" )();
7979
}
8080

81-
virtual const std::string &variable( const boost::string_view &name, bool &recurse ) const
81+
const std::string &variable( const boost::string_view &name, bool &recurse ) const override
8282
{
8383
object result = this->get_override( "variable" )( std::string( name ) );
8484
extract<tuple> tupleExtractor( result );

0 commit comments

Comments
 (0)