Skip to content

Commit 91b9ae5

Browse files
MeshAlgo::triangulate : Refactor and fix reserve() sizes
The refactor isn't needed - I had originally thought it might make sense to expose a function that just returned the indices needed by distributePoints, without the overhead of actually reindexing the data - before I realized that there's actually no need for triangulate to reindex the data at all. I can stuff this function back into where it came from if you prefer it, but I find it a little clearer with a separate function that handles the indices. The only difference in behaviour is that it now sets the reserve sizes correctly ( it would be easy enough to do this to the original code if we do revert the refactor ).
1 parent e4782a4 commit 91b9ae5

File tree

1 file changed

+106
-84
lines changed

1 file changed

+106
-84
lines changed

src/IECoreScene/MeshAlgoTriangulate.cpp

Lines changed: 106 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,101 @@ using namespace IECoreScene;
4848
namespace
4949
{
5050

51+
// Compute all the new indices needed to triangulate the mesh.
52+
// \todo : Multithread this.
53+
void triangulateMeshIndices(
54+
const MeshPrimitive *mesh,
55+
std::vector<int> &newVertexIds,
56+
std::vector<int> &newFaceVertexIds,
57+
std::vector<int> &newUniformIds,
58+
const IECore::Canceller *canceller
59+
)
60+
{
61+
const std::vector<int> &verticesPerFace = mesh->verticesPerFace()->readable();
62+
const std::vector<int> &vertexIds = mesh->vertexIds()->readable();
63+
64+
newVertexIds.clear();
65+
newFaceVertexIds.clear();
66+
newUniformIds.clear();
67+
68+
int numTris = 0;
69+
for( auto n : verticesPerFace )
70+
{
71+
numTris += n - 2;
72+
}
73+
74+
newVertexIds.reserve( numTris * 3 );
75+
newFaceVertexIds.reserve( numTris * 3 );
76+
newUniformIds.reserve( numTris );
77+
78+
int faceVertexIdStart = 0;
79+
for( int faceIdx = 0; faceIdx < (int)verticesPerFace.size(); faceIdx++ )
80+
{
81+
if( ( faceIdx % 100 ) == 0 )
82+
{
83+
Canceller::check( canceller );
84+
}
85+
86+
int numFaceVerts = verticesPerFace[ faceIdx ];
87+
88+
if( numFaceVerts > 3 )
89+
{
90+
/// For the time being, just do a simple triangle fan.
91+
92+
const int i0 = faceVertexIdStart + 0;
93+
const int v0 = vertexIds[i0];
94+
95+
int i1 = faceVertexIdStart + 1;
96+
int i2 = faceVertexIdStart + 2;
97+
int v1 = vertexIds[i1];
98+
int v2 = vertexIds[i2];
99+
100+
for( int i = 1; i < numFaceVerts - 1; i++ )
101+
{
102+
i1 = faceVertexIdStart + ( ( i + 0 ) % numFaceVerts );
103+
i2 = faceVertexIdStart + ( ( i + 1 ) % numFaceVerts );
104+
v1 = vertexIds[i1];
105+
v2 = vertexIds[i2];
106+
107+
/// Triangulate the vertices
108+
newVertexIds.push_back( v0 );
109+
newVertexIds.push_back( v1 );
110+
newVertexIds.push_back( v2 );
111+
112+
/// Store the indices required to rebuild the facevarying primvars
113+
newFaceVertexIds.push_back( i0 );
114+
newFaceVertexIds.push_back( i1 );
115+
newFaceVertexIds.push_back( i2 );
116+
117+
newUniformIds.push_back( faceIdx );
118+
}
119+
}
120+
else
121+
{
122+
assert( numFaceVerts == 3 );
123+
124+
int i0 = faceVertexIdStart + 0;
125+
int i1 = faceVertexIdStart + 1;
126+
int i2 = faceVertexIdStart + 2;
127+
128+
/// Copy across the vertexId data
129+
newVertexIds.push_back( vertexIds[i0] );
130+
newVertexIds.push_back( vertexIds[i1] );
131+
newVertexIds.push_back( vertexIds[i2] );
132+
133+
/// Store the indices required to rebuild the facevarying primvars
134+
newFaceVertexIds.push_back( i0 );
135+
newFaceVertexIds.push_back( i1 );
136+
newFaceVertexIds.push_back( i2 );
137+
138+
newUniformIds.push_back( faceIdx );
139+
}
140+
141+
faceVertexIdStart += numFaceVerts;
142+
}
143+
}
144+
145+
51146
/// A functor for use with despatchTypedData, which copies elements from another vector, as specified by an array of indices into that data
52147
struct TriangleDataRemap
53148
{
@@ -114,96 +209,17 @@ struct TriangulateFn
114209
template<typename T>
115210
ReturnType operator()( T *p )
116211
{
117-
const typename T::ValueType &pReadable = p->readable();
118-
119-
MeshPrimitivePtr meshCopy = m_mesh->copy();
120-
121-
ConstIntVectorDataPtr verticesPerFace = m_mesh->verticesPerFace();
122-
const std::vector<int> &verticesPerFaceReadable = verticesPerFace->readable();
123-
ConstIntVectorDataPtr vertexIds = m_mesh->vertexIds();
124-
const std::vector<int> &vertexIdsReadable = vertexIds->readable();
125-
126212
IntVectorDataPtr newVertexIds = new IntVectorData();
127213
std::vector<int> &newVertexIdsWritable = newVertexIds->writable();
128-
newVertexIdsWritable.reserve( vertexIdsReadable.size() );
129-
130-
IntVectorDataPtr newVerticesPerFace = new IntVectorData();
131-
std::vector<int> &newVerticesPerFaceWritable = newVerticesPerFace->writable();
132-
newVerticesPerFaceWritable.reserve( verticesPerFaceReadable.size() );
133-
134214
std::vector<int> faceVaryingIndices;
135215
std::vector<int> uniformIndices;
136-
int faceVertexIdStart = 0;
137-
int faceIdx = 0;
138-
for( IntVectorData::ValueType::const_iterator it = verticesPerFaceReadable.begin(); it != verticesPerFaceReadable.end(); ++it, ++faceIdx )
139-
{
140-
if( ( faceIdx % 100 ) == 0 )
141-
{
142-
Canceller::check( m_canceller );
143-
}
144-
int numFaceVerts = *it;
216+
triangulateMeshIndices( m_mesh, newVertexIdsWritable, faceVaryingIndices, uniformIndices, m_canceller );
145217

146-
if( numFaceVerts > 3 )
147-
{
148-
/// For the time being, just do a simple triangle fan.
149-
150-
const int i0 = faceVertexIdStart + 0;
151-
const int v0 = vertexIdsReadable[i0];
152-
153-
int i1 = faceVertexIdStart + 1;
154-
int i2 = faceVertexIdStart + 2;
155-
int v1 = vertexIdsReadable[i1];
156-
int v2 = vertexIdsReadable[i2];
157-
158-
for( int i = 1; i < numFaceVerts - 1; i++ )
159-
{
160-
i1 = faceVertexIdStart + ( ( i + 0 ) % numFaceVerts );
161-
i2 = faceVertexIdStart + ( ( i + 1 ) % numFaceVerts );
162-
v1 = vertexIdsReadable[i1];
163-
v2 = vertexIdsReadable[i2];
164-
165-
/// Create a new triangle
166-
newVerticesPerFaceWritable.push_back( 3 );
167-
168-
/// Triangulate the vertices
169-
newVertexIdsWritable.push_back( v0 );
170-
newVertexIdsWritable.push_back( v1 );
171-
newVertexIdsWritable.push_back( v2 );
172-
173-
/// Store the indices required to rebuild the facevarying primvars
174-
faceVaryingIndices.push_back( i0 );
175-
faceVaryingIndices.push_back( i1 );
176-
faceVaryingIndices.push_back( i2 );
177-
178-
uniformIndices.push_back( faceIdx );
179-
}
180-
}
181-
else
182-
{
183-
assert( numFaceVerts == 3 );
184-
185-
int i0 = faceVertexIdStart + 0;
186-
int i1 = faceVertexIdStart + 1;
187-
int i2 = faceVertexIdStart + 2;
188-
189-
newVerticesPerFaceWritable.push_back( 3 );
190-
191-
/// Copy across the vertexId data
192-
newVertexIdsWritable.push_back( vertexIdsReadable[i0] );
193-
newVertexIdsWritable.push_back( vertexIdsReadable[i1] );
194-
newVertexIdsWritable.push_back( vertexIdsReadable[i2] );
195-
196-
/// Store the indices required to rebuild the facevarying primvars
197-
faceVaryingIndices.push_back( i0 );
198-
faceVaryingIndices.push_back( i1 );
199-
faceVaryingIndices.push_back( i2 );
200-
201-
uniformIndices.push_back( faceIdx );
202-
}
203-
204-
faceVertexIdStart += numFaceVerts;
205-
}
218+
IntVectorDataPtr newVerticesPerFace = new IntVectorData();
219+
std::vector<int> &newVerticesPerFaceWritable = newVerticesPerFace->writable();
220+
newVerticesPerFaceWritable.resize( newVertexIdsWritable.size() / 3, 3 );
206221

222+
const typename T::ValueType &pReadable = p->readable();
207223
m_mesh->setTopologyUnchecked( newVerticesPerFace, newVertexIds, pReadable.size(), m_mesh->interpolation() );
208224

209225
/// Rebuild all the facevarying primvars, using the list of indices into the old data we created above.
@@ -230,6 +246,12 @@ struct TriangulateFn
230246
DataPtr result = inputData->copy();
231247
remap->m_other = inputData;
232248

249+
// \todo - using this to reindex data is a waste of time and memory. If there are no indices,
250+
// we could simply set the indices of the primvar to the needed indexes. This would be simpler,
251+
// almost free, and likely results in more efficient computations downstream as well ( since
252+
// the data will be smaller to operate on ). The only non-trivial part of this change is
253+
// evaluating whether anyone is relying on the previous behaviour, or exposing a parameter to
254+
// control it - the next person to touch this code should definitely do this.
233255
despatchTypedData<TriangleDataRemap, TypeTraits::IsVectorTypedData>( result.get(), *remap );
234256

235257
if( it->second.indices )

0 commit comments

Comments
 (0)