Style Cleanup:
[blender-staging.git] / source / blender / bmesh / intern / bmesh_mods.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_mods.c
24  *  \ingroup bmesh
25  *
26  * This file contains functions for locally modifying
27  * the topology of existing mesh data. (split, join, flip etc).
28  */
29
30 #include <limits.h>
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_listBase.h"
34
35 #include "BLI_utildefines.h"
36 #include "BLI_linklist.h"
37 #include "BLI_ghash.h"
38 #include "BLI_math.h"
39 #include "BLI_array.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_smallhash.h"
42
43 #include "bmesh.h"
44 #include "bmesh_private.h"
45
46 #include <stdlib.h>
47 #include <string.h>
48
49 /**
50  *                      bmesh_dissolve_disk
51  *
52  *  Turns the face region surrounding a manifold vertex into
53  *  A single polygon.
54  *
55  *
56  * Example:
57  *
58  *          |=========|             |=========|
59  *          |  \   /  |             |         |
60  * Before:  |    V    |      After: |         |
61  *          |  /   \  |             |         |
62  *          |=========|             |=========|
63  *
64  *
65  */
66 #if 1
67 int BM_Dissolve_Vert(BMesh *bm, BMVert *v)
68 {
69         BMIter iter;
70         BMEdge *e;
71         int len = 0;
72
73         if (!v) {
74                 return FALSE;
75         }
76         
77         e = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v);
78         for ( ; e; e = BMIter_Step(&iter)) {
79                 len++;
80         }
81         
82         if (len == 1) {
83                 if (v->e)
84                         BM_Kill_Edge(bm, v->e);
85                 BM_Kill_Vert(bm, v);
86                 return TRUE;
87         }
88
89         if (BM_Nonmanifold_Vert(bm, v)) {
90                 if (!v->e) BM_Kill_Vert(bm, v);
91                 else if (!v->e->l) {
92                         BM_Kill_Edge(bm, v->e);
93                         BM_Kill_Vert(bm, v);
94                 }
95                 else {
96                         return FALSE;
97                 }
98
99                 return TRUE;
100         }
101
102         return BM_Dissolve_Disk(bm, v);
103 }
104
105 int BM_Dissolve_Disk(BMesh *bm, BMVert *v)
106 {
107         BMFace *f, *f2;
108         BMEdge *e, *keepedge = NULL, *baseedge = NULL;
109         int len = 0;
110
111         if (BM_Nonmanifold_Vert(bm, v)) {
112                 return FALSE;
113         }
114         
115         if (v->e) {
116                 /* v->e we keep, what else */
117                 e = v->e;
118                 do {
119                         e = bmesh_disk_nextedge(e, v);
120                         if (!(BM_Edge_Share_Faces(e, v->e))) {
121                                 keepedge = e;
122                                 baseedge = v->e;
123                                 break;
124                         }
125                         len++;
126                 } while (e != v->e);
127         }
128         
129         /* this code for handling 2 and 3-valence verts
130          * may be totally bad */
131         if (keepedge == NULL && len == 3) {
132                 /* handle specific case for three-valence.  solve it by
133                  * increasing valence to four.  this may be hackish. .  */
134                 BMLoop *loop = e->l;
135                 if (loop->v == v) loop = loop->next;
136                 if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL))
137                         return FALSE;
138
139                 if (!BM_Dissolve_Disk(bm, v)) {
140                         return FALSE;
141                 }
142                 return TRUE;
143         }
144         else if (keepedge == NULL && len == 2) {
145                 /* collapse the verte */
146                 e = BM_Collapse_Vert_Faces(bm, v->e, v, 1.0, TRUE);
147
148                 if (!e) {
149                         return FALSE;
150                 }
151
152                 /* handle two-valenc */
153                 f = e->l->f;
154                 f2 = e->l->radial_next->f;
155
156                 if (f != f2 && !BM_Join_TwoFaces(bm, f, f2, e)) {
157                         return FALSE;
158                 }
159
160                 return TRUE;
161         }
162
163         if (keepedge) {
164                 int done = 0;
165
166                 while (!done) {
167                         done = 1;
168                         e = v->e;
169                         do {
170                                 f = NULL;
171                                 len = bmesh_radial_length(e->l);
172                                 if (len == 2 && (e != baseedge) && (e != keepedge)) {
173                                         f = BM_Join_TwoFaces(bm, e->l->f, e->l->radial_next->f, e);
174                                         /* return if couldn't join faces in manifold
175                                          * conditions */
176                                         //!disabled for testing why bad things happen
177                                         if (!f) {
178                                                 return FALSE;
179                                         }
180                                 }
181
182                                 if (f) {
183                                         done = 0;
184                                         break;
185                                 }
186                                 e = bmesh_disk_nextedge(e, v);
187                         } while (e != v->e);
188                 }
189
190                 /* collapse the verte */
191                 e = BM_Collapse_Vert_Faces(bm, baseedge, v, 1.0, TRUE);
192
193                 if (!e) {
194                         return FALSE;
195                 }
196                 
197                 /* get remaining two face */
198                 f = e->l->f;
199                 f2 = e->l->radial_next->f;
200
201                 if (f != f2) {
202                         /* join two remaining face */
203                         if (!BM_Join_TwoFaces(bm, f, f2, e)) {
204                                 return FALSE;
205                         }
206                 }
207         }
208
209         return TRUE;
210 }
211 #else
212 void BM_Dissolve_Disk(BMesh *bm, BMVert *v)
213 {
214         BMFace *f;
215         BMEdge *e;
216         BMIter iter;
217         int done, len;
218         
219         if (v->e) {
220                 done = 0;
221                 while (!done) {
222                         done = 1;
223                         
224                         /* loop the edges looking for an edge to dissolv */
225                         for (e = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v); e;
226                              e = BMIter_Step(&iter)) {
227                                 f = NULL;
228                                 len = bmesh_cycle_length(&(e->l->radial));
229                                 if (len == 2) {
230                                         f = BM_Join_TwoFaces(bm, e->l->f, ((BMLoop *)(e->l->radial_next))->f, e);
231                                 }
232                                 if (f) {
233                                         done = 0;
234                                         break;
235                                 }
236                         };
237                 }
238                 BM_Collapse_Vert_Faces(bm, v->e, v, 1.0, TRUE);
239         }
240 }
241 #endif
242
243 /**
244  * BM_Join_TwoFaces
245  *
246  *  Joins two adjacenct faces togather.
247  *
248  *  Because this method calls to BM_Join_Faces to do its work, ff a pair
249  *  of faces share multiple edges, the pair of faces will be joined at
250  *  every edge (not just edge e). This part of the functionality might need
251  *  to be reconsidered.
252  *
253  *  If the windings do not match the winding of the new face will follow
254  *  f1's winding (i.e. f2 will be reversed before the join).
255  *
256  * Returns:
257  *       pointer to the combined face
258  */
259
260 BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
261 {
262         BMLoop *l1, *l2;
263         BMEdge *jed = NULL;
264         BMFace *faces[2] = {f1, f2};
265         
266         jed = e;
267         if (!jed) {
268                 BMLoop *l_first;
269                 /* search for an edge that has both these faces in its radial cycl */
270                 l1 = l_first = BM_FACE_FIRST_LOOP(f1);
271                 do {
272                         if (l1->radial_next->f == f2) {
273                                 jed = l1->e;
274                                 break;
275                         }
276                 } while ((l1 = l1->next) != l_first);
277         }
278
279         if (!jed) {
280                 bmesh_error();
281                 return NULL;
282         }
283         
284         l1 = jed->l;
285         
286         if (!l1) {
287                 bmesh_error();
288                 return NULL;
289         }
290         
291         l2 = l1->radial_next;
292         if (l1->v == l2->v) {
293                 bmesh_loop_reverse(bm, f2);
294         }
295
296         f1 = BM_Join_Faces(bm, faces, 2);
297         
298         return f1;
299 }
300
301 /* connects two verts together, automatically (if very naively) finding the
302  * face they both share (if there is one) and splittling it.  use this at your
303  * own risk, as it doesn't handle the many complex cases it should (like zero-area faces,
304  * multiple faces, etc).
305  *
306  * this is really only meant for cases where you don't know before hand the face
307  * the two verts belong to for splitting (e.g. the subdivision operator).
308  */
309
310 BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf)
311 {
312         BMIter iter, iter2;
313         BMVert *v;
314         BMLoop *nl;
315         BMFace *face;
316
317         /* be warned: this can do weird things in some ngon situation, see BM_LegalSplit */
318         for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face = BMIter_Step(&iter)) {
319                 for (v = BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v = BMIter_Step(&iter2)) {
320                         if (v == v2) {
321                                 face = BM_Split_Face(bm, face, v1, v2, &nl, NULL);
322
323                                 if (nf) *nf = face;
324                                 return nl->e;
325                         }
326                 }
327         }
328
329         return NULL;
330 }
331
332 /**
333  * BM_Split_Face
334  *
335  *  Splits a single face into two.
336  *
337  *   f - the original face
338  *   v1 & v2 - vertices which define the split edge, must be different
339  *   nl - pointer which will receive the BMLoop for the split edge in the new face
340  *
341  *  Notes: the
342
343  *  Returns -
344  *        Pointer to the newly created face representing one side of the split
345  *   if the split is successful (and the original original face will be the
346  *   other side). NULL if the split fails.
347  *
348  */
349
350 BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *UNUSED(example))
351 {
352         const int has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS);
353         BMFace *nf, *of;
354         
355         /* do we have a multires layer */
356         if (has_mdisp) {
357                 of = BM_Copy_Face(bm, f, 0, 0);
358         }
359         
360         nf = bmesh_sfme(bm, f, v1, v2, nl, NULL);
361         
362         if (nf) {
363                 BM_Copy_Attributes(bm, bm, f, nf);
364                 copy_v3_v3(nf->no, f->no);
365
366                 /* handle multires update */
367                 if (has_mdisp && (nf != f)) {
368                         BMLoop *l_iter;
369                         BMLoop *l_first;
370
371                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
372                         do {
373                                 BM_loop_interp_from_face(bm, l_iter, of, FALSE, TRUE);
374                         } while ((l_iter = l_iter->next) != l_first);
375
376                         l_iter = l_first = BM_FACE_FIRST_LOOP(nf);
377                         do {
378                                 BM_loop_interp_from_face(bm, l_iter, of, FALSE, TRUE);
379                         } while ((l_iter = l_iter->next) != l_first);
380
381                         BM_Kill_Face(bm, of);
382
383                         BM_multires_smooth_bounds(bm, f);
384                         BM_multires_smooth_bounds(bm, nf);
385                 }
386         }
387
388         return nf;
389 }
390
391 /**
392  *                      BM_Collapse_Vert_Faces
393  *
394  *  Collapses a vertex that has only two manifold edges
395  *  onto a vertex it shares an edge with. Fac defines
396  *  the amount of interpolation for Custom Data.
397  *
398  *  Note that this is not a general edge collapse function.
399  *
400  * Note this function is very close to 'BM_Collapse_Vert_Edges', both collapse
401  * a vertex and return a new edge. Except this takes a factor and merges
402  * custom data.
403  *
404  *  BMESH_TODO:
405  *    Insert error checking for KV valance.
406  *
407  * @param fac The factor along the edge
408  * @param join_faces When true the faces around the vertex will be joined
409  * otherwise collapse the vertex by merging the 2 edges this vert touches into one.
410  *  @returns The New Edge
411  */
412
413 BMEdge *BM_Collapse_Vert_Faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, const int join_faces)
414 {
415         BMEdge *ne = NULL;
416         BMVert *tv = bmesh_edge_getothervert(ke, kv);
417
418         BMEdge *e2;
419         BMVert *tv2;
420
421         BMIter iter;
422         BMLoop *l = NULL, *kvloop = NULL, *tvloop = NULL;
423
424         void *src[2];
425         float w[2];
426
427         /* Only intended to be called for 2-valence vertices */
428         BLI_assert(bmesh_disk_count(kv) <= 2);
429
430
431         /* first modify the face loop data  */
432         w[0] = 1.0f - fac;
433         w[1] = fac;
434
435         if (ke->l) {
436                 l = ke->l;
437                 do {
438                         if (l->v == tv && l->next->v == kv) {
439                                 tvloop = l;
440                                 kvloop = l->next;
441
442                                 src[0] = kvloop->head.data;
443                                 src[1] = tvloop->head.data;
444                                 CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data);
445                         }
446                         l = l->radial_next;
447                 } while (l != ke->l);
448         }
449
450         /* now interpolate the vertex data */
451         BM_Data_Interp_From_Verts(bm, kv, tv, kv, fac);
452
453         e2 = bmesh_disk_nextedge(ke, kv);
454         tv2 = BM_OtherEdgeVert(e2, kv);
455
456         if (join_faces) {
457                 BMFace **faces = NULL, *f;
458                 BLI_array_staticdeclare(faces, 8);
459
460                 BM_ITER(f, &iter, bm, BM_FACES_OF_VERT, kv) {
461                         BLI_array_append(faces, f);
462                 }
463
464                 if (BLI_array_count(faces) >= 2) {
465                         BMFace *f2 = BM_Join_Faces(bm, faces, BLI_array_count(faces));
466                         if (f2) {
467                                 BMLoop *nl = NULL;
468                                 if (BM_Split_Face(bm, f2, tv, tv2, &nl, NULL)) {
469                                         ne = nl->e;
470                                 }
471                         }
472                 }
473
474                 BLI_array_free(faces);
475
476                 return ne;
477         }
478
479         /* single face or no faces */
480         /* same as BM_Collapse_Vert_Edges() however we already
481          * have vars to perform this operation so dont call. */
482         bmesh_jekv(bm, ke, kv);
483         ne = BM_Edge_Exist(tv, tv2);
484
485         return ne;
486 }
487
488
489 /**
490  *                      BM_Collapse_Vert_Edges
491  *
492  * Collapses a vertex onto another vertex it shares an edge with.
493  *
494  * Returns -
495  * The New Edge
496  */
497
498 BMEdge *BM_Collapse_Vert_Edges(BMesh *bm, BMEdge *ke, BMVert *kv)
499 {
500         /* nice example implimentation but we want loops to have their customdata
501          * accounted for */
502 #if 0
503         BMEdge *ne = NULL;
504
505         /* Collapse between 2 edges */
506
507         /* in this case we want to keep all faces and not join them,
508          * rather just get rid of the veretex - see bug [#28645] */
509         BMVert *tv  = bmesh_edge_getothervert(ke, kv);
510         if (tv) {
511                 BMEdge *e2 = bmesh_disk_nextedge(ke, kv);
512                 if (e2) {
513                         BMVert *tv2 = BM_OtherEdgeVert(e2, kv);
514                         if (tv2) {
515                                 /* only action, other calls here only get the edge to return */
516                                 bmesh_jekv(bm, ke, kv);
517
518                                 ne = BM_Edge_Exist(tv, tv2);
519                         }
520                 }
521         }
522
523         return ne;
524 #else
525         /* with these args faces are never joined, same as above
526          * but account for loop customdata */
527         return BM_Collapse_Vert_Faces(bm, ke, kv, 1.0f, FALSE);
528 #endif
529 }
530
531 #undef DO_V_INTERP
532
533 /**
534  *                      BM_split_edge
535  *
536  *      Splits an edge. v should be one of the vertices in e and
537  *  defines the direction of the splitting operation for interpolation
538  *  purposes.
539  *
540  *  Returns -
541  *      the new vert
542  */
543
544 BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percent)
545 {
546         BMVert *nv, *v2;
547         BMFace **oldfaces = NULL;
548         BMEdge *dummy;
549         BLI_array_staticdeclare(oldfaces, 32);
550         SmallHash hash;
551
552         /* we need this for handling multire */
553         if (!ne)
554                 ne = &dummy;
555
556         /* do we have a multires layer */
557         if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l) {
558                 BMLoop *l;
559                 int i;
560                 
561                 l = e->l;
562                 do {
563                         BLI_array_append(oldfaces, l->f);
564                         l = l->radial_next;
565                 } while (l != e->l);
566                 
567                 /* create a hash so we can differentiate oldfaces from new face */
568                 BLI_smallhash_init(&hash);
569                 
570                 for (i = 0; i < BLI_array_count(oldfaces); i++) {
571                         oldfaces[i] = BM_Copy_Face(bm, oldfaces[i], 1, 1);
572                         BLI_smallhash_insert(&hash, (intptr_t)oldfaces[i], NULL);
573                 }
574         }
575
576         v2 = bmesh_edge_getothervert(e, v);
577         nv = bmesh_semv(bm, v, e, ne);
578         if (nv == NULL) {
579                 return NULL;
580         }
581
582         sub_v3_v3v3(nv->co, v2->co, v->co);
583         madd_v3_v3v3fl(nv->co, v->co, nv->co, percent);
584
585         if (ne) {
586                 (*ne)->head.hflag = e->head.hflag;
587                 BM_Copy_Attributes(bm, bm, e, *ne);
588         }
589
590         /* v->nv->v2 */
591         BM_Data_Facevert_Edgeinterp(bm, v2, v, nv, e, percent);
592         BM_Data_Interp_From_Verts(bm, v, v2, nv, percent);
593
594         if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l && nv) {
595                 int i, j;
596
597                 /* interpolate new/changed loop data from copied old face */
598                 for (j = 0; j < 2; j++) {
599                         for (i = 0; i < BLI_array_count(oldfaces); i++) {
600                                 BMEdge *e1 = j ? *ne : e;
601                                 BMLoop *l, *l2;
602                                 
603                                 l = e1->l;
604                                 if (!l) {
605                                         bmesh_error();
606                                         break;
607                                 }
608                                 
609                                 do {
610                                         if (!BLI_smallhash_haskey(&hash, (intptr_t)l->f)) {
611                                                 BMLoop *l2_first;
612
613                                                 l2 = l2_first = BM_FACE_FIRST_LOOP(l->f);
614                                                 do {
615                                                         BM_loop_interp_multires(bm, l2, oldfaces[i]);
616                                                 } while ((l2 = l2->next) != l2_first);
617                                         }
618                                         l = l->radial_next;
619                                 } while (l != e1->l);
620                         }
621                 }
622                 
623                 /* destroy the old face */
624                 for (i = 0; i < BLI_array_count(oldfaces); i++) {
625                         BM_Kill_Face_Verts(bm, oldfaces[i]);
626                 }
627                 
628                 /* fix boundaries a bit, doesn't work too well quite ye */
629 #if 0
630                 for (j = 0; j < 2; j++) {
631                         BMEdge *e1 = j ? *ne : e;
632                         BMLoop *l, *l2;
633                         
634                         l = e1->l;
635                         if (!l) {
636                                 bmesh_error();
637                                 break;
638                         }
639                         
640                         do {
641                                 BM_multires_smooth_bounds(bm, l->f);
642                                 l = l->radial_next;
643                         } while (l != e1->l);
644                 }
645 #endif
646                 
647                 BLI_array_free(oldfaces);
648                 BLI_smallhash_release(&hash);
649         }
650         
651         return nv;
652 }
653
654 BMVert  *BM_Split_Edge_Multi(BMesh *bm, BMEdge *e, int numcuts)
655 {
656         int i;
657         float percent;
658         BMVert *nv = NULL;
659         
660         for (i = 0; i < numcuts; i++) {
661                 percent = 1.0f / (float)(numcuts + 1 - i);
662                 nv = BM_Split_Edge(bm, e->v2, e, NULL, percent);
663         }
664         return nv;
665 }
666
667 int BM_Validate_Face(BMesh *bm, BMFace *face, FILE *err)
668 {
669         BMIter iter;
670         BLI_array_declare(verts);
671         BMVert **verts = NULL;
672         BMLoop *l;
673         int ret = 1, i, j;
674         
675         if (face->len == 2) {
676                 fprintf(err, "warning: found two-edged face. face ptr: %p\n", face);
677                 fflush(err);
678         }
679
680         for (l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, face); l; l = BMIter_Step(&iter)) {
681                 BLI_array_growone(verts);
682                 verts[BLI_array_count(verts) - 1] = l->v;
683                 
684                 if (l->e->v1 == l->e->v2) {
685                         fprintf(err, "Found bmesh edge with identical verts!\n");
686                         fprintf(err, "  edge ptr: %p, vert: %p\n",  l->e, l->e->v1);
687                         fflush(err);
688                         ret = 0;
689                 }
690         }
691
692         for (i = 0; i < BLI_array_count(verts); i++) {
693                 for (j = 0; j < BLI_array_count(verts); j++) {
694                         if (j == i) {
695                                 continue;
696                         }
697
698                         if (verts[i] == verts[j]) {
699                                 fprintf(err, "Found duplicate verts in bmesh face!\n");
700                                 fprintf(err, "  face ptr: %p, vert: %p\n", face, verts[i]);
701                                 fflush(err);
702                                 ret = 0;
703                         }
704                 }
705         }
706         
707         BLI_array_free(verts);
708         return ret;
709 }
710
711 /*
712  *         BM Rotate Edge
713  *
714  * Spins an edge topologically, either counter-clockwise or clockwise.
715  * If ccw is true, the edge is spun counter-clockwise, otherwise it is
716  * spun clockwise.
717  *
718  * Returns the spun edge.  Note that this works by dissolving the edge
719  * then re-creating it, so the returned edge won't have the same pointer
720  * address as the original one.
721  *
722  * Returns NULL on error (e.g., if the edge isn't surrounded by exactly
723  * two faces).
724  */
725 BMEdge *BM_Rotate_Edge(BMesh *bm, BMEdge *e, int ccw)
726 {
727         BMVert *v1, *v2;
728         BMLoop *l, *l1, *l2, *nl;
729         BMFace *f;
730         BMIter liter;
731
732         v1 = e->v1;
733         v2 = e->v2;
734
735         if (BM_Edge_FaceCount(e) != 2)
736                 return NULL;
737
738         f = BM_Join_TwoFaces(bm, e->l->f, e->l->radial_next->f, e);
739
740         if (f == NULL)
741                 return NULL;
742
743         BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
744                 if (l->v == v1)
745                         l1 = l;
746                 else if (l->v == v2)
747                         l2 = l;
748         }
749         
750         if (ccw) {
751                 l1 = l1->prev;
752                 l2 = l2->prev;
753         }
754         else {
755                 l1 = l1->next;
756                 l2 = l2->next;
757         }
758
759         if (!BM_Split_Face(bm, f, l1->v, l2->v, &nl, NULL))
760                 return NULL;
761
762         return nl->e;
763 }
764
765 BMVert *BM_Rip_Vertex ( BMesh *bm, BMFace *sf, BMVert *sv)
766 {
767         return bmesh_urmv(bm, sf, sv);
768 }