Revision: 40949
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=40949
Author:   ender79
Date:     2011-10-12 06:11:21 +0000 (Wed, 12 Oct 2011)
Log Message:
-----------
implementation of bmesh_urmv (unglue region make vert) and use of it to fix 
ripping corners joining just two faces, which wasn't working before

Modified Paths:
--------------
    branches/bmesh/blender/source/blender/bmesh/bmesh.h
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.h
    branches/bmesh/blender/source/blender/bmesh/operators/createops.c
    branches/bmesh/blender/source/blender/editors/mesh/bmesh_tools.c

Modified: branches/bmesh/blender/source/blender/bmesh/bmesh.h
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/bmesh.h 2011-10-12 03:46:38 UTC 
(rev 40948)
+++ branches/bmesh/blender/source/blender/bmesh/bmesh.h 2011-10-12 06:11:21 UTC 
(rev 40949)
@@ -201,6 +201,9 @@
   (if ccw is 1).*/
 BMEdge *BM_Rotate_Edge ( BMesh *bm, BMEdge *e, int ccw );
 
+/* Rip a single face from a vertex fan */
+BMVert *BM_Rip_Vertex ( BMesh *bm, BMFace *sf, BMVert *sv);
+
 /*updates a face normal*/
 void BM_Face_UpdateNormal ( BMesh *bm, BMFace *f );
 

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c     
2011-10-12 03:46:38 UTC (rev 40948)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mods.c     
2011-10-12 06:11:21 UTC (rev 40949)
@@ -499,7 +499,6 @@
        }
 
        BLI_array_free(faces);
-
        return ne;
 }
 
@@ -563,7 +562,7 @@
 
        if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l && nv) {
                int i, j;
-               
+
                /*interpolate new/changed loop data from copied old faces*/
                for (j=0; j<2; j++) {
                        for (i=0; i<BLI_array_count(oldfaces); i++) {
@@ -723,3 +722,8 @@
 
        return nl->e;
 }
+
+BMVert *BM_Rip_Vertex ( BMesh *bm, BMFace *sf, BMVert *sv)
+{
+       return bmesh_urmv(bm, sf, sv);
+}

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c  
2011-10-12 03:46:38 UTC (rev 40948)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c  
2011-10-12 06:11:21 UTC (rev 40949)
@@ -203,7 +203,7 @@
                /*just return NULL for now*/
                return NULL;
        }
-       
+
        f = BLI_mempool_calloc(bm->fpool);
        bm->totface += 1;
        f->head.type = BM_FACE;
@@ -531,10 +531,9 @@
        len = bmesh_loop_length(l);
 
        for(i=0, curloop = l; i< len; i++, curloop= curloop->next) {
-               bmesh_radial_remove_loop(curloop, curloop->e);
-               /*in case of border edges we HAVE to zero out curloop->radial 
Next/Prev*/
-               curloop->radial_next = curloop->radial_prev = NULL;
-               BLI_array_append(edar, curloop->e);
+               BMEdge *curedge = curloop->e;
+               bmesh_radial_remove_loop(curloop, curedge);
+               BLI_array_append(edar, curedge);
        }
 
        /*actually reverse the loop.*/
@@ -1398,7 +1397,7 @@
 
        /*validate direction of f2's loop cycle is compatible.*/
        if(f1loop->v == f2loop->v) return NULL;
-       
+
        /*
                validate that for each face, each vertex has another edge in 
its disk cycle that is 
                not e, and not shared.
@@ -1480,3 +1479,295 @@
        
        return f1;
 }
+
+/*
+ * BMESH SPLICE VERT
+ *
+ * merges two verts into one (v into vtarget).
+ */
+static int bmesh_splicevert(BMesh *bm, BMVert *v, BMVert *vtarget)
+{
+       BMEdge *e;
+       BMLoop *l;
+       BMIter liter;
+
+       /* verts already spliced */
+       if (v == vtarget) {
+               return 0;
+       }
+
+       /* retarget all the loops of v to vtarget */
+       BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
+               l->v = vtarget;
+       }
+
+       /* move all the edges from v's disk to vtarget's disk */
+       e = v->e;
+       while (e != NULL) {
+               bmesh_disk_remove_edge(e, v);
+               bmesh_edge_swapverts(e, v, vtarget);
+               bmesh_disk_append_edge(e, vtarget);
+               e = v->e;
+       }
+
+       /* v is unused now, and can be killed */
+       BM_Kill_Vert(bm, v);
+
+       return 1;
+}
+
+/* BMESH CUT VERT
+ *
+ * cut all disjoint fans that meet at a vertex, making a unique
+ * vertex for each region. returns an array of all resulting
+ * vertices.
+ */
+static int bmesh_cutvert(BMesh *bm, BMVert *v, BMVert ***vout, int *len)
+{
+       BMEdge **stack = NULL;
+       BLI_array_declare(stack);
+       BMVert **verts = NULL;
+       GHash *visithash;
+       BMIter eiter, liter;
+       BMLoop *l;
+       BMEdge *e;
+       int i, maxindex;
+       BMLoop *nl;
+
+       visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, 
"bmesh_cutvert visithash");
+
+       maxindex = 0;
+       BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+               if (BLI_ghash_haskey(visithash, e)) {
+                       continue;
+               }
+
+               /* Prime the stack with this unvisited edge */
+               BLI_array_append(stack, e);
+
+               /* Walk over edges that:
+                  1) have v as one of the vertices
+                  2) are connected to e through face loop cycles 
+                  assigning a unique index to that group of edges */
+               while (e = BLI_array_pop(stack)) {
+                       BLI_ghash_insert(visithash, e, 
SET_INT_IN_POINTER(maxindex));
+                       BM_SetIndex(e, maxindex);
+
+                       BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+                               nl = (l->v == v) ? l->prev : l->next;
+                               if (!BLI_ghash_haskey(visithash, nl->e)) {
+                                       BLI_array_append(stack, nl->e);
+                               }
+                       }
+               }
+
+               maxindex++;
+       }
+
+       /* Make enough verts to split v for each group */
+       verts = MEM_callocN(sizeof(BMVert *) * maxindex, "bmesh_cutvert");
+       verts[0] = v;
+       for (i = 1; i < maxindex; i++) {
+               verts[i] = BM_Make_Vert(bm, v->co, v);
+       }
+
+       /* Replace v with the new verts in each group */
+       BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
+               i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e));
+               if (i == 0) {
+                       continue;
+               }
+
+               if (l->v == v) {
+                       l->v = verts[i];
+               }
+               if (l->next->v == v) {
+                       l->next->v = verts[i];
+               }
+       }
+
+       BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+               i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, e));
+               if (i == 0) {
+                       continue;
+               }
+
+               BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+                       if (l->v == v) {
+                               l->v = verts[i];
+                       }
+                       if (l->next->v == v) {
+                               l->next->v = verts[i];
+                       }
+               }
+
+               if (e->v1 == v || e->v2 == v) {
+                       bmesh_disk_remove_edge(e, v);
+                       bmesh_edge_swapverts(e, v, verts[i]);
+                       bmesh_disk_append_edge(e, verts[i]);
+               }
+       }
+
+       BLI_ghash_free(visithash, NULL, NULL);
+       BLI_array_free(stack);
+
+       *vout = verts;
+       *len = maxindex;
+
+       return 1;
+}
+
+/* BMESH SPLICE EDGE
+ *
+ * splice two unique edges which share the same two vertices into one edge.
+ *
+ * edges must already have the same vertices
+ */
+static int bmesh_spliceedge(BMesh *bm, BMEdge *e, BMEdge *etarget)
+{
+       BMLoop *l;
+
+       if (!BM_Vert_In_Edge(e, etarget->v1) || !BM_Vert_In_Edge(e, 
etarget->v2)) {
+               /* not the same vertices can't splice */
+               return 0;
+       }
+
+       while (e->l) {
+               l = e->l;
+               bmesh_radial_remove_loop(l, e);
+               bmesh_radial_append(etarget, l);
+       }
+
+       BM_Kill_Edge(bm, e);
+
+       return 1;
+}
+
+/*
+ * BMESH CUT EDGE
+ *
+ * Cuts a single edge into two edge: the original edge and
+ * a new edge that has only "cutl" in its radial.
+ *
+ * Does nothing if cutl is already the only loop in the
+ * edge radial.
+ */
+static int bmesh_cutedge(BMesh *bm, BMEdge *e, BMLoop *cutl)
+{
+       BMEdge *ne;
+
+       BLI_assert(cutl->e == e);
+       BLI_assert(e->l);
+       
+       if (bmesh_radial_length(e->l) < 2) {
+               /* no cut required */
+               return 1;
+       }
+
+       if (cutl == e->l) {
+               e->l = cutl->radial_next;
+       }
+
+       ne = BM_Make_Edge(bm, e->v1, e->v2, e, 0);
+       bmesh_radial_remove_loop(cutl, e);
+       bmesh_radial_append(ne, cutl);
+       cutl->e = ne;
+
+       return 1;
+}
+
+/*
+ * BMESH UNGLUE REGION MAKE VERT
+ *
+ * Disconnects a face from its vertex fan at loop sl.
+ */
+static BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
+{
+       BMVert **vtar;
+       int len, i;
+       BMVert *nv = NULL;
+       BMVert *sv = sl->v;
+
+       /* peel the face from the edge radials on both sides of the
+          loop vert, disconnecting the face from its fan */
+       bmesh_cutedge(bm, sl->e, sl);
+       bmesh_cutedge(bm, sl->prev->e, sl->prev);
+
+       if (bmesh_disk_count(sv) == 2) {
+               /* If there are still only two edges out of sv, then
+                  this whole URMV was just a no-op, so exit now. */
+               return sv;
+       }
+
+       /* Update the disk start, so that v->e points to an edge
+          not touching the split loop. This is so that bmesh_cutvert
+          will leave the original sv on some *other* fan (not the
+          one-face fan that holds the unglue face). */
+       while (sv->e == sl->e || sv->e == sl->prev->e) {
+               sv->e = bmesh_disk_nextedge(sv->e, sv);
+       }
+
+       /* Split all fans connected to the vert, duplicating it for
+          each fans. */
+       bmesh_cutvert(bm, sv, &vtar, &len);
+
+       /* There should have been at least two fans cut apart here,
+          otherwise the early exit would have kicked in. */
+       BLI_assert(len >= 2);
+
+       nv = sl->v;
+
+       /* Desired result here is that a new vert should always be
+          created for the unglue face. This is so we can glue any
+          extras back into the original vert. */
+       BLI_assert(nv != sv);
+       BLI_assert(sv == vtar[0]);
+
+       /* If there are more than two verts as a result, glue together
+          all the verts except the one this URMV intended to create */
+       if (len > 2) {
+               for (i = 0; i < len; i++) {
+                       if (vtar[i] == nv) {
+                               break;
+                       }
+               }
+
+               if (i != len) {
+                       /* Swap the single vert that was needed for the
+                          unglue into the last array slot */
+                       SWAP(BMVert *, vtar[i], vtar[len - 1]);
+
+                       /* And then glue the rest back together */
+                       for (i = 1; i < len - 1; i++) {
+                               bmesh_splicevert(bm, vtar[i], vtar[0]);
+                       }
+               }
+       }
+
+       MEM_freeN(vtar);
+
+       return nv;
+}
+
+/*
+ * BMESH UNGLUE REGION MAKE VERT
+ *
+ * Disconnects a face from its vertex fan at loop sl.
+ */
+BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
+{
+       BMLoop *hl, *sl;
+
+       hl = sl = bm_firstfaceloop(sf);
+       do {
+               if (sl->v == sv) break;
+               sl = sl->next;
+       } while (sl != hl);
+               
+       if (sl->v != sv) {
+               /* sv is not part of sf */
+               return NULL;
+       }
+
+       return bmesh_urmv_loop(bm, sl);
+}

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.c        
2011-10-12 03:46:38 UTC (rev 40948)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.c        
2011-10-12 06:11:21 UTC (rev 40949)
@@ -361,8 +361,21 @@
        return 1;
 }
 
+/*
+ * BMESH RADIAL REMOVE LOOP
+ *
+ * Removes a loop from an radial cycle. If edge e is non-NULL
+ * it should contain the radial cycle, and it will also get
+ * updated (in the case that the edge's link into the radial
+ * cycle was the loop which is being removed from the cycle).
+ */
 void bmesh_radial_remove_loop(BMLoop *l, BMEdge *e)
 {
+       /* if e is non-NULL, l must be in the radial cycle of e */
+       if (e && e != l->e) {
+               bmesh_error();
+       }
+
        if (l->radial_next != l) {
                if (e && l == e->l)
                        e->l = l->radial_next;
@@ -370,12 +383,20 @@
                l->radial_next->radial_prev = l->radial_prev;
                l->radial_prev->radial_next = l->radial_next;
        } else {
-               l->radial_next = l->radial_prev = NULL;
-               if (e && l == e->l)
-                       e->l = NULL;
-               else if (e)
-                       bmesh_error();
+               if (e) {
+                       if (l == e->l) {
+                               e->l = NULL;
+                       }

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to