Skip to content

Commit bf2040e

Browse files
MeshAlgo : Added MeshSplitter
1 parent 4ce5680 commit bf2040e

File tree

6 files changed

+1796
-2
lines changed

6 files changed

+1796
-2
lines changed

include/IECoreScene/MeshAlgo.h

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
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.
9697
IECORESCENE_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.
103161
IECORESCENE_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

include/IECoreScene/MeshAlgo.inl

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//////////////////////////////////////////////////////////////////////////
2+
//
3+
// Copyright (c) 2023, Image Engine Design Inc. All rights reserved.
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are
7+
// met:
8+
//
9+
// * Redistributions of source code must retain the above
10+
// copyright notice, this list of conditions and the following
11+
// disclaimer.
12+
//
13+
// * Redistributions in binary form must reproduce the above
14+
// copyright notice, this list of conditions and the following
15+
// disclaimer in the documentation and/or other materials provided with
16+
// the distribution.
17+
//
18+
// * Neither the name of John Haddon nor the names of
19+
// any other contributors to this software may be used to endorse or
20+
// promote products derived from this software without specific prior
21+
// written permission.
22+
//
23+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24+
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25+
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26+
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27+
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28+
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29+
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30+
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31+
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32+
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33+
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34+
//
35+
//////////////////////////////////////////////////////////////////////////
36+
37+
#ifndef IECORESCENE_MESHALGO_INL
38+
#define IECORESCENE_MESHALGO_INL
39+
40+
namespace IECoreScene
41+
{
42+
43+
namespace MeshAlgo
44+
{
45+
46+
int MeshSplitter::numMeshes() const
47+
{
48+
return m_meshIndices.size();
49+
}
50+
51+
template< typename T >
52+
typename std::vector<T>::const_reference IECoreScene::MeshAlgo::MeshSplitter::value( int segmentId ) const
53+
{
54+
if( segmentId < 0 || segmentId > (int)m_meshIndices.size() )
55+
{
56+
throw IECore::Exception( "Invalid mesh id " + std::to_string( segmentId ) );
57+
}
58+
59+
int firstFace = m_meshIndices[ segmentId ];
60+
int originalFaceIndex = m_faceRemap[ firstFace ];
61+
return PrimitiveVariable::IndexedView<T>( m_segmentPrimitiveVariable )[ originalFaceIndex ];
62+
}
63+
64+
} // namespace MeshAlgo
65+
66+
} // namespace IECoreScene
67+
68+
#endif // IECORESCENE_MESHALGO_INL

0 commit comments

Comments
 (0)