Skip to content

Commit 2d7eb96

Browse files
authored
Merge pull request #1400 from johnhaddon/usdNurbs
USD CurvesAlgo : Add basic support for reading UsdGeomNurbsCurves
2 parents a9850fd + 285ab04 commit 2d7eb96

File tree

3 files changed

+108
-16
lines changed

3 files changed

+108
-16
lines changed

Changes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
10.5.x.x (relative to 10.5.4.2)
22
========
33

4+
Improvements
5+
------------
46

7+
- USDScene : Added basic loading of UsdGeomNurbsCurves, converting them to CurvesPrimitives.
58

69
10.5.4.2 (relative to 10.5.4.1)
710
========

contrib/IECoreUSD/src/IECoreUSD/CurvesAlgo.cpp

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
IECORE_PUSH_DEFAULT_VISIBILITY
4444
#include "pxr/usd/usdGeom/basisCurves.h"
45+
#include "pxr/usd/usdGeom/nurbsCurves.h"
4546
IECORE_POP_DEFAULT_VISIBILITY
4647

4748
using namespace IECore;
@@ -55,13 +56,37 @@ using namespace IECoreUSD;
5556
namespace
5657
{
5758

58-
IECore::ObjectPtr readCurves( pxr::UsdGeomBasisCurves &curves, pxr::UsdTimeCode time, const Canceller *canceller )
59+
IECore::ObjectPtr readCurves( pxr::UsdGeomCurves &curves, pxr::UsdTimeCode time, const IECore::CubicBasisf &basis, bool periodic, const Canceller *canceller )
5960
{
6061
Canceller::check( canceller );
6162
pxr::VtIntArray vertexCountsArray;
6263
curves.GetCurveVertexCountsAttr().Get( &vertexCountsArray, time );
6364
IECore::IntVectorDataPtr countData = DataAlgo::fromUSD( vertexCountsArray );
6465

66+
Canceller::check( canceller );
67+
IECoreScene::CurvesPrimitivePtr newCurves = new IECoreScene::CurvesPrimitive( countData, basis, periodic );
68+
PrimitiveAlgo::readPrimitiveVariables( curves, time, newCurves.get(), canceller );
69+
70+
Canceller::check( canceller );
71+
PrimitiveAlgo::readPrimitiveVariable(
72+
curves.GetWidthsAttr(), time, newCurves.get(), "width", PrimitiveAlgo::fromUSD( curves.GetWidthsInterpolation() )
73+
);
74+
75+
return newCurves;
76+
}
77+
78+
bool curvesMightBeTimeVarying( pxr::UsdGeomCurves &curves )
79+
{
80+
return
81+
curves.GetCurveVertexCountsAttr().ValueMightBeTimeVarying() ||
82+
curves.GetWidthsAttr().ValueMightBeTimeVarying() ||
83+
PrimitiveAlgo::primitiveVariablesMightBeTimeVarying( curves )
84+
;
85+
}
86+
87+
IECore::ObjectPtr readBasisCurves( pxr::UsdGeomBasisCurves &curves, pxr::UsdTimeCode time, const Canceller *canceller )
88+
{
89+
6590
// Basis
6691
Canceller::check( canceller );
6792
IECore::CubicBasisf basis = CubicBasisf::linear();
@@ -103,32 +128,44 @@ IECore::ObjectPtr readCurves( pxr::UsdGeomBasisCurves &curves, pxr::UsdTimeCode
103128
IECore::msg( IECore::Msg::Warning, "USDScene", boost::format( "Unsupported wrap \"%1%\"" ) % wrap );
104129
}
105130

106-
// Curves and primvars
131+
return readCurves( curves, time, basis, periodic, canceller );
132+
}
107133

108-
IECoreScene::CurvesPrimitivePtr newCurves = new IECoreScene::CurvesPrimitive( countData, basis, periodic );
109-
PrimitiveAlgo::readPrimitiveVariables( curves, time, newCurves.get(), canceller );
134+
bool basisCurvesMightBeTimeVarying( pxr::UsdGeomBasisCurves &curves )
135+
{
136+
return
137+
curvesMightBeTimeVarying( curves ) ||
138+
curves.GetTypeAttr().ValueMightBeTimeVarying() ||
139+
curves.GetBasisAttr().ValueMightBeTimeVarying() ||
140+
curves.GetWrapAttr().ValueMightBeTimeVarying()
141+
;
142+
}
143+
144+
IECore::ObjectPtr readNurbsCurves( pxr::UsdGeomNurbsCurves &curves, pxr::UsdTimeCode time, const Canceller *canceller )
145+
{
146+
IECore::CubicBasisf basis = IECore::CubicBasisf::linear();
110147

111148
Canceller::check( canceller );
112-
PrimitiveAlgo::readPrimitiveVariable(
113-
curves.GetWidthsAttr(), time, newCurves.get(), "width", PrimitiveAlgo::fromUSD( curves.GetWidthsInterpolation() )
114-
);
149+
pxr::VtIntArray order;
150+
curves.GetOrderAttr().Get( &order, time );
151+
if( std::all_of( order.begin(), order.end(), [] ( int o ) { return o == 4; } ) )
152+
{
153+
basis = CubicBasisf::bSpline();
154+
}
115155

116-
return newCurves;
156+
return readCurves( curves, time, basis, false, canceller );
117157
}
118158

119-
bool curvesMightBeTimeVarying( pxr::UsdGeomBasisCurves &curves )
159+
bool nurbsCurvesMightBeTimeVarying( pxr::UsdGeomNurbsCurves &curves )
120160
{
121161
return
122-
curves.GetCurveVertexCountsAttr().ValueMightBeTimeVarying() ||
123-
curves.GetTypeAttr().ValueMightBeTimeVarying() ||
124-
curves.GetBasisAttr().ValueMightBeTimeVarying() ||
125-
curves.GetWrapAttr().ValueMightBeTimeVarying() ||
126-
curves.GetWidthsAttr().ValueMightBeTimeVarying() ||
127-
PrimitiveAlgo::primitiveVariablesMightBeTimeVarying( curves )
162+
curvesMightBeTimeVarying( curves ) ||
163+
curves.GetOrderAttr().ValueMightBeTimeVarying()
128164
;
129165
}
130166

131-
ObjectAlgo::ReaderDescription<pxr::UsdGeomBasisCurves> g_curvesReaderDescription( pxr::TfToken( "BasisCurves" ), readCurves, curvesMightBeTimeVarying );
167+
ObjectAlgo::ReaderDescription<pxr::UsdGeomBasisCurves> g_curvesReaderDescription( pxr::TfToken( "BasisCurves" ), readBasisCurves, basisCurvesMightBeTimeVarying );
168+
ObjectAlgo::ReaderDescription<pxr::UsdGeomNurbsCurves> g_nurbsCurvesReaderDescription( pxr::TfToken( "NurbsCurves" ), readNurbsCurves, nurbsCurvesMightBeTimeVarying );
132169

133170
} // namespace
134171

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,58 @@ def testCurveBasisAndWrap( self ) :
16551655
self.assertEqual( curves2, curves )
16561656
del root
16571657

1658+
def testReadNurbsCurves( self ) :
1659+
1660+
# Write USD file
1661+
1662+
fileName = os.path.join( self.temporaryDirectory(), "nurbs.usda" )
1663+
stage = pxr.Usd.Stage.CreateNew( fileName )
1664+
1665+
curves = pxr.UsdGeom.NurbsCurves.Define( stage, "/cubic" )
1666+
curves.CreateCurveVertexCountsAttr().Set( [ 4 ] )
1667+
curves.CreatePointsAttr().Set( [ ( x, x, x ) for x in range( 0, 4 ) ] )
1668+
curves.CreateOrderAttr().Set( [ 4 ] )
1669+
curves.CreateKnotsAttr().Set( [ 0, 0, 0, 0.333, 0.666, 1, 1, 1 ] )
1670+
1671+
curves = pxr.UsdGeom.NurbsCurves.Define( stage, "/nonCubic" )
1672+
curves.CreateCurveVertexCountsAttr().Set( [ 4 ] )
1673+
curves.CreatePointsAttr().Set( [ ( x, x, x ) for x in range( 0, 4 ) ] )
1674+
curves.CreateOrderAttr().Set( [ 3 ] )
1675+
curves.CreateKnotsAttr().Set( [ 0, 0, 0, 0.5, 1, 1, 1 ] )
1676+
1677+
stage.GetRootLayer().Save()
1678+
del stage
1679+
1680+
# Load and check
1681+
1682+
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
1683+
1684+
cubic = root.child( "cubic" ).readObject( 0.0 )
1685+
self.assertIsInstance( cubic, IECoreScene.CurvesPrimitive )
1686+
self.assertEqual( cubic.verticesPerCurve(), IECore.IntVectorData( [ 4 ] ) )
1687+
self.assertEqual( cubic.basis(), IECore.CubicBasisf.bSpline() )
1688+
self.assertEqual( cubic.periodic(), False )
1689+
self.assertEqual(
1690+
cubic["P"].data,
1691+
IECore.V3fVectorData(
1692+
[ imath.V3f( x ) for x in range( 0, 4 ) ],
1693+
IECore.GeometricData.Interpretation.Point
1694+
)
1695+
)
1696+
1697+
nonCubic = root.child( "nonCubic" ).readObject( 0.0 )
1698+
self.assertIsInstance( nonCubic, IECoreScene.CurvesPrimitive )
1699+
self.assertEqual( nonCubic.verticesPerCurve(), IECore.IntVectorData( [ 4 ] ) )
1700+
self.assertEqual( nonCubic.basis(), IECore.CubicBasisf.linear() )
1701+
self.assertEqual( nonCubic.periodic(), False )
1702+
self.assertEqual(
1703+
cubic["P"].data,
1704+
IECore.V3fVectorData(
1705+
[ imath.V3f( x ) for x in range( 0, 4 ) ],
1706+
IECore.GeometricData.Interpretation.Point
1707+
)
1708+
)
1709+
16581710
def testIndexedWidths( self ) :
16591711

16601712
# Write USD file from points with indexed widths

0 commit comments

Comments
 (0)