@@ -48,6 +48,101 @@ using namespace IECoreScene;
4848namespace
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
52147struct 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