Implements T102359.
The MLoop struct is split into two separate integer arrays called corner_verts
and corner_edges, referring to the vertex each corner is attached to, and the next
edge around the face at each corner. These arrays can be sliced to give access to
just the edges or vertices in a face. Then they are often referred to as "poly_verts"
or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only one
array is used, and simplifications from using regular integer indices instead of
a special purpose struct.
Like the other mesh struct of array refactors, forward compatibility is maintained
by writing files with the older format. This will be done until 4.0 to ease the
transition process.
Looking at a small portion of the patch should give a reader a good impression
for the rest of the changes. I aimed to make the changes as small as possible in
most places, so it's easy to tell the correctness from the diff. Though I found
Blender developers have been very inventive about finding different ways to loop
over the corners of a face.
For performance, nearly every piece of code that deals with Mesh is at least
slightly impacted. Any algorithm that is memory bottle-necked should see an
improvement. As an example, here is a comparison of interpolating a vertex float
attribute to face corners (Ryzen 3700x):
Before: (Average: 3.7 ms, Min: 3.4 ms)
threading::parallel_for(loops.index_range(), 4096, [&](const IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});After: (Average: 2.9 ms, Min: 2.6 ms)
array_utils::gather(src, corner_verts, dst);
That's an improvement of 28% to the average, and 31% to minimum timings.
The better part in my opinion is that it's also a simplification, since a generic
index-based routine can be used with the patch applied.