Hi,
I’ve tried 3 variants of a function that is calculating loose parts from a bmesh structure.
The benchmark is on an cube arrayed x400 twice (so 160000 loose parts).
The first one is iterative and uses a std::queue. Result: about 4 seconds.
The second is recursive. Result: 0.35 seconds
The third is iterative and use a simple array (size is amount of vertices) as replacement for the std::queue. Result: 0.5 seconds
So recursive seems to be faster. But I do not know about its limits (stack size) in Blender’s compilation context (I don’t know either if the compiler is able to translate by itself from recursive to iterative).
Do you have any information about it?
The recursive function code:
Main call:
/* Returns an array of int where each int value corresponds to a loose part number of the corresponding vertex index (from 0 to < part_count) */
int *bm_get_loose_parts(BMesh *bmesh, int *part_count)
{
clock_t t = clock();
int num_verts = bmesh->totvert;
int *loose_part_map = (int *)MEM_malloc_arrayN(num_verts, sizeof(int), __func__);
memset(loose_part_map, -1, num_verts * sizeof(int));
BMVert *vert;
BMIter vert_iter;
BM_ITER_MESH(vert, &vert_iter, bmesh, BM_VERTS_OF_MESH)
{
if (loose_part_map[BM_elem_index_get(vert)] == -1)
{
walk_linked_edges(bmesh, vert, (*part_count), loose_part_map);
(*part_count)++;
}
}
t = clock() - t;
float seconds = (float)t / CLOCKS_PER_SEC;
return loose_part_map;
}
Recursive part:
void walk_linked_edges(BMesh *bmesh, BMVert *vert, int loose_part, int *loose_part_map)
{
loose_part_map[BM_elem_index_get(vert)] = loose_part;
BMEdge *edge;
BMIter edge_iter;
BM_ITER_ELEM(edge, &edge_iter, vert, BM_EDGES_OF_VERT)
{
BMVert *other = BM_edge_other_vert(edge, vert);
if (loose_part_map[BM_elem_index_get(other)] == -1)
{
walk_linked_edges(bmesh, other, loose_part, loose_part_map);
}
}
}