3636#define IECORESCENE_MESHALGO_H
3737
3838#include " IECore/Canceller.h"
39+ #include " IECore/ImathHash.h"
3940#include " IECoreScene/MeshPrimitive.h"
4041#include " IECoreScene/PointsPrimitive.h"
4142#include " IECoreScene/PrimitiveVariable.h"
@@ -95,11 +96,68 @@ IECORESCENE_API void reorderVertices( MeshPrimitive *mesh, int id0, int id1, int
9596// / vertex spacing, provided the UVs are well layed out.
9697IECORESCENE_API PointsPrimitivePtr distributePoints ( const MeshPrimitive *mesh, float density = 100.0 , const Imath::V2f &offset = Imath::V2f( 0 ), const std::string &densityMask = "density", const std::string &uvSet = "uv", const std::string &position = "P", const IECore::Canceller *canceller = nullptr );
9798
98- // / Segment the input mesh in to N meshes based on the N unique values contained in the segmentValues argument.
99+
100+ // / Split the input mesh in to N meshes based on the N unique values contained in a segment primitive variable.
101+ // / Using a class allows for the initialization work to be done once, and shared when actually splitting
102+ // / ( splitting may be performed on multiple threads )
103+ // /
104+ // / Use numMeshes() to get the number of results, then call mesh( i ) for i in range( numMeshes() ) to get
105+ // / all the split meshes. The results are ordered by sorting the unique values of the primvar ( sorting by
106+ // / the first element first in the case of vector types ). You can use value( i ) to get the corresponding
107+ // / value of the segment primitive variable.
108+
109+ class IECORESCENE_API MeshSplitter
110+ {
111+ public:
112+
113+ // Initialize with a mesh, and matching uniform primitive variable - the mesh will be split based on
114+ // unique values of this primitive variable
115+ MeshSplitter ( ConstMeshPrimitivePtr mesh, const PrimitiveVariable &segmentPrimitiveVariable, const IECore::Canceller *canceller = nullptr );
116+
117+ // Return the number of meshes we are splitting into, based on the primitive variable passed to the constructor
118+ inline int numMeshes () const ;
119+
120+ // Return one of the result meshes. Because this is an const method which does not alter any shared
121+ // data, it is safe to call in parallel on multiple threads
122+ MeshPrimitivePtr mesh ( int segmentId, const IECore::Canceller *canceller = nullptr ) const ;
123+
124+ // Return the value of the given segment primitive variable corresponding to one of the outputs
125+ template < typename T>
126+ typename std::vector<T>::const_reference value ( int segmentId ) const ;
127+
128+ // Return a bound containing all values of the primitive variable P for one of the result meshes,
129+ // or an empty box if there is no P. Yields an identical result to mesh( id )->bound(). Faster than
130+ // calling mesh(), but slower than calling bound() if you already have the split mesh.
131+ Imath::Box3f bound ( int segmentId, const IECore::Canceller *canceller = nullptr ) const ;
132+
133+ // Used by the python binding, but otherwise shouldn't be necessary
134+ const PrimitiveVariable &segmentPrimitiveVariable () const
135+ {
136+ return m_segmentPrimitiveVariable;
137+ }
138+
139+ private:
140+
141+ // Holds the original mesh
142+ ConstMeshPrimitivePtr m_mesh;
143+
144+ // Holds the primitive value we're splitting with
145+ const PrimitiveVariable m_segmentPrimitiveVariable;
146+
147+ // Internal data. We want to avoid doing work up-front which can't be threaded, so this is the minimal
148+ // data to allow mesh() to only need to process the indices for one output mesh
149+ std::vector< int > m_meshIndices;
150+ std::vector< int > m_faceRemap;
151+ std::vector< int > m_faceIndices;
152+
153+ };
154+
155+ // / Deprecated. Use MeshSplitter instead.
156+ // / Split the input mesh in to N meshes based on the N unique values contained in the segmentValues argument.
99157// / If segmentValues isn't supplied then primitive is split into the unique values contained in the primitiveVariable.
100158// / The primitiveVariable must have 'Uniform' iterpolation and match the base type of the VectorTypedData in the segmentValues.
101159// / Specifying the two parameters segmentValues & primitiveVariable allows for a subset of meshes to be created, rather than
102- // / completely segmententing the mesh based on the unique values in a primitive variable.
160+ // / completely segmenting the mesh based on the unique values in a primitive variable.
103161IECORESCENE_API std::vector<MeshPrimitivePtr> segment ( const MeshPrimitive *mesh, const PrimitiveVariable &primitiveVariable, const IECore::Data *segmentValues = nullptr , const IECore::Canceller *canceller = nullptr );
104162
105163// / Merge the input meshes into a single mesh.
@@ -118,4 +176,6 @@ IECORESCENE_API std::pair<IECore::IntVectorDataPtr, IECore::IntVectorDataPtr> co
118176
119177} // namespace IECoreScene
120178
179+ #include " IECoreScene/MeshAlgo.inl"
180+
121181#endif // IECORESCENE_MESHALGO_H
0 commit comments