To build polygons using the existing list of vertices, we need to split this list into chunks of the required length. One chunk for each polygon. For a good mesh topology, square polygons are usually built, so the list of vertices is best divided into blocks of 4 vertices.
In general, splitting a list of objects into blocks using Python is not difficult, but we need to take into account that each subsequent polygon uses two points from the previous polygon.
Therefore, having the initial list of points, for example
1 |
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
we can’t use a simple sequence of blocks like
1 |
[[1, 2, 3, 4], [5, 6, 7, 8], ...] |
but we need the following sequence of blocks
1 |
[[1, 2, 3, 4], [3, 4, 5, 6], ...] |
The blocks must overlap by two points.
Let’s write a function that takes a sequence of points in its parameters and returns the sequence, divided into chunks with the specified offset.
1 2 3 |
def chunks(lst, n, offset=0): for i in range(0, len(lst), n - offset): yield lst[i:i + n] |
In the input parameters of the function, we pass a list of points “lst”, the number of elements in one block “n”, and the required value for overlapping points in blocks “offset”.
To test the function in action, let’s create a bmesh object from the current active mesh with just a sequence of vertices.
1 2 3 |
bm = bmesh.new() bm.from_mesh(bpy.context.object.data) bm.verts.ensure_lookup_table() |
and call our funcion
1 2 3 4 5 |
ch = chunks( lst=[vertex for vertex in bm.verts], n=4, offset=2 ) |
We need blocks of 4 vertices, so in the “n” parameter we pass a value of 4, and accordingly the overlap of vertices will be equal to 2, we pass 2 in the “offset” parameter. In the “lst” parameter, we pass a list of mesh vertices.
As a result, we get a set of necessary chunks:
1 2 3 4 5 6 |
for chunk in ch: print(chunk) # [<BMVert(0x00000255AC1E1A90), index=0>, <BMVert(0x00000255AC1E1AC8), index=1>, <BMVert(0x00000255AC1E1B00), index=2>, <BMVert(0x00000255AC1E1B38), index=3>] # [<BMVert(0x00000255AC1E1B00), index=2>, <BMVert(0x00000255AC1E1B38), index=3>, <BMVert(0x00000255AC1E1B70), index=4>, <BMVert(0x00000255AC1E1BA8), index=5>] # ... |
Using the resulting list of chunks, we can create polygons.
1 2 3 |
for chunk in ch: if len(chunk) == 4: bm.faces.new(chunk) |
Checking for the number of points in a chunk is needed to avoid trying to create a polygon based on the last block, which will only have two vertices.