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
path: root/source
diff options
context:
space:
mode:
authorHoward Trickey <howard.trickey@gmail.com>2014-05-16 18:28:15 +0400
committerHoward Trickey <howard.trickey@gmail.com>2014-05-16 18:28:15 +0400
commit758bdcd6c234d119c25231f0ab08763109223d78 (patch)
tree83c2d67d7ed893b50336a7ff27130454f98061cd /source
parent3e38be0000ca73315dc3112811687c20d82dfa2f (diff)
Fix Bevel bugs T39726 and T39108, bevels with wire edges.
This updates the fix in rB27db75363, which had to be undone because it broke other bevels. It also fixes cases where edges went away went doing vertex bevel on vertices with some wire edges.
Diffstat (limited to 'source')
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c115
1 files changed, 109 insertions, 6 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 33ba4b9550e..0f7c3e2e3cf 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -136,7 +136,7 @@ typedef struct BoundVert {
Profile profile; /* edge profile between this and next BoundVert */
bool any_seam; /* are any of the edges attached here seams? */
// int _pad;
-} BoundVert;
+} BoundVert;
/* Mesh structure replacing a vertex */
typedef struct VMesh {
@@ -157,12 +157,14 @@ typedef struct VMesh {
/* Data for a vertex involved in a bevel */
typedef struct BevVert {
BMVert *v; /* original mesh vertex */
- int edgecount; /* total number of edges around the vertex */
+ int edgecount; /* total number of edges around the vertex (excluding wire edges if edge beveling) */
int selcount; /* number of selected edges around the vertex */
+ int wirecount; /* count of wire edges */
float offset; /* offset for this vertex, if vertex_only bevel */
bool any_seam; /* any seams on attached edges? */
bool visited; /* used in graph traversal */
EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */
+ BMEdge **wire_edges; /* array of size wirecount of wire edges */
VMesh *vmesh; /* mesh structure for replacing vertex */
} BevVert;
@@ -2680,6 +2682,25 @@ static void bevel_build_quadstrip(BMesh *bm, BevVert *bv)
}
}
+/* Special case: there is no vmesh pattern because this has only two boundary verts,
+ * and there are no faces in the original mesh at the original vertex.
+ * Since there will be no rebuilt face to make the edge between the boundary verts,
+ * we have to make it here. */
+static void bevel_build_one_wire(BMesh *bm, BevVert *bv)
+{
+ VMesh *vm = bv->vmesh;
+ BMVert *v1, *v2;
+ BMEdge *e_eg;
+
+ BLI_assert(vm->count == 2);
+
+ v1 = mesh_vert(vm, 0, 0, 0)->v;
+ v2 = mesh_vert(vm, 1, 0, 0)->v;
+ e_eg = bv->edges[0].e;
+ BLI_assert(v1 != NULL && v2 != NULL && e_eg != NULL);
+ BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+}
+
/* Given that the boundary is built, now make the actual BMVerts
* for the boundary and the interior of the vertex mesh. */
static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
@@ -2763,7 +2784,8 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
switch (vm->mesh_kind) {
case M_NONE:
- /* do nothing */
+ if (n == 2 && BM_vert_face_count(bv->v) == 0)
+ bevel_build_one_wire(bm, bv);
break;
case M_POLY:
bevel_build_poly(bm, bv);
@@ -2814,6 +2836,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
int i, found_shared_face, ccw_test_sum;
int nsel = 0;
int ntot = 0;
+ int nwire = 0;
int fcnt;
/* Gather input selected edges.
@@ -2821,13 +2844,14 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
* Want edges to be ordered so that they share faces.
* There may be one or more chains of shared faces broken by
* gaps where there are no faces.
- * TODO: Want to ignore wire edges completely for edge beveling.
+ * Want to ignore wire edges completely for edge beveling.
* TODO: make following work when more than one gap.
*/
first_bme = NULL;
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
fcnt = BM_edge_face_count(bme);
+ BM_BEVEL_EDGE_TAG_DISABLE(bme);
if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
BLI_assert(fcnt == 2);
nsel++;
@@ -2838,8 +2862,15 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
/* good to start face chain from this edge */
first_bme = bme;
}
- ntot++;
- BM_BEVEL_EDGE_TAG_DISABLE(bme);
+ if (fcnt > 0 || bp->vertex_only)
+ ntot++;
+ if (BM_edge_is_wire(bme)) {
+ nwire++;
+ /* If edge beveling, exclude wire edges from edges array.
+ * Mark this edge as "chosen" so loop below won't choose it. */
+ if (!bp->vertex_only)
+ BM_BEVEL_EDGE_TAG_ENABLE(bme);
+ }
}
if (!first_bme)
first_bme = v->e;
@@ -2854,8 +2885,13 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
bv->v = v;
bv->edgecount = ntot;
bv->selcount = nsel;
+ bv->wirecount = nwire;
bv->offset = bp->offset;
bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf));
+ if (nwire)
+ bv->wire_edges = (BMEdge **)BLI_memarena_alloc(bp->mem_arena, nwire * sizeof(BMEdge *));
+ else
+ bv->wire_edges = NULL;
bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh));
bv->vmesh->seg = bp->seg;
@@ -3023,6 +3059,17 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->is_seam = true;
}
+ if (nwire) {
+ i = 0;
+ BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(bme)) {
+ BLI_assert(i < bv->wirecount);
+ bv->wire_edges[i++] = bme;
+ }
+ }
+ BLI_assert(i == bv->wirecount);
+ }
+
return bv;
}
@@ -3128,6 +3175,61 @@ static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *
}
}
+/* If there were any wire edges, they need to be reattached somewhere */
+static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
+{
+ BMEdge *e;
+ BMVert *vclosest, *vother, *votherclosest;
+ BevVert *bv, *bvother;
+ BoundVert *bndv, *bndvother;
+ float d, dclosest;
+ int i;
+
+ bv = find_bevvert(bp, v);
+ if (!bv || bv->wirecount == 0 || !bv->vmesh)
+ return;
+
+ for (i = 0; i < bv->wirecount; i++) {
+ e = bv->wire_edges[i];
+ /* look for the new vertex closest to the other end of e */
+ vclosest = NULL;
+ dclosest = FLT_MAX;
+ votherclosest = NULL;
+ vother = BM_edge_other_vert(e, v);
+ bvother = NULL;
+ if (BM_elem_flag_test(vother, BM_ELEM_TAG)) {
+ bvother = find_bevvert(bp, vother);
+ if (!bvother || !bvother->vmesh)
+ return; /* shouldn't happen */
+ }
+ bndv = bv->vmesh->boundstart;
+ do {
+ if (bvother) {
+ bndvother = bvother->vmesh->boundstart;
+ do {
+ d = len_squared_v3v3(bndvother->nv.co, bndv->nv.co);
+ if (d < dclosest) {
+ vclosest = bndv->nv.v;
+ votherclosest = bndvother->nv.v;
+ dclosest = d;
+
+ }
+ } while ((bndvother = bndvother->next) != bvother->vmesh->boundstart);
+ }
+ else {
+ d = len_squared_v3v3(vother->co, bndv->nv.co);
+ if (d < dclosest) {
+ vclosest = bndv->nv.v;
+ votherclosest = vother;
+ dclosest = d;
+ }
+ }
+ } while((bndv = bndv->next) != bv->vmesh->boundstart);
+ if (vclosest)
+ BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE);
+ }
+}
+
static void bev_merge_end_uvs(BMesh *bm, BevVert *bv, EdgeHalf *e)
{
VMesh *vm = bv->vmesh;
@@ -3504,6 +3606,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type,
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bevel_rebuild_existing_polygons(bm, &bp, v);
+ bevel_reattach_wires(bm, &bp, v);
}
}