diff options
author | Chris Want <cwant@ualberta.ca> | 2005-12-30 02:26:48 +0300 |
---|---|---|
committer | Chris Want <cwant@ualberta.ca> | 2005-12-30 02:26:48 +0300 |
commit | 10d67f254c6ed61b395402294b91ffb3389c41a8 (patch) | |
tree | 307c47168593acb4f0f8c85fcd5dffbde3f344c7 | |
parent | eec7b460fcc71d31e90ae96ac56fe8986ac95483 (diff) |
With the royal blessing of guitarGeek, I commit the sharp/flat mesh
editmode selection tools. The documentation can (currently) be
found here:
http://mediawiki.blender.org/index.php/Requests/SharpFlatSelect
-rw-r--r-- | source/blender/blenlib/BLI_editVert.h | 1 | ||||
-rw-r--r-- | source/blender/include/BIF_editmesh.h | 2 | ||||
-rw-r--r-- | source/blender/src/editmesh_mods.c | 258 | ||||
-rw-r--r-- | source/blender/src/header_view3d.c | 12 | ||||
-rw-r--r-- | source/blender/src/space.c | 9 | ||||
-rw-r--r-- | source/blender/src/toolbox.c | 2 |
6 files changed, 283 insertions, 1 deletions
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index 5e393570e94..a11e1ebfeff 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -66,6 +66,7 @@ typedef struct HashEdge { typedef struct EditEdge { struct EditEdge *next, *prev; + /* Note: vn is for general purpose temporary storage */ struct EditVert *v1, *v2, *vn; short f1, f2; /* short, f1 is (ab)used in subdiv */ unsigned char f, h, dir, seam; diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index 632509953e0..b1620ec58a6 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -134,6 +134,8 @@ extern void editmesh_align_view_to_selected(struct View3D *v3d, int axis); /* Selection */ extern void select_non_manifold(void); +extern void select_sharp_edges(void); +extern void select_linked_flat_faces(void); extern void select_faces_by_numverts(int numverts); extern void select_more(void); extern void select_less(void); diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 3c568266c05..5d811950c6b 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -1506,6 +1506,264 @@ void select_faces_by_numverts(int numverts) BIF_undo_push("Select non-Triangles/Quads"); } +void select_sharp_edges(void) +{ + /* Find edges that have exactly two neighboring faces, + * check the angle between those faces, and if angle is + * small enough, select the edge + */ + EditMesh *em = G.editMesh; + EditEdge *eed; + EditFace *efa; + EditFace **efa1; + EditFace **efa2; + long edgecount = 0, i, *vnptr; + static short sharpness = 135; + float fsharpness; + + if(G.scene->selectmode==SCE_SELECT_FACE) { + error("Doesn't work in face selection mode"); + return; + } + + if(button(&sharpness,0, 180,"Max Angle:")==0) return; + /* if faces are at angle 'sharpness', then the face normals + * are at angle 180.0 - 'sharpness' (convert to radians too) + */ + fsharpness = ((180.0 - sharpness) * M_PI) / 180.0; + + i=0; + /* count edges, (ab)use vn to be a long */ + eed= em->edges.first; + while(eed) { + edgecount++; + vnptr = (long *) &eed->vn; + *vnptr = i; + eed= eed->next; + ++i; + } + + /* for each edge, we want a pointer to two adjacent faces */ + efa1 = MEM_callocN(edgecount*sizeof(EditFace *), + "pairs of edit face pointers"); + efa2 = MEM_callocN(edgecount*sizeof(EditFace *), + "pairs of edit face pointers"); + +#define face_table_edge { \ + i = *vnptr; \ + if (i != -1) { \ + if (efa1[i]) { \ + if (efa2[i]) { \ + *vnptr = -1; /* bad, edge has more than two neighbors */ \ + } \ + else { \ + efa2[i] = efa; \ + } \ + } \ + else { \ + efa1[i] = efa; \ + } \ + } \ + } + + /* find the adjacent faces of each edge, we want only two */ + efa= em->faces.first; + while(efa) { + vnptr = (long *) &efa->e1->vn; + face_table_edge; + vnptr = (long *) &efa->e2->vn; + face_table_edge; + vnptr = (long *) &efa->e3->vn; + face_table_edge; + if (efa->e4) { + vnptr = (long *) &efa->e4->vn; + face_table_edge; + } + efa= efa->next; + } + +#undef face_table_edge + + eed= em->edges.first; + while(eed) { + vnptr = (long *) &eed->vn; + i = *vnptr; + if (i != -1) { + /* edge has two or less neighboring faces */ + if ( (efa1[i]) && (efa2[i]) ) { + /* edge has exactly two neighboring faces, check angle */ + float angle; + angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] + + efa1[i]->n[1]*efa2[i]->n[1] + + efa1[i]->n[2]*efa2[i]->n[2]); + if (fabs(angle) >= fsharpness) + EM_select_edge(eed, 1); + } + } + + eed= eed->next; + } + + MEM_freeN(efa1); + MEM_freeN(efa2); + + countall(); + addqueue(curarea->win, REDRAW, 0); + BIF_undo_push("Select Sharp Edges"); +} + +void select_linked_flat_faces(void) +{ + /* Find faces that are linked to selected faces that are + * relatively flat (angle between faces is higher than + * specified angle) + */ + EditMesh *em = G.editMesh; + EditEdge *eed; + EditFace *efa; + EditFace **efa1; + EditFace **efa2; + long edgecount = 0, i, *vnptr, faceselcount=0, faceselcountold=0; + static short sharpness = 135; + float fsharpness; + + if(G.scene->selectmode!=SCE_SELECT_FACE) { + error("Only works in face selection mode"); + return; + } + + if(button(&sharpness,0, 180,"Min Angle:")==0) return; + /* if faces are at angle 'sharpness', then the face normals + * are at angle 180.0 - 'sharpness' (convert to radians too) + */ + fsharpness = ((180.0 - sharpness) * M_PI) / 180.0; + + i=0; + /* count edges, (ab)use vn to be a long */ + eed= em->edges.first; + while(eed) { + edgecount++; + vnptr = (long *) &eed->vn; + *vnptr = i; + eed= eed->next; + ++i; + } + + /* for each edge, we want a pointer to two adjacent faces */ + efa1 = MEM_callocN(edgecount*sizeof(EditFace *), + "pairs of edit face pointers"); + efa2 = MEM_callocN(edgecount*sizeof(EditFace *), + "pairs of edit face pointers"); + +#define face_table_edge { \ + i = *vnptr; \ + if (i != -1) { \ + if (efa1[i]) { \ + if (efa2[i]) { \ + *vnptr = -1; /* bad, edge has more than two neighbors */ \ + } \ + else { \ + efa2[i] = efa; \ + } \ + } \ + else { \ + efa1[i] = efa; \ + } \ + } \ + } + + /* find the adjacent faces of each edge, we want only two */ + efa= em->faces.first; + while(efa) { + vnptr = (long *) &efa->e1->vn; + face_table_edge; + vnptr = (long *) &efa->e2->vn; + face_table_edge; + vnptr = (long *) &efa->e3->vn; + face_table_edge; + if (efa->e4) { + vnptr = (long *) &efa->e4->vn; + face_table_edge; + } + + /* while were at it, count the selected faces */ + if (efa->f & SELECT) ++faceselcount; + + efa= efa->next; + } + +#undef face_table_edge + + eed= em->edges.first; + while(eed) { + vnptr = (long *) &eed->vn; + i = *vnptr; + if (i != -1) { + /* edge has two or less neighboring faces */ + if ( (efa1[i]) && (efa2[i]) ) { + /* edge has exactly two neighboring faces, check angle */ + float angle; + angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] + + efa1[i]->n[1]*efa2[i]->n[1] + + efa1[i]->n[2]*efa2[i]->n[2]); + /* flag sharp edges */ + if (fabs(angle) >= fsharpness) + *vnptr = -1; + } + else { + /* less than two neighbors */ + *vnptr = -1; + } + } + + eed= eed->next; + } + +#define select_flat_neighbor { \ + i = *vnptr; \ + if (i!=-1) { \ + if (! (efa1[i]->f & SELECT) ) { \ + EM_select_face(efa1[i], 1); \ + ++faceselcount; \ + } \ + if (! (efa2[i]->f & SELECT) ) { \ + EM_select_face(efa2[i], 1); \ + ++faceselcount; \ + } \ + } \ + } + + while (faceselcount != faceselcountold) { + faceselcountold = faceselcount; + + efa= em->faces.first; + while(efa) { + if (efa->f & SELECT) { + vnptr = (long *) &efa->e1->vn; + select_flat_neighbor; + vnptr = (long *) &efa->e2->vn; + select_flat_neighbor; + vnptr = (long *) &efa->e3->vn; + select_flat_neighbor; + if (efa->e4) { + vnptr = (long *) &efa->e4->vn; + select_flat_neighbor; + } + } + efa= efa->next; + } + } + +#undef select_flat_neighbor + + MEM_freeN(efa1); + MEM_freeN(efa2); + + countall(); + addqueue(curarea->win, REDRAW, 0); + BIF_undo_push("Select Linked Flat Faces"); +} + void select_non_manifold(void) { EditMesh *em = G.editMesh; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index c2f83c637fd..c52704e4020 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -859,6 +859,12 @@ void do_view3d_select_meshmenu(void *arg, int event) case 13: /* select non-triangles/quads */ select_faces_by_numverts(5); break; + case 14: /* select less */ + select_sharp_edges(); + break; + case 15: /* select less */ + select_linked_flat_faces(); + break; } allqueue(REDRAWVIEW3D, 0); @@ -887,6 +893,12 @@ static uiBlock *view3d_select_meshmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Non-Manifold|Ctrl Alt Shift M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Sharp Edges|Ctrl Alt Shift S", + 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Linked flat faces|Ctrl Alt Shift F", + 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index f94a459bfad..404d3e5bb09 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1245,6 +1245,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) edge_flip(); else if (G.qual==0) addedgeface_mesh(); + else if ( G.qual == + (LR_SHIFTKEY | LR_ALTKEY | LR_CTRLKEY) ) { + select_linked_flat_faces(); + } + } else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) addsegment_nurb(); } @@ -1632,7 +1637,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) initTransform(TFM_TOSPHERE, CTX_NONE); Transform(); } - + if ( G.qual == (LR_SHIFTKEY | LR_ALTKEY | LR_CTRLKEY) ) { + if(G.obedit->type==OB_MESH) select_sharp_edges(); + } } else if(G.qual==LR_ALTKEY) { if(G.f & G_WEIGHTPAINT) diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index b99535119fa..61a9eb6418d 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -1700,6 +1700,8 @@ static TBitem tb_mesh_select[]= { { 0, "SEPR", 0, NULL}, { 0, "Random...", 5, NULL}, { 0, "Non-Manifold|Shift Ctrl Alt M", 9, NULL}, +{ 0, "Sharp Edges|Shift Ctrl Alt S", 14, NULL}, +{ 0, "Linked Flat Faces|Shift Ctrl Alt F", 15, NULL}, { 0, "Triangles|Shift Ctrl Alt 3", 11, NULL}, { 0, "Quads|Shift Ctrl Alt 4", 12, NULL}, { 0, "Non-Triangles/Quads|Shift Ctrl Alt 5", 13, NULL}, |