Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-08-16 18:18:54 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-08-16 18:18:54 +0400
commitef8ea14f459e0e765e07fc48858c18dc11cfdfb5 (patch)
tree01af1661f43fc2f2689888971cfe8709bc11e6e8 /source/blender/bmesh/operators/bmo_edgenet.c
parent36c530dec917d548de24d5c31ed77a2ab565ed05 (diff)
rewrite edgenet fill bmesh operator.
previous code created faces with mixed face-flipping and could get very slow, test with ~60,000 edges here hung my system for over 2min (didnt wait for it to finish), new code executes in about 1 second. new code doesn't attempt to flip faces correctly, its quite involved to do so, especially when the new faces are not created adjacent to eachother. so simpler to calculate normals afterwards.
Diffstat (limited to 'source/blender/bmesh/operators/bmo_edgenet.c')
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c1009
1 files changed, 15 insertions, 994 deletions
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 923b877b822..6c88161ca35 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -48,1017 +48,38 @@
#define ELE_NEW 1
#define ELE_ORIG 4
-#define FACE_IGNORE 16
-
-typedef struct EPathNode {
- struct EPathNode *next, *prev;
- BMVert *v;
- BMEdge *e;
- BMEdge *cure;
-} EPathNode;
-
-typedef struct EPath {
- ListBase nodes;
- float weight;
- int group;
-} EPath;
-
-typedef struct PathBase {
- BLI_mempool *nodepool, *pathpool;
-} PathBase;
-
-typedef struct EdgeData {
- int tag;
- int ftag;
- BMDiskLink v1_disk_link, v2_disk_link;
-} EdgeData;
-
-typedef struct VertData {
- BMEdge *e;
- float no[3], offco[3], sco[3]; /* offco is vertex coordinate slightly offset randomly */
- int tag;
-} VertData;
-
-static int count_edge_faces(BMesh *bm, BMEdge *e);
-
-/**** rotation system code * */
-
-BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
-{
- return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
- &(((EdgeData *)e_data)->v2_disk_link);
-}
-
-static bool rotsys_append_edge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
-{
- EdgeData *ed = &edata[BM_elem_index_get(e)];
- VertData *vd = &vdata[BM_elem_index_get(v)];
-
- if (!vd->e) {
- Link *e1 = (Link *)rs_edge_link_get(e, v, ed);
-
- vd->e = e;
- e1->next = e1->prev = (Link *)e;
- }
- else {
- BMDiskLink *dl1, *dl2, *dl3;
- EdgeData *ved = &edata[BM_elem_index_get(vd->e)];
-
- dl1 = rs_edge_link_get(e, v, ed);
- dl2 = rs_edge_link_get(vd->e, v, ved);
- dl3 = dl2->prev ? rs_edge_link_get(dl2->prev, v, &edata[BM_elem_index_get(dl2->prev)]) : NULL;
-
- dl1->next = vd->e;
- dl1->prev = dl2->prev;
-
- dl2->prev = e;
- if (dl3) {
- dl3->next = e;
- }
- }
-
- return true;
-}
-
-static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
-{
- EdgeData *ed = edata + BM_elem_index_get(e);
- VertData *vd = vdata + BM_elem_index_get(v);
- BMDiskLink *e1, *e2;
-
- e1 = rs_edge_link_get(e, v, ed);
- if (e1->prev) {
- e2 = rs_edge_link_get(e1->prev, v, ed);
- e2->next = e1->next;
- }
-
- if (e1->next) {
- e2 = rs_edge_link_get(e1->next, v, ed);
- e2->prev = e1->prev;
- }
-
- if (vd->e == e)
- vd->e = (e != e1->next) ? e1->next : NULL;
-
- e1->next = e1->prev = NULL;
-}
-
-static BMEdge *rotsys_nextedge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *UNUSED(vdata))
-{
- if (v == e->v1)
- return edata[BM_elem_index_get(e)].v1_disk_link.next;
- if (v == e->v2)
- return edata[BM_elem_index_get(e)].v2_disk_link.next;
- return NULL;
-}
-
-static BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *UNUSED(vdata))
-{
- if (v == e->v1)
- return edata[BM_elem_index_get(e)].v1_disk_link.prev;
- if (v == e->v2)
- return edata[BM_elem_index_get(e)].v2_disk_link.prev;
- return NULL;
-}
-
-static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertData *vdata)
-{
- BMEdge **edges = NULL;
- BMEdge *e_first;
- BMEdge *e;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- int i, totedge;
-
- e = e_first = vdata[BM_elem_index_get(v)].e;
- do {
- BLI_array_append(edges, e);
- e = rotsys_nextedge(e, v, edata, vdata);
- } while (e != e_first);
-
- totedge = BLI_array_count(edges);
- for (i = 0; i < totedge / 2; i++) {
- SWAP(BMEdge *, edges[i], edges[totedge - 1 - i]);
- }
-
- vdata[BM_elem_index_get(v)].e = NULL;
- for (i = 0; i < totedge; i++) {
- rotsys_append_edge(edges[i], v, edata, vdata);
- }
-
- BLI_array_free(edges);
-}
-
-static int UNUSED_FUNCTION(rotsys_count)(BMVert *v, EdgeData *edata, VertData *vdata)
-{
- BMEdge *e = vdata[BM_elem_index_get(v)].e;
- int i = 0;
-
- if (!e)
- return 0;
-
- do {
- if (!e)
- return 0;
- e = rotsys_nextedge(e, v, edata, vdata);
-
- if (i >= (1 << 20)) {
- printf("bmesh error: infinite loop in disk cycle!\n");
- return 0;
- }
-
- i += 1;
- } while (e != vdata[BM_elem_index_get(v)].e);
-
- return i;
-}
-
-static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e, **edges = NULL;
- BLI_array_declare(edges);
- BMVert *v, **verts = NULL;
- BMFace *f;
- BLI_array_declare(verts);
- SmallHash visithash, *hash = &visithash;
- int i;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMEdge *e2, *starte;
- BMVert *startv;
- int rad, ok;
-
- rad = count_edge_faces(bm, e);
-
- if (rad < 2) {
- starte = e;
- }
- else {
- continue;
- }
-
- /* do two passes, going forward then backward */
- for (i = 0; i < 2; i++) {
- BLI_smallhash_init(hash);
-
- BLI_array_empty(verts);
- BLI_array_empty(edges);
-
- startv = v = starte->v1;
- e2 = starte;
- ok = 1;
- if (!v || !e2)
- continue;
-
- do {
- if (BLI_smallhash_haskey(hash, (uintptr_t)e2) ||
- BLI_smallhash_haskey(hash, (uintptr_t)v))
- {
- ok = 0;
- break;
- }
-
- BLI_array_append(verts, v);
- BLI_array_append(edges, e2);
-
- BLI_smallhash_insert(hash, (uintptr_t)e2, NULL);
-
- v = BM_edge_other_vert(e2, v);
- e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
- } while (e2 != starte && v != startv);
-
- BLI_smallhash_release(hash);
-
- if (!ok || BLI_array_count(edges) < 3)
- continue;
-
- f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE);
- if (UNLIKELY(f == NULL)) {
- continue;
- }
- }
- }
-
- return 0;
-}
-
-static void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e;
- BMVert *v, **stack = NULL;
- BLI_array_declare(stack);
- int i;
-
- for (i = 0; i < bm->totvert; i++) {
- vdata[i].tag = 0;
- }
-
- while (1) {
- VertData *vd;
- BMVert *startv = NULL;
- float dis;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- vd = vdata + BM_elem_index_get(v);
-
- if (vd->tag)
- continue;
-
- if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
- dis = dot_v3v3(vd->offco, vd->offco);
- startv = v;
- }
- }
-
- if (!startv)
- break;
-
- vd = vdata + BM_elem_index_get(startv);
-
- BLI_array_empty(stack);
- BLI_array_append(stack, startv);
-
- vd->tag = 1;
-
- while (BLI_array_count(stack)) {
- v = BLI_array_pop(stack);
- vd = vdata + BM_elem_index_get(v);
-
- if (!vd->e)
- continue;
-
- e = vd->e;
- do {
- BMVert *v2 = BM_edge_other_vert(e, v);
- VertData *vd2 = vdata + BM_elem_index_get(v2);
-
- if (dot_v3v3(vd->no, vd2->no) < 0.0f + FLT_EPSILON * 2) {
- rotsys_reverse(e, v2, edata, vdata);
- mul_v3_fl(vd2->no, -1.0f);
- }
-
- if (!vd2->tag) {
- BLI_array_append(stack, v2);
- vd2->tag = 1;
- }
-
- e = rotsys_nextedge(e, v, edata, vdata);
- } while (e != vd->e);
- }
- }
-
- BLI_array_free(stack);
-}
-
-static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e;
- BMEdge **edges = NULL;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- BMVert *v;
- RNG *rng;
- /* BMVert **verts = NULL; */
- /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */
- int i;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMIter eiter;
- float no[3], cent[3];
- int j, k = 0, totedge = 0;
-
- if (BM_elem_index_get(v) == -1)
- continue;
-
- BLI_array_empty(edges);
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- BLI_array_append(edges, e);
- totedge++;
- }
- }
-
- copy_v3_v3(cent, v->co);
-
- zero_v3(no);
- for (i = 0; i < totedge; i++) {
- BMEdge *e1, *e2;
- float cno[3], vec1[3], vec2[3];
-
- e1 = edges[i];
- e2 = edges[(i + 1) % totedge];
-
- sub_v3_v3v3(vec1, (BM_edge_other_vert(e1, v))->co, v->co);
- sub_v3_v3v3(vec2, (BM_edge_other_vert(e2, v))->co, v->co);
-
- cross_v3_v3v3(cno, vec1, vec2);
- normalize_v3(cno);
-
- if (i && dot_v3v3(cno, no) < 0.0f + FLT_EPSILON * 10)
- mul_v3_fl(cno, -1.0f);
-
- add_v3_v3(no, cno);
- normalize_v3(no);
- }
-
- /* generate plane-flattened coordinates */
- for (i = 0; i < totedge; i++) {
- BMEdge *e1;
- BMVert *v2;
- float cvec[3], vec1[3];
-
- e1 = edges[i];
- v2 = BM_edge_other_vert(e1, v);
-
- sub_v3_v3v3(vec1, v2->co, v->co);
-
- cross_v3_v3v3(cvec, vec1, no);
- cross_v3_v3v3(vec1, cvec, no);
- normalize_v3(vec1);
-
- mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
- add_v3_v3(vec1, v->co);
-
- copy_v3_v3(vdata[BM_elem_index_get(v2)].sco, vec1);
- }
-
- rng = BLI_rng_new_srandom(0);
-
- /* first, ensure no 0 or 180 angles between adjacent
- * (and that adjacent's adjacent) edges */
- for (i = 0, k = 0; i < totedge; i++) {
- BMEdge *e1, *e2, *e3 = NULL;
- BMVert *v1, *v2, *v3;
- VertData *vd1, *vd2, *vd3;
- float vec1[3], vec2[3], vec3[3], size;
- int s1, s2, s3;
-
- if (totedge < 3)
- continue;
-
- e1 = edges[(i + totedge - 1) % totedge];
- e2 = edges[i];
- e3 = edges[(i + 1) % totedge];
-
- v1 = BM_edge_other_vert(e1, v);
- v2 = BM_edge_other_vert(e2, v);
- v3 = BM_edge_other_vert(e3, v);
-
- vd1 = vdata + BM_elem_index_get(v1);
- vd2 = vdata + BM_elem_index_get(v2);
- vd3 = vdata + BM_elem_index_get(v3);
-
- sub_v3_v3v3(vec1, vd1->sco, cent);
- sub_v3_v3v3(vec2, vd2->sco, cent);
- sub_v3_v3v3(vec3, vd3->sco, cent);
-
- size = (len_v3(vec1) + len_v3(vec3)) * 0.01f;
- normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
-
-#ifdef STRAIGHT
-#undef STRAIGHT
-#endif
-#define STRAIGHT(vec11, vec22) (fabsf(dot_v3v3((vec11), (vec22))) > 1.0f - ((float)FLT_EPSILON * 1000.0f))
-
- s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
-
- if (s1 || s2 || s3) {
- copy_v3_v3(cent, v->co);
-
- for (j = 0; j < 3; j++) {
- float fac = (BLI_rng_get_float(rng) - 0.5f) * size;
- cent[j] += fac;
- }
-
- if (k < 2000) {
- i = 0;
- k++;
- continue;
- }
- else {
- k++;
- continue;
- }
-
- }
- }
-
- BLI_rng_free(rng);
-
- copy_v3_v3(vdata[BM_elem_index_get(v)].offco, cent);
- //copy_v3_v3(v->co, cent);
-
- /* now, sort edges so the triangle fan of all edges
- * has a consistent normal. this is the same as
- * sorting by polar coordinates along a group normal */
- for (j = 0; j < totedge; j++) {
- for (i = 0; i < totedge; i++) {
- BMEdge *e1, *e2, *e3 = NULL;
- BMVert *v1, *v2, *v3;
- VertData *vd1, *vd2, *vd3;
- float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
-
- e1 = edges[(i + totedge - 1) % totedge];
- e2 = edges[i];
- e3 = edges[(i + 1) % totedge];
-
- v1 = BM_edge_other_vert(e1, v);
- v2 = BM_edge_other_vert(e2, v);
- v3 = BM_edge_other_vert(e3, v);
-
- vd1 = vdata + BM_elem_index_get(v1);
- vd2 = vdata + BM_elem_index_get(v2);
- vd3 = vdata + BM_elem_index_get(v3);
-
- sub_v3_v3v3(vec1, vd1->sco, cent);
- sub_v3_v3v3(vec2, vd2->sco, cent);
- sub_v3_v3v3(vec3, vd3->sco, cent);
-
- cross_v3_v3v3(n1, vec1, vec2);
- cross_v3_v3v3(n2, vec2, vec3);
- cross_v3_v3v3(n3, vec1, vec3);
-
- /* this case happens often enough and probably not worth bothering users with,
- * maybe enable for debugging code but not for everyday use - campbell */
-#if 0
- /* Other way to determine if two vectors approach are (nearly) parallel: the
- * cross product of the two vectors will approach zero */
- {
- int s1, s2, s3;
- s1 = (dot_v3v3(n1, n1) < (0.0f + FLT_EPSILON * 10));
- s2 = (dot_v3v3(n2, n2) < (0.0f + FLT_EPSILON * 10));
- s3 = (totedge < 3) ? 0 : (dot_v3v3(n3, n3) < (0.0f + FLT_EPSILON * 10));
-
- if (s1 || s2 || s3) {
- fprintf(stderr, "%s: s1: %d, s2: %d, s3: %dx (bmesh internal error)\n", __func__, s1, s2, s3);
- }
- }
-#endif
-
- normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
-
-
- if (dot_v3v3(n1, n2) < 0.0f) {
- if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON * 10) {
- SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
- }
- else {
- SWAP(BMEdge *, edges[(i + totedge - 1) % totedge], edges[(i + 1) % totedge]);
- SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
- }
- }
- }
- }
-
-#undef STRAIGHT
-
- zero_v3(no);
-
- /* yay, edges are sorted */
- for (i = 0; i < totedge; i++) {
- BMEdge *e1 = edges[i], *e2 = edges[(i + 1) % totedge];
- float eno[3];
-
- normal_tri_v3(eno, BM_edge_other_vert(e1, v)->co, v->co, BM_edge_other_vert(e2, v)->co);
- add_v3_v3(no, eno);
-
- rotsys_append_edge(edges[i], v, edata, vdata);
- }
-
- normalize_v3(no);
- copy_v3_v3(vdata[BM_elem_index_get(v)].no, no);
- }
-
- /* now, make sure rotation system is topologically consistent
- * (e.g. vert normals consistently point either inside or outside) */
- rotsys_make_consistent(bm, edata, vdata);
-
- //rotsys_fill_faces(bm, edata, vdata);
-
-#if 0
- /* create visualizing geometry */
- BMVert *lastv;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMVert *v2;
- BMFace *f;
- int totedge = BM_vert_edge_count(v);
-
- if (BM_elem_index_get(v) == -1)
- continue;
-
- //cv = BM_vert_create(bm, cent, v);
- //BM_elem_index_set(cv, -1); /* set_dirty! */
- i = 0;
- e = vdata[BM_elem_index_get(v)].e;
- lastv = NULL;
- do {
- BMEdge *e2;
- BMVert *v2;
- float f = ((float)i / (float)totedge) * 0.35 + 0.05;
- float co[3];
-
- if (!e)
- break;
-
- if (!BM_edge_other_vert(e, v))
- continue;
-
- sub_v3_v3v3(co, (BM_edge_other_vert(e, v))->co, vdata[BM_elem_index_get(v)].offco);
- mul_v3_fl(co, f);
- add_v3_v3(co, vdata[BM_elem_index_get(v)].offco);
-
- v2 = BM_vert_create(bm, co, NULL);
- BM_elem_index_set(v2, -1); /* set_dirty! */
- //BM_edge_create(bm, cv, v2, NULL, 0);
-
- BM_vert_select_set(bm, v2, true);
- if (lastv) {
- e2 = BM_edge_create(bm, lastv, v2, NULL, 0);
- BM_edge_select_set(bm, e2, true);
- }
-
- lastv = v2;
-
- e = rotsys_nextedge(e, v, edata, vdata);
- i++;
- } while (e != vdata[BM_elem_index_get(v)].e);
- }
-#endif
-
- BLI_array_free(edges);
-}
-
-static PathBase *edge_pathbase_new(void)
-{
- PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
-
- pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512, BLI_MEMPOOL_SYSMALLOC);
- pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512, BLI_MEMPOOL_SYSMALLOC);
-
- return pb;
-}
-
-static void edge_pathbase_free(PathBase *pathbase)
-{
- BLI_mempool_destroy(pathbase->nodepool);
- BLI_mempool_destroy(pathbase->pathpool);
- MEM_freeN(pathbase);
-}
-
-static EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
-{
- EPath *path2;
- EPathNode *node, *node2;
-
- path2 = BLI_mempool_alloc(pb->pathpool);
- path2->nodes.first = path2->nodes.last = NULL;
- path2->weight = 0.0f;
- path2->group = path->group;
-
- for (node = path->nodes.first; node; node = node->next) {
- node2 = BLI_mempool_alloc(pb->nodepool);
- *node2 = *node;
- BLI_addtail(&path2->nodes, node2);
- }
-
- node2 = BLI_mempool_alloc(pb->nodepool);
- node2->v = appendv;
- node2->e = e;
- node2->cure = NULL;
-
- BLI_addtail(&path2->nodes, node2);
-
- return path2;
-}
-
-static EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
-{
- EPath *path;
- EPathNode *node;
-
- path = BLI_mempool_alloc(pb->pathpool);
- node = BLI_mempool_alloc(pb->nodepool);
-
- path->nodes.first = path->nodes.last = NULL;
-
- node->v = start;
- node->e = starte;
- node->cure = NULL;
-
- BLI_addtail(&path->nodes, node);
- path->weight = 0.0f;
-
- return path;
-}
-
-static float edge_weight_path(EPath *path, EdgeData *edata, VertData *UNUSED(vdata))
-{
- EPathNode *node, *first = path->nodes.first;
- float w = 0.0;
-
- for (node = path->nodes.first; node; node = node->next) {
- if (node->e && node != path->nodes.first) {
- w += edata[BM_elem_index_get(node->e)].ftag;
- if (node->prev) {
- /* BMESH_TOD */
- (void)first;
- //w += len_v3v3(node->v->co, first->e->v1->co) * 0.0001f;
- //w += len_v3v3(node->v->co, first->e->v2->co) * 0.0001f;
- }
- }
-
- w += 1.0f;
- }
-
- return w;
-}
-
-
-static void edge_free_path(PathBase *pathbase, EPath *path)
-{
- EPathNode *node, *next;
-
- for (node = path->nodes.first; node; node = next) {
- next = node->next;
- BLI_mempool_free(pathbase->nodepool, node);
- }
-
- BLI_mempool_free(pathbase->pathpool, path);
-}
-
-static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
- VertData *vdata, PathBase *pathbase, int group)
-{
- BMEdge *e;
- GHash *gh = BLI_ghash_ptr_new("createops find shortest path");
- BMVert *v1, *v2;
- BMVert **verts = NULL;
- BLI_array_staticdeclare(verts, 1024);
- Heap *heap = BLI_heap_new();
- EPath *path = NULL, *path2;
- BMVert *startv;
- BMVert *endv;
- EPathNode *node;
- int i;
- const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
-
-
- startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1;
- endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2;
-
- path = edge_path_new(pathbase, startv, edge);
- BLI_ghash_insert(gh, startv, NULL);
- BLI_heap_insert(heap, path->weight, path);
- path->group = group;
-
- while (BLI_heap_size(heap)) {
- VertData *vd;
- EPathNode *last;
- BMFace *f = NULL;
-
- path = BLI_heap_popmin(heap);
- last = path->nodes.last;
- v1 = last->v;
-
- if (v1 == endv) {
- /* make sure this path loop doesn't already exists */
- i = 0;
- BLI_array_empty(verts);
- for (i = 0, node = path->nodes.first; node; node = node->next, i++) {
- BLI_array_grow_one(verts);
- verts[i] = node->v;
- }
-
- if (BM_face_exists(verts, i, &f)) {
- if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) {
- BLI_ghash_remove(gh, endv, NULL, NULL);
- continue;
- }
- }
- break;
- }
-
- vd = vdata + BM_elem_index_get(v1);
- if (!vd->e)
- continue;
-
- v2 = NULL;
- while (1) {
- if (!last->cure) {
- last->cure = e = vdata[BM_elem_index_get(last->v)].e;
- }
- else {
- last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
- if (last->cure == vdata[BM_elem_index_get(last->v)].e) {
- v2 = NULL;
- break;
- }
- }
-
- if (e == edge || !BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
-
- v2 = BM_edge_other_vert(e, last->v);
-
- if (BLI_ghash_haskey(gh, v2)) {
- v2 = NULL;
- continue;
- }
-
- if (use_restrict) {
- int *group_flag = (int *)BMO_slot_map_data_get(slot_restrict, e);
- if (group_flag) {
- if (!(*group_flag & path->group)) {
- v2 = NULL;
- continue;
- }
- }
- }
-
- break;
- }
-
- if (!v2) {
- edge_free_path(pathbase, path);
- path = NULL;
- continue;
- }
-
- /* add path back into heap */
- BLI_heap_insert(heap, path->weight, path);
-
- /* put v2 in gh ma */
- BLI_ghash_insert(gh, v2, NULL);
-
- path2 = edge_copy_add_path(pathbase, path, v2, e);
- path2->weight = edge_weight_path(path2, edata, vdata);
-
- BLI_heap_insert(heap, path2->weight, path2);
- }
-
- if (path && ((EPathNode *)path->nodes.last)->v != endv) {
- edge_free_path(pathbase, path);
- path = NULL;
- }
-
- BLI_array_free(verts);
- BLI_heap_free(heap, NULL);
- BLI_ghash_free(gh, NULL, NULL);
-
- return path;
-}
-
-static int count_edge_faces(BMesh *bm, BMEdge *e)
-{
- int i = 0;
- BMLoop *l = e->l;
-
- if (!l) {
- return 0;
- }
-
- do {
- if (!BMO_elem_flag_test(bm, l->f, FACE_IGNORE)) {
- i++;
- }
-
- l = l->radial_next;
- } while (l != e->l);
-
- return i;
-}
-
-BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int winding[2])
-{
- BMVert *test_v1, *test_v2;
- /* we want to use the reverse winding to the existing order */
- BM_edge_ordered_verts(edge, &test_v2, &test_v1);
-
- /* edges vote on which winding wins out */
- winding[(test_v1 == node->v)]++;
-}
-
-static BMFace *bm_face_from_path(BMesh *bm, EPath *path,
- EdgeData *edata,
- const bool use_fill_check)
-{
- /* accumulte winding directions for each edge which has a face */
- const unsigned int path_len = BLI_countlist(&path->nodes);
- unsigned int winding[2] = {0, 0};
- unsigned int i;
-
- EPathNode *node;
-
- BMVert **verts = BLI_array_alloca(verts, path_len);
- BMEdge **edges = BLI_array_alloca(edges, path_len);
- BMEdge *e;
- BMVert *v;
-
- for (node = path->nodes.first, i = 0; node; node = node->next, i++) {
-
- v = node->v;
- e = BM_edge_exists(v, node->next ?
- node->next->v :
- ((EPathNode *)path->nodes.first)->v);
-
- /* check on the winding */
- if (e->l) {
- if (UNLIKELY(count_edge_faces(bm, e) >= 2)) {
- return NULL;
- }
-
- vote_on_winding(e, node, winding);
- }
-
- verts[i] = v;
- edges[i] = e;
- }
-
- /* do after incase we bail early, above */
- for (i = 0; i < path_len; i++) {
- edata[BM_elem_index_get(edges[i])].ftag++;
- }
-
-
- /* if these are even it doesn't really matter what to do,
- * with consistent geometry one will be zero, the choice is clear */
- if (winding[0] > winding[1]) {
- BLI_array_wrap(verts, path_len, -1);
- BLI_array_reverse(verts, path_len);
- BLI_array_reverse(edges, path_len);
- }
-
- if ((use_fill_check == false) ||
- /* fairly expensive check - see if there are already faces filling this area */
- (BM_face_exists_multi(verts, edges, path_len) == false))
- {
- return BM_face_create(bm, verts, edges, path_len, BM_CREATE_NO_DOUBLE);
- }
- else {
- return NULL;
- }
-}
-
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
{
- BMIter iter;
BMOIter siter;
BMFace *f;
- BMEdge *e;
- EPath *path;
- EdgeData *edata;
- VertData *vdata;
- PathBase *pathbase;
- const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
- int i;
- BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
- BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out");
if (!bm->totvert || !bm->totedge)
return;
- pathbase = edge_pathbase_new();
-
- edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData");
- vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData");
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMO_elem_flag_enable(bm, f, ELE_ORIG);
- }
+ BM_mesh_edgenet(bm, true, FACE_NEW);
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- BM_elem_index_set(e, i); /* set_inline */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
- if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- edata[i].tag = 2;
+ BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
}
+ /* normals are zero'd */
+ BM_face_normal_update(f);
}
- bm->elem_index_dirty &= ~BM_EDGE;
-
- init_rotsys(bm, edata, vdata);
-
- while (1) {
- BMEdge *edge = NULL;
- int group = 0;
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /* if restrict is on, only start on faces in the restrict map */
- if (use_restrict && !BMO_slot_map_contains(slot_restrict, e))
- continue;
-
- if (edata[BM_elem_index_get(e)].tag < 2) {
- edge = e;
-
- if (use_restrict) {
- int gi_iter = 0, gi_count = 0, gi = 0;
- group = BMO_slot_map_int_get(slot_restrict, e);
-
- for (gi_iter = 0; gi_iter < 30; gi_iter++) {
- if (group & (1 << gi_iter)) {
- gi_count++;
- gi = gi_iter;
-
- if (gi_count - 1 == edata[BM_elem_index_get(e)].tag) {
- break;
- }
- }
- }
-
- group = (1 << gi);
- }
-
- break;
- }
- }
-
- if (!edge)
- break;
-
- edata[BM_elem_index_get(edge)].tag += 1;
-
- path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
- if (path && path->nodes.first) {
- BMFace *f = bm_face_from_path(bm, path, edata,
- use_fill_check);
-
- if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
- BMO_elem_flag_enable(bm, f, FACE_NEW);
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- }
-
- if (use_restrict) {
- BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
- }
-
- edge_free_path(pathbase, path);
- }
+ /* recalc normals,
+ * TODO, could do checks to make normals consistent */
+ {
+ BMO_op_callf(bm, op->flag,
+ "recalc_face_normals faces=%S",
+ op, "faces.out");
}
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
-
- edge_pathbase_free(pathbase);
- MEM_freeN(edata);
- MEM_freeN(vdata);
}
static BMEdge *edge_next(BMesh *bm, BMEdge *e)