2012-02-06 06:10:11 +00:00
|
|
|
/*
|
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): Joseph Eagar.
|
|
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2009-01-21 07:03:39 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
|
|
|
|
|
#include "bmesh.h"
|
2009-02-28 12:49:18 +00:00
|
|
|
#include "mesh_intern.h"
|
2009-01-21 07:03:39 +00:00
|
|
|
#include "bmesh_private.h"
|
2009-11-23 14:41:22 +00:00
|
|
|
#include "BLI_math.h"
|
2009-09-17 23:05:33 +00:00
|
|
|
#include "BLI_array.h"
|
2009-01-21 07:03:39 +00:00
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2009-03-08 15:02:49 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2009-01-21 07:03:39 +00:00
|
|
|
|
|
|
|
|
#define FACE_MARK 1
|
2009-03-08 15:02:49 +00:00
|
|
|
#define FACE_ORIG 2
|
|
|
|
|
#define FACE_NEW 4
|
2009-03-09 09:52:32 +00:00
|
|
|
#define EDGE_MARK 1
|
|
|
|
|
|
|
|
|
|
#define VERT_MARK 1
|
|
|
|
|
|
2011-11-16 17:09:41 +00:00
|
|
|
static int UNUSED_FUNCTION(check_hole_in_region)(BMesh *bm, BMFace *f)
|
2011-11-07 09:02:10 +00:00
|
|
|
{
|
2009-03-09 09:52:32 +00:00
|
|
|
BMWalker regwalker;
|
|
|
|
|
BMIter liter2;
|
|
|
|
|
BMLoop *l2, *l3;
|
|
|
|
|
BMFace *f2;
|
2011-03-20 16:30:39 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* checks if there are any unmarked boundary edges in the face regio */
|
2009-03-09 09:52:32 +00:00
|
|
|
|
2012-02-06 05:18:08 +00:00
|
|
|
BMW_Init(®walker, bm, BMW_ISLAND,
|
|
|
|
|
BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, FACE_MARK,
|
|
|
|
|
BMW_NIL_LAY);
|
2009-03-09 09:52:32 +00:00
|
|
|
f2 = BMW_Begin(®walker, f);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; f2; f2 = BMW_Step(®walker)) {
|
2009-03-09 09:52:32 +00:00
|
|
|
l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; l2; l2 = BMIter_Step(&liter2)) {
|
2009-03-09 09:52:32 +00:00
|
|
|
l3 = bmesh_radial_nextloop(l2);
|
2012-02-07 01:46:47 +00:00
|
|
|
if ( BMO_TestFlag(bm, l3->f, FACE_MARK) !=
|
|
|
|
|
BMO_TestFlag(bm, l2->f, FACE_MARK))
|
2009-03-09 09:52:32 +00:00
|
|
|
{
|
|
|
|
|
if (!BMO_TestFlag(bm, l2->e, EDGE_MARK)) {
|
2012-02-07 01:46:47 +00:00
|
|
|
return FALSE;
|
2009-03-09 09:52:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
BMW_End(®walker);
|
|
|
|
|
|
2012-02-07 01:46:47 +00:00
|
|
|
return TRUE;
|
2009-03-09 09:52:32 +00:00
|
|
|
}
|
2009-02-15 01:02:51 +00:00
|
|
|
|
2009-02-28 12:49:18 +00:00
|
|
|
void dissolvefaces_exec(BMesh *bm, BMOperator *op)
|
2009-01-21 07:03:39 +00:00
|
|
|
{
|
2009-03-08 15:02:49 +00:00
|
|
|
BMOIter oiter;
|
2011-03-20 14:49:16 +00:00
|
|
|
BMFace *f, *f2 /* , *nf = NULL */;
|
2011-03-27 02:56:41 +00:00
|
|
|
BLI_array_declare(faces);
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_declare(regions);
|
2011-03-27 02:56:41 +00:00
|
|
|
BMFace ***regions = NULL;
|
|
|
|
|
BMFace **faces = NULL;
|
2009-03-13 13:11:50 +00:00
|
|
|
BMWalker regwalker;
|
2011-05-13 10:59:30 +00:00
|
|
|
int i;
|
2009-02-28 12:49:18 +00:00
|
|
|
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
BMO_Flag_Buffer(bm, op, "faces", FACE_MARK, BM_FACE);
|
2009-03-08 15:02:49 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* collect region */
|
2011-03-27 02:56:41 +00:00
|
|
|
BMO_ITER(f, &oiter, bm, op, "faces", BM_FACE) {
|
2009-03-08 15:02:49 +00:00
|
|
|
if (!BMO_TestFlag(bm, f, FACE_MARK)) continue;
|
|
|
|
|
|
2011-03-27 02:56:41 +00:00
|
|
|
BLI_array_empty(faces);
|
2012-02-06 04:37:27 +00:00
|
|
|
faces = NULL; /* forces different allocatio */
|
2009-02-28 12:49:18 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* yay, walk */
|
2012-02-06 05:18:08 +00:00
|
|
|
BMW_Init(®walker, bm, BMW_ISLAND,
|
|
|
|
|
BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, FACE_MARK,
|
|
|
|
|
BMW_NIL_LAY);
|
|
|
|
|
|
2009-03-13 13:11:50 +00:00
|
|
|
f2 = BMW_Begin(®walker, f);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; f2; f2 = BMW_Step(®walker)) {
|
2011-03-27 02:56:41 +00:00
|
|
|
BLI_array_append(faces, f2);
|
2009-03-13 13:11:50 +00:00
|
|
|
}
|
|
|
|
|
BMW_End(®walker);
|
2011-03-27 02:56:41 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
for (i = 0; i < BLI_array_count(faces); i++) {
|
2011-03-27 02:56:41 +00:00
|
|
|
f2 = faces[i];
|
2009-03-13 13:11:50 +00:00
|
|
|
BMO_ClearFlag(bm, f2, FACE_MARK);
|
|
|
|
|
BMO_SetFlag(bm, f2, FACE_ORIG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BMO_HasError(bm)) {
|
|
|
|
|
BMO_ClearStack(bm);
|
|
|
|
|
BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
|
|
|
|
|
goto cleanup;
|
2009-02-28 12:49:18 +00:00
|
|
|
}
|
2009-03-13 13:11:50 +00:00
|
|
|
|
2011-03-27 02:56:41 +00:00
|
|
|
BLI_array_append(faces, NULL);
|
|
|
|
|
BLI_array_append(regions, faces);
|
2009-02-28 12:49:18 +00:00
|
|
|
}
|
2009-03-08 15:02:49 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
for (i = 0; i < BLI_array_count(regions); i++) {
|
|
|
|
|
int tot = 0;
|
2009-03-08 15:02:49 +00:00
|
|
|
|
2011-03-27 02:56:41 +00:00
|
|
|
faces = regions[i];
|
|
|
|
|
if (!faces[0]) {
|
2009-03-14 02:52:16 +00:00
|
|
|
BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED,
|
2012-02-06 04:37:27 +00:00
|
|
|
"Could not find boundary of dissolve region");
|
2009-03-14 02:52:16 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
}
|
2009-03-22 23:16:43 +00:00
|
|
|
|
2011-03-27 02:56:41 +00:00
|
|
|
while (faces[tot])
|
|
|
|
|
tot++;
|
|
|
|
|
|
|
|
|
|
f = BM_Join_Faces(bm, faces, tot);
|
2009-03-09 15:15:17 +00:00
|
|
|
if (!f) {
|
|
|
|
|
BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED,
|
2012-02-06 04:37:27 +00:00
|
|
|
"Could not create merged face");
|
2009-03-09 15:15:17 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* if making the new face failed (e.g. overlapping test)
|
2012-02-06 06:03:46 +00:00
|
|
|
* unmark the original faces for deletion */
|
2009-03-09 09:52:32 +00:00
|
|
|
BMO_ClearFlag(bm, f, FACE_ORIG);
|
2009-03-08 15:02:49 +00:00
|
|
|
BMO_SetFlag(bm, f, FACE_NEW);
|
|
|
|
|
|
2009-02-28 12:49:18 +00:00
|
|
|
}
|
|
|
|
|
|
2009-03-08 15:02:49 +00:00
|
|
|
BMO_CallOpf(bm, "del geom=%ff context=%d", FACE_ORIG, DEL_FACES);
|
2009-03-09 15:15:17 +00:00
|
|
|
if (BMO_HasError(bm)) goto cleanup;
|
2009-03-08 15:02:49 +00:00
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
BMO_Flag_To_Slot(bm, op, "regionout", FACE_NEW, BM_FACE);
|
2009-03-08 15:02:49 +00:00
|
|
|
|
|
|
|
|
cleanup:
|
2012-02-06 04:37:27 +00:00
|
|
|
/* free/cleanu */
|
|
|
|
|
for (i = 0; i < BLI_array_count(regions); i++) {
|
2010-07-14 22:06:10 +00:00
|
|
|
if (regions[i]) MEM_freeN(regions[i]);
|
2009-03-08 15:02:49 +00:00
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_free(regions);
|
2009-02-28 12:49:18 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* almost identical to dissolve edge, except it cleans up vertice */
|
2009-06-23 05:35:49 +00:00
|
|
|
void dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
|
2009-06-18 04:39:33 +00:00
|
|
|
{
|
2011-03-20 14:49:16 +00:00
|
|
|
/* BMOperator fop; */
|
2009-06-18 04:39:33 +00:00
|
|
|
BMOIter oiter;
|
|
|
|
|
BMIter iter;
|
|
|
|
|
BMVert *v, **verts = NULL;
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_declare(verts);
|
2009-06-18 04:39:33 +00:00
|
|
|
BMEdge *e;
|
2011-03-20 14:49:16 +00:00
|
|
|
/* BMFace *f; */
|
2009-06-18 04:39:33 +00:00
|
|
|
int i;
|
|
|
|
|
|
2009-06-23 05:35:49 +00:00
|
|
|
BMO_ITER(e, &oiter, bm, op, "edges", BM_EDGE) {
|
2009-06-18 04:39:33 +00:00
|
|
|
if (BM_Edge_FaceCount(e) == 2) {
|
|
|
|
|
BMO_SetFlag(bm, e->v1, VERT_MARK);
|
|
|
|
|
BMO_SetFlag(bm, e->v2, VERT_MARK);
|
|
|
|
|
|
2010-07-14 22:06:10 +00:00
|
|
|
BM_Join_TwoFaces(bm, e->l->f,
|
2011-09-12 15:10:59 +00:00
|
|
|
e->l->radial_next->f,
|
|
|
|
|
e);
|
2009-06-18 04:39:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
2012-02-05 23:09:07 +00:00
|
|
|
if (BMO_TestFlag(bm, v, VERT_MARK) && BM_Vert_EdgeCount(v) == 2) {
|
2012-01-17 03:40:37 +00:00
|
|
|
BLI_array_append(verts, v);
|
2009-06-18 04:39:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* clean up extreneous 2-valence vertice */
|
|
|
|
|
for (i = 0; i < BLI_array_count(verts); i++) {
|
2012-01-18 12:31:41 +00:00
|
|
|
if (verts[i]->e) {
|
|
|
|
|
BM_Collapse_Vert_Edges(bm, verts[i]->e, verts[i]);
|
|
|
|
|
}
|
2009-06-18 04:39:33 +00:00
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_free(verts);
|
2009-06-18 04:39:33 +00:00
|
|
|
|
|
|
|
|
//BMO_InitOpf(bm, &fop, "dissolvefaces faces=%ff", FACE_MARK);
|
|
|
|
|
//BMO_Exec_Op(bm, &fop);
|
|
|
|
|
|
|
|
|
|
//BMO_CopySlot(op, &fop, "regionout", "regionout");
|
|
|
|
|
|
|
|
|
|
//BMO_Finish_Op(bm, &fop);
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-23 05:35:49 +00:00
|
|
|
|
|
|
|
|
void dissolveedges_exec(BMesh *bm, BMOperator *op)
|
|
|
|
|
{
|
2011-12-06 02:24:30 +00:00
|
|
|
/* might want to make this an option or mode - campbell */
|
|
|
|
|
#define DISSOLVE_EDGE_VERTS
|
|
|
|
|
|
2011-03-20 14:49:16 +00:00
|
|
|
/* BMOperator fop; */
|
2011-12-06 02:24:30 +00:00
|
|
|
BMOIter eiter;
|
2009-06-23 05:35:49 +00:00
|
|
|
BMEdge *e;
|
|
|
|
|
|
2011-12-06 02:24:30 +00:00
|
|
|
#ifdef DISSOLVE_EDGE_VERTS
|
|
|
|
|
BMIter viter;
|
|
|
|
|
BMVert *v;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DISSOLVE_EDGE_VERTS
|
|
|
|
|
BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
BMO_ClearFlag(bm, v, VERT_MARK);
|
|
|
|
|
}
|
|
|
|
|
#endif /* DISSOLVE_EDGE_VERTS */
|
|
|
|
|
|
|
|
|
|
BMO_ITER(e, &eiter, bm, op, "edges", BM_EDGE) {
|
2012-02-06 04:37:27 +00:00
|
|
|
const int edge_face_count = BM_Edge_FaceCount(e);
|
2011-12-01 02:20:24 +00:00
|
|
|
if (edge_face_count == 2) {
|
2011-12-06 02:24:30 +00:00
|
|
|
|
|
|
|
|
#ifdef DISSOLVE_EDGE_VERTS
|
|
|
|
|
/* later check if these verts are between 2 edges and can dissolve */
|
|
|
|
|
BMO_SetFlag(bm, e->v1, VERT_MARK);
|
|
|
|
|
BMO_SetFlag(bm, e->v2, VERT_MARK);
|
|
|
|
|
#endif /* DISSOLVE_EDGE_VERTS */
|
|
|
|
|
|
2011-12-01 02:20:24 +00:00
|
|
|
/* join faces */
|
2010-07-14 22:06:10 +00:00
|
|
|
BM_Join_TwoFaces(bm, e->l->f,
|
2011-09-12 15:10:59 +00:00
|
|
|
e->l->radial_next->f,
|
|
|
|
|
e);
|
2009-06-23 05:35:49 +00:00
|
|
|
}
|
2011-12-01 02:20:24 +00:00
|
|
|
else if (edge_face_count < 2) {
|
|
|
|
|
/* join verts, assign because first join frees the edge */
|
2012-02-06 04:37:27 +00:00
|
|
|
BMVert *v1 = e->v1, *v2 = e->v2;
|
2011-12-01 02:20:24 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* collapse the ver */
|
2012-01-18 12:31:41 +00:00
|
|
|
if (BM_Vert_EdgeCount(v1) == 2) BM_Collapse_Vert_Edges(bm, v1->e, v1);
|
|
|
|
|
if (BM_Vert_EdgeCount(v2) == 2) BM_Collapse_Vert_Edges(bm, v2->e, v2);
|
2011-12-01 02:20:24 +00:00
|
|
|
|
|
|
|
|
}
|
2009-06-23 05:35:49 +00:00
|
|
|
}
|
2011-12-06 02:24:30 +00:00
|
|
|
|
|
|
|
|
#ifdef DISSOLVE_EDGE_VERTS
|
|
|
|
|
BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
if (BMO_TestFlag(bm, v, VERT_MARK)) {
|
|
|
|
|
if (BM_Vert_EdgeCount(v) == 2) {
|
2012-01-18 12:31:41 +00:00
|
|
|
BM_Collapse_Vert_Edges(bm, v->e, v);
|
2011-12-06 02:24:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* DISSOLVE_EDGE_VERTS */
|
|
|
|
|
|
2009-06-23 05:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
2009-03-13 13:11:50 +00:00
|
|
|
static int test_extra_verts(BMesh *bm, BMVert *v)
|
|
|
|
|
{
|
|
|
|
|
BMIter iter, liter, iter2, iter3;
|
|
|
|
|
BMFace *f, *f2;
|
|
|
|
|
BMLoop *l;
|
|
|
|
|
BMEdge *e;
|
|
|
|
|
int found;
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* test faces around verts for verts that would be wronly killed
|
|
|
|
|
* by dissolve faces. */
|
2009-05-16 16:18:08 +00:00
|
|
|
f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; f; f = BMIter_Step(&iter)) {
|
|
|
|
|
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
|
|
|
|
|
for ( ; l; l = BMIter_Step(&liter)) {
|
2009-03-13 13:11:50 +00:00
|
|
|
if (!BMO_TestFlag(bm, l->v, VERT_MARK)) {
|
2012-02-06 04:37:27 +00:00
|
|
|
/* if an edge around a vert is a boundary edge,
|
|
|
|
|
* then dissolve faces won't destroy it.
|
|
|
|
|
* also if it forms a boundary with one
|
|
|
|
|
* of the face region */
|
|
|
|
|
found = FALSE;
|
2009-05-16 16:18:08 +00:00
|
|
|
e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, l->v);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; e; e = BMIter_Step(&iter2)) {
|
|
|
|
|
if (BM_Edge_FaceCount(e) == 1) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
}
|
2009-05-16 16:18:08 +00:00
|
|
|
f2 = BMIter_New(&iter3, bm, BM_FACES_OF_EDGE, e);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; f2; f2 = BMIter_Step(&iter3)) {
|
2009-03-13 13:11:50 +00:00
|
|
|
if (!BMO_TestFlag(bm, f2, FACE_MARK)) {
|
2012-02-06 04:37:27 +00:00
|
|
|
found = TRUE;
|
2009-03-13 13:11:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-06 04:37:27 +00:00
|
|
|
if (found == TRUE) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (found == FALSE) {
|
|
|
|
|
return FALSE;
|
2009-03-13 13:11:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
return TRUE;
|
2009-03-13 13:11:50 +00:00
|
|
|
}
|
2009-02-15 01:02:51 +00:00
|
|
|
void dissolveverts_exec(BMesh *bm, BMOperator *op)
|
2009-01-21 10:11:01 +00:00
|
|
|
{
|
|
|
|
|
BMOpSlot *vinput;
|
2009-03-08 15:02:49 +00:00
|
|
|
BMIter iter, fiter;
|
2009-02-15 01:02:51 +00:00
|
|
|
BMVert *v;
|
2009-03-08 15:02:49 +00:00
|
|
|
BMFace *f;
|
2011-03-20 14:49:16 +00:00
|
|
|
/* int i; */
|
2009-01-21 10:11:01 +00:00
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
vinput = BMO_GetSlot(op, "verts");
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
BMO_Flag_Buffer(bm, op, "verts", VERT_MARK, BM_VERT);
|
2009-02-15 02:14:40 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
for (v = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BMIter_Step(&iter)) {
|
2009-03-08 15:02:49 +00:00
|
|
|
if (BMO_TestFlag(bm, v, VERT_MARK)) {
|
2012-02-06 04:37:27 +00:00
|
|
|
/* check if it's a two-valence ver */
|
2009-11-06 12:59:58 +00:00
|
|
|
if (BM_Vert_EdgeCount(v) == 2) {
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* collapse the ver */
|
2012-01-18 12:31:41 +00:00
|
|
|
BM_Collapse_Vert_Faces(bm, v->e, v, 1.0f, TRUE);
|
2009-11-06 12:59:58 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
f = BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
|
|
|
|
|
for ( ; f; f = BMIter_Step(&fiter)) {
|
2009-03-13 13:11:50 +00:00
|
|
|
BMO_SetFlag(bm, f, FACE_ORIG);
|
2009-03-08 15:02:49 +00:00
|
|
|
BMO_SetFlag(bm, f, FACE_MARK);
|
2009-02-15 02:14:40 +00:00
|
|
|
}
|
2009-03-13 13:11:50 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* check if our additions to the input to face dissolve
|
|
|
|
|
* will destroy nonmarked vertices. */
|
2009-03-13 13:11:50 +00:00
|
|
|
if (!test_extra_verts(bm, v)) {
|
2012-02-06 04:37:27 +00:00
|
|
|
f = BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
|
|
|
|
|
for ( ; f; f = BMIter_Step(&fiter)) {
|
2009-03-13 13:11:50 +00:00
|
|
|
if (BMO_TestFlag(bm, f, FACE_ORIG)) {
|
|
|
|
|
BMO_ClearFlag(bm, f, FACE_MARK);
|
|
|
|
|
BMO_ClearFlag(bm, f, FACE_ORIG);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-05 15:55:28 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-02-06 04:37:27 +00:00
|
|
|
f = BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
|
|
|
|
|
for ( ; f; f = BMIter_Step(&fiter)) {
|
2009-03-13 13:11:50 +00:00
|
|
|
BMO_ClearFlag(bm, f, FACE_ORIG);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-01-21 10:11:01 +00:00
|
|
|
}
|
2009-03-08 15:02:49 +00:00
|
|
|
}
|
2009-01-21 10:11:01 +00:00
|
|
|
|
2009-03-08 15:02:49 +00:00
|
|
|
BMO_CallOpf(bm, "dissolvefaces faces=%ff", FACE_MARK);
|
|
|
|
|
if (BMO_HasError(bm)) {
|
2011-03-20 14:49:16 +00:00
|
|
|
const char *msg;
|
2009-03-09 09:52:32 +00:00
|
|
|
|
|
|
|
|
BMO_GetError(bm, &msg, NULL);
|
2009-03-08 15:02:49 +00:00
|
|
|
BMO_ClearStack(bm);
|
2012-02-06 04:37:27 +00:00
|
|
|
BMO_RaiseError(bm, op, BMERR_DISSOLVEVERTS_FAILED, msg);
|
2009-03-08 15:02:49 +00:00
|
|
|
}
|
2009-03-09 15:15:17 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* clean up any remainin */
|
|
|
|
|
for (v = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BMIter_Step(&iter)) {
|
2009-03-09 15:15:17 +00:00
|
|
|
if (BMO_TestFlag(bm, v, VERT_MARK)) {
|
|
|
|
|
if (!BM_Dissolve_Vert(bm, v)) {
|
2012-02-06 04:37:27 +00:00
|
|
|
BMO_RaiseError(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL);
|
2009-03-09 15:15:17 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-08 15:02:49 +00:00
|
|
|
}
|
2009-02-15 02:14:40 +00:00
|
|
|
|
2012-02-06 04:37:27 +00:00
|
|
|
/* this code is for cleaning up two-edged faces, it shall become
|
|
|
|
|
* it's own function one day */
|
2009-03-08 15:02:49 +00:00
|
|
|
#if 0
|
2012-02-06 04:37:27 +00:00
|
|
|
/* clean up two-edged face */
|
|
|
|
|
/* basic idea is to keep joining 2-edged faces until their
|
|
|
|
|
* gone. this however relies on joining two 2-edged faces
|
|
|
|
|
* together to work, which doesn't */
|
2009-02-15 02:14:40 +00:00
|
|
|
found3 = 1;
|
|
|
|
|
while (found3) {
|
|
|
|
|
found3 = 0;
|
2012-02-06 04:37:27 +00:00
|
|
|
for (f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BMIter_Step(&iter)) {
|
2009-03-02 02:21:18 +00:00
|
|
|
if (!BM_Validate_Face(bm, f, stderr)) {
|
2009-02-28 12:49:18 +00:00
|
|
|
printf("error.\n");
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-15 02:14:40 +00:00
|
|
|
if (f->len == 2) {
|
|
|
|
|
//this design relies on join faces working
|
|
|
|
|
//with two-edged faces properly.
|
|
|
|
|
//commenting this line disables the
|
|
|
|
|
//outermost loop.
|
|
|
|
|
//found3 = 1;
|
|
|
|
|
found2 = 0;
|
|
|
|
|
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
|
|
|
|
|
fe = l->e;
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; l; l = BMIter_Step(&liter)) {
|
2009-02-15 02:14:40 +00:00
|
|
|
f2 = BMIter_New(&fiter, bm,
|
2009-05-16 16:18:08 +00:00
|
|
|
BM_FACES_OF_EDGE, l->e);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; f2; f2 = BMIter_Step(&fiter)) {
|
2009-02-15 02:14:40 +00:00
|
|
|
if (f2 != f) {
|
[note: do not test quite yet]
Phase 1 of restructuring done. There are now two
distinct subclass systems within the bmesh API;
one is compile-time, and forms the backend of what will
eventually be a "lite" bmesh API for modifiers (the
ones that use bmesh are simply too slow right now).
The other is dynamic, and will be used to implement
multires reprojection.
The idea was to solve as many serious problems with
memory, speed, etc, at once as possible and set up others
to be solved more easily later.
I've also added holes into the data structure, but not
the api; I don't plan to finish implementing that until
after bmesh gets into trunk. I simply wanted to lessen
how much code I'll have to rewrite, since I was doing a
fairly major restructuring anyway.
In addition, I've added iteration support to mempool, to
avoid having to store linked list pointers (though this
has caveats).
Next step: merge in trunk changes. . .oh, what fun :P
2010-07-15 00:55:31 +00:00
|
|
|
BM_Join_TwoFaces(bm, f, f2, l->e);
|
2009-02-15 02:14:40 +00:00
|
|
|
found2 = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (found2) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found2) {
|
|
|
|
|
bmesh_kf(bm, f);
|
|
|
|
|
bmesh_ke(bm, fe);
|
|
|
|
|
}
|
2012-02-06 04:37:27 +00:00
|
|
|
} /* else if (f->len == 3) {
|
2009-02-15 02:14:40 +00:00
|
|
|
BMEdge *ed[3];
|
|
|
|
|
BMVert *vt[3];
|
|
|
|
|
BMLoop *lp[3];
|
2012-02-06 04:37:27 +00:00
|
|
|
int i = 0;
|
2009-02-15 02:14:40 +00:00
|
|
|
|
2009-02-15 14:02:27 +00:00
|
|
|
//check for duplicate edges
|
2009-02-15 02:14:40 +00:00
|
|
|
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
|
2012-02-06 04:37:27 +00:00
|
|
|
for ( ; l; l = BMIter_Step(&liter)) {
|
2009-02-15 14:02:27 +00:00
|
|
|
ed[i] = l->e;
|
|
|
|
|
lp[i] = l;
|
2009-02-15 02:14:40 +00:00
|
|
|
vt[i++] = l->v;
|
|
|
|
|
}
|
|
|
|
|
if (vt[0] == vt[1] || vt[0] == vt[2]) {
|
|
|
|
|
i += 1;
|
2009-02-15 01:02:51 +00:00
|
|
|
}
|
2012-02-06 04:37:27 +00:00
|
|
|
*/
|
2009-02-15 01:02:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-02-15 02:14:40 +00:00
|
|
|
if (oldlen == len) break;
|
|
|
|
|
oldlen = len;
|
|
|
|
|
|
2009-03-08 15:02:49 +00:00
|
|
|
#endif
|