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
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenlib/BLI_editVert.h1
-rw-r--r--source/blender/include/BIF_editmesh.h2
-rw-r--r--source/blender/src/editmesh_mods.c258
-rw-r--r--source/blender/src/header_view3d.c12
-rw-r--r--source/blender/src/space.c9
-rw-r--r--source/blender/src/toolbox.c2
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},