static void propagate_split(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) { SmoothEdge *edge2; LinkNode *visited_faces = NULL; #ifdef EDGESPLIT_DEBUG_1 printf("=== START === propagate_split(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif edge2 = find_other_sharp_edge(vert, edge, &visited_faces); if(!edge2) { /* didn't find a sharp or loose edge, so we've hit a dead end */ } else if(!edge_is_loose(edge2)) { /* edge2 is not loose, so it must be sharp */ if(edge_is_loose(edge)) { /* edge is loose, so we can split edge2 at this vert */ split_edge(edge2, vert, mesh); } else if(edge_is_sharp(edge)) { /* both edges are sharp, so we can split the pair at vert */ split_edge(edge, vert, mesh); } else { /* edge is not sharp, so try to split edge2 at its other vert */ split_edge(edge2, other_vert(edge2, vert), mesh); } } else { /* edge2 is loose */ if(edge_is_loose(edge)) { SmoothVert *vert2; ReplaceData repdata; /* can't split edge, what should we do with vert? */ if(linklist_subset(vert->faces, visited_faces)) { /* vert has only one fan of faces attached; don't split it */ } else { /* vert has more than one fan of faces attached; split it */ vert2 = smoothvert_copy(vert, mesh); /* fails in rare cases, see [#26993] */ if(vert2) { /* replace vert with its copy in visited_faces */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); } } } else { /* edge is not loose, so it must be sharp; split it */ split_edge(edge, vert, mesh); } } BLI_linklist_free(visited_faces, NULL); #ifdef EDGESPLIT_DEBUG_1 printf("=== END === propagate_split(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif }
static void number_connected_verts(struct mds* m, mds_id v, struct mds_tag* tag, mds_id* label) { struct queue q; struct mds_set adj[2]; int i; adj[0].n = adj[1].n = 0; if (!visit(m, tag, label, v)) return; make_queue(&q, m->n[MDS_VERTEX]); push_queue(&q, v); while ( ! queue_empty(&q)) { v = pop_queue(&q); mds_get_adjacent(m, v, 1, &adj[1]); adj[0].n = adj[1].n; for (i = 0; i < adj[1].n; ++i) adj[0].e[i] = other_vert(m, adj[1].e[i], v); for (i = 0; i < adj[0].n; ++i) if (visit(m, tag, label, adj[0].e[i])) push_queue(&q, adj[0].e[i]); } free_queue(&q); }
static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) { SmoothEdge *edge2; SmoothVert *vert2; ReplaceData repdata; /* the list of faces traversed while looking for a sharp edge */ LinkNode *visited_faces = NULL; #ifdef EDGESPLIT_DEBUG_1 printf("=== START === split_edge(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif edge2 = find_other_sharp_edge(vert, edge, &visited_faces); if(!edge2) { /* didn't find a sharp or loose edge, so try the other vert */ vert2 = other_vert(edge, vert); push_propagate_stack(edge, vert2, mesh); } else if(!edge_is_loose(edge2)) { /* edge2 is not loose, so it must be sharp */ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh); SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh); SmoothVert *vert2; /* replace edge with its copy in visited_faces */ repdata.find = edge; repdata.replace = copy_edge; BLI_linklist_apply(visited_faces, face_replace_edge, &repdata); /* replace edge2 with its copy in visited_faces */ repdata.find = edge2; repdata.replace = copy_edge2; BLI_linklist_apply(visited_faces, face_replace_edge, &repdata); vert2 = smoothvert_copy(vert, mesh); /* replace vert with its copy in visited_faces (must be done after * edge replacement so edges have correct vertices) */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); /* all copying and replacing is done; the mesh should be consistent. * now propagate the split to the vertices at either end */ push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh); push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh); if(smoothedge_has_vert(edge, vert)) push_propagate_stack(edge, vert, mesh); } else { /* edge2 is loose */ SmoothEdge *copy_edge = smoothedge_copy(edge, mesh); SmoothVert *vert2; /* replace edge with its copy in visited_faces */ repdata.find = edge; repdata.replace = copy_edge; BLI_linklist_apply(visited_faces, face_replace_edge, &repdata); vert2 = smoothvert_copy(vert, mesh); /* bug [#29205] which is caused by exactly the same reason as [#26316] this check will only prevent crash without fixing actual issue and some vertices can stay unsplitted when they should (sergey) */ if(vert2) { /* replace vert with its copy in visited_faces (must be done after * edge replacement so edges have correct vertices) */ repdata.find = vert; repdata.replace = vert2; BLI_linklist_apply(visited_faces, face_replace_vert, &repdata); } /* copying and replacing is done; the mesh should be consistent. * now propagate the split to the vertex at the other end */ push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh); if(smoothedge_has_vert(edge, vert)) push_propagate_stack(edge, vert, mesh); } BLI_linklist_free(visited_faces, NULL); #ifdef EDGESPLIT_DEBUG_1 printf("=== END === split_edge(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif }