@@ -58,6 +58,7 @@ IECORE_PUSH_DEFAULT_VISIBILITY
5858#include " pxr/usd/usdGeom/camera.h"
5959#include " pxr/usd/usdGeom/gprim.h"
6060#include " pxr/usd/usdGeom/metrics.h"
61+ #include " pxr/usd/usdGeom/modelAPI.h"
6162#include " pxr/usd/usdGeom/pointInstancer.h"
6263#include " pxr/usd/usdGeom/primvar.h"
6364#include " pxr/usd/usdGeom/primvarsAPI.h"
@@ -528,6 +529,33 @@ Imath::M44d localTransform( const pxr::UsdPrim &prim, pxr::UsdTimeCode time )
528529 return result;
529530}
530531
532+ static const bool g_useModelAPIBounds = []() -> bool {
533+ const char *c = getenv ( " IECOREUSD_USE_MODELAPI_BOUNDS" );
534+ if ( !c )
535+ {
536+ return true ;
537+ }
538+ return strcmp ( c, " 0" );
539+ }();
540+
541+ pxr::UsdAttribute boundAttribute ( const pxr::UsdPrim &prim )
542+ {
543+ if ( auto boundable = pxr::UsdGeomBoundable ( prim ) )
544+ {
545+ return boundable.GetExtentAttr ();
546+ }
547+
548+ if ( g_useModelAPIBounds )
549+ {
550+ if ( auto modelAPI = pxr::UsdGeomModelAPI ( prim ) )
551+ {
552+ return modelAPI.GetExtentsHintAttr ();
553+ }
554+ }
555+
556+ return pxr::UsdAttribute ();
557+ }
558+
531559// Used to assign a unique hash to each USD file. Using a global counter rather than the file name
532560// means that we treat the same file as separate if it is closed and reopened. This means it's not
533561// a problem if USD changes things when a file is reopened. USD appears to not in general guarantee
@@ -820,30 +848,32 @@ std::string USDScene::fileName() const
820848
821849Imath::Box3d USDScene::readBound ( double time ) const
822850{
823- pxr::UsdGeomBoundable boundable = pxr::UsdGeomBoundable ( m_location->prim );
824- if ( !boundable )
825- {
826- return Imath::Box3d ();
827- }
828-
829- pxr::UsdAttribute attr = boundable.GetExtentAttr ();
851+ pxr::UsdAttribute attr = boundAttribute ( m_location->prim );
830852 if ( !attr.IsValid () )
831853 {
832854 return Imath::Box3d ();
833855 }
834856
835857 pxr::VtArray<pxr::GfVec3f> extents;
836- attr.Get <pxr::VtArray<pxr::GfVec3f> > ( &extents, m_root->getTime ( time ) );
858+ attr.Get ( &extents, m_root->getTime ( time ) );
837859
838- if ( extents.size () == 2 )
860+ // When coming from UsdGeomModelAPI, `extents` may contain several bounds,
861+ // on a per-purpose basis. Take the union, since the SceneInterface API only
862+ // has a single bound per location.
863+ Imath::Box3d result;
864+ for ( size_t i = 0 ; i + 1 < extents.size (); i += 2 )
839865 {
840- return Imath::Box3d (
841- DataAlgo::fromUSD ( extents[0 ] ),
842- DataAlgo::fromUSD ( extents[1 ] )
866+ const Imath::Box3d b (
867+ DataAlgo::fromUSD ( extents[i ] ),
868+ DataAlgo::fromUSD ( extents[i+ 1 ] )
843869 );
870+ if ( !b.isEmpty () )
871+ {
872+ result.extendBy ( b );
873+ }
844874 }
845875
846- return Imath::Box3d () ;
876+ return result ;
847877}
848878
849879ConstDataPtr USDScene::readTransform ( double time ) const
@@ -873,14 +903,7 @@ void USDScene::path( SceneInterface::Path &p ) const
873903
874904bool USDScene::hasBound () const
875905{
876- pxr::UsdGeomBoundable boundable = pxr::UsdGeomBoundable ( m_location->prim );
877- pxr::UsdAttribute attr;
878-
879- if ( boundable )
880- {
881- attr = boundable.GetExtentAttr ();
882- }
883-
906+ pxr::UsdAttribute attr = boundAttribute ( m_location->prim );
884907 return attr.IsValid ();
885908}
886909
0 commit comments