diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index 57fe08e5305..7a75e605e6c 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -55,14 +55,18 @@ typedef struct EditVert void *p; long l; } tmp; - float no[3]; - float co[3]; - short xs, ys; - unsigned char f, h, f1, f2; - short fast; /* only 0 or 1, for editmesh_fastmalloc */ - short totweight; /* __NLA */ + float no[3]; /*vertex normal */ + float co[3]; /*vertex location */ + short xs, ys; /* used to store a screenspace 2d projection of the verts */ + + /* f stores selection eg. if (eve->f & SELECT) {... + h for hidden. if (!eve->h) {... + f1 and f2 can be used for temp data, clear them first*/ + unsigned char f, h, f1, f2; + short fast; /* only 0 or 1, for editmesh_fastmalloc, do not store temp data here! */ + short totweight; /* __NLA total number of vertex weights for this vertex */ int hash; - struct MDeformWeight *dw; /* __NLA */ + struct MDeformWeight *dw; /* __NLA a pointer to an array of defirm weights */ int keyindex; /* original index #, for restoring key information */ } EditVert; @@ -87,6 +91,7 @@ typedef struct EditEdge struct EditFace *f; void *p; long l; + float fp; } tmp; short f1, f2; /* short, f1 is (ab)used in subdiv */ unsigned char f, h, dir, seam; @@ -111,6 +116,7 @@ typedef struct EditFace struct EditFace *f; void *p; long l; + float fp; } tmp; float n[3], cent[3]; struct TFace tf; /* a copy of original tface. */ diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index bbf2f88134c..4053b8307e1 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -114,6 +114,7 @@ void Crossf(float *c, float *a, float *b) c[2] = a[0] * b[1] - a[1] * b[0]; } +/* Inpf returns the dot product, also called the scalar product and inner product */ float Inpf( float *v1, float *v2) { return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]; diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 7ea473f23fc..54592f1e300 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -760,85 +760,94 @@ void facegroup_select(short mode) { EditMesh *em = G.editMesh; EditFace *efa, *base_efa=NULL; - unsigned int selcount=0; + unsigned int selcount=0, facecount=0, base_idx=0, idx=0; + short ok=0; float thresh=G.scene->toolsettings->doublimit; /* todo. better var for this */ + float *facearea; /*store face areas here*/ for(efa= em->faces.first; efa; efa= efa->next) { if (efa->f & SELECT && !efa->h) { - base_efa= efa; - break; + efa->f1=1; + ok=1; + } else { + efa->f1=0; + } + facecount++; + } + + if (!ok) /* no data selected */ + return; + + /*if mode is 3 then record face areas, 4 record perimeter */ + if (mode==3) { + for(efa= em->faces.first; efa; efa= efa->next) { + efa->tmp.fp= EM_face_area(efa); + } + } else if (mode==4) { + for(efa= em->faces.first; efa; efa= efa->next) { + efa->tmp.fp= EM_face_perimeter(efa); } } - if (!base_efa) - return; - - if (mode==1) { /* same material */ - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h && base_efa->mat_nr == efa->mat_nr) { - EM_select_face(efa, 1); - selcount++; - } - } - } else if (mode==2) { /* same image */ - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h && base_efa->tf.tpage == efa->tf.tpage) { - EM_select_face(efa, 1); - selcount++; - } - } - } else if (mode==3) { /* same area */ - float area, base_area; - base_area= EM_face_area(base_efa); - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - area= EM_face_area(efa); - if (fabs(area-base_area)<=thresh) { - EM_select_face(efa, 1); - selcount++; - } - } - } - } else if (mode==4) { /* same perimeter */ - float perimeter, base_perimeter; - base_perimeter= EM_face_perimeter(base_efa); - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - perimeter= EM_face_perimeter(efa); - if (fabs(perimeter-base_perimeter)<=thresh) { - EM_select_face(efa, 1); - selcount++; - } - } - } - } else if (mode==5) { /* same normal */ - float angle; - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - angle= VecAngle2(base_efa->n, efa->n); - if (angle<=thresh) { - EM_select_face(efa, 1); - selcount++; - } - } - } - } else if (mode==6) { /* same planer */ - float angle, base_dot, dot; - base_dot= base_efa->cent[0]*base_efa->n[0] + base_efa->cent[1]*base_efa->n[1] + base_efa->cent[2]*base_efa->n[2]; - for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h) { - angle= VecAngle2(base_efa->n, efa->n); - if (angle<=thresh) { - dot= efa->cent[0]*base_efa->n[0] + efa->cent[1]*base_efa->n[1] + efa->cent[2]*base_efa->n[2]; - if (fabs(base_dot-dot) <= thresh) { + for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next, base_idx++) { + if (base_efa->f1) { + if (mode==1) { /* same material */ + for(efa= em->faces.first; efa; efa= efa->next) { + if ( + !(efa->f & SELECT) && + !efa->h && + base_efa->mat_nr == efa->mat_nr + ) { EM_select_face(efa, 1); selcount++; } } + } else if (mode==2) { /* same image */ + for(efa= em->faces.first; efa; efa= efa->next) { + if (!(efa->f & SELECT) && !efa->h && base_efa->tf.tpage == efa->tf.tpage) { + EM_select_face(efa, 1); + selcount++; + } + } + } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */ + idx=0; + for(efa= em->faces.first; efa; efa= efa->next, idx++) { + if (!(efa->f & SELECT) && !efa->h) { + if (fabs(efa->tmp.fp-base_efa->tmp.fp)<=thresh) { + EM_select_face(efa, 1); + selcount++; + } + } + } + } else if (mode==5) { /* same normal */ + float angle; + for(efa= em->faces.first; efa; efa= efa->next) { + if (!(efa->f & SELECT) && !efa->h) { + angle= VecAngle2(base_efa->n, efa->n); + if (angle<=thresh) { + EM_select_face(efa, 1); + selcount++; + } + } + } + } else if (mode==6) { /* same planer */ + float angle, base_dot, dot; + base_dot= Inpf(base_efa->cent, base_efa->n); + for(efa= em->faces.first; efa; efa= efa->next) { + if (!(efa->f & SELECT) && !efa->h) { + angle= VecAngle2(base_efa->n, efa->n); + if (angle<=thresh) { + dot=Inpf(efa->cent, base_efa->n); + if (fabs(base_dot-dot) <= thresh) { + EM_select_face(efa, 1); + selcount++; + } + } + } + } } } - } - + } /* end base_efa loop */ if (selcount) { G.totfacesel+=selcount; @@ -859,54 +868,30 @@ void edgegroup_select(short mode) EditMesh *em = G.editMesh; EditEdge *eed, *base_eed=NULL; unsigned int selcount=0; + short ok=0; float thresh=G.scene->toolsettings->doublimit; /* todo. better var for this */ - if (mode==3) { /* set all eed->tmp.l to 0 we use them later.*/ - for(eed= em->edges.first; eed; eed= eed->next) { - if (eed->f & SELECT && !eed->h) { - base_eed= eed; - } - eed->tmp.l=0; - } - } else { - for(eed= em->edges.first; eed; eed= eed->next) { - if (eed->f & SELECT && !eed->h) { - base_eed= eed; - break; - } + + for(eed= em->edges.first; eed; eed= eed->next) { + if (eed->f & SELECT && !eed->h) { + eed->f1=1; + ok=1; + } else { + eed->f1=0; } + /* set all eed->tmp.l to 0 we use it later. + for counting face users*/ + eed->tmp.l=0; } - if (!base_eed) + if (!ok) /* no data selected */ return; - if (mode==1) { /* same length */ - float base_length= VecLenf(base_eed->v1->co, base_eed->v2->co); + if (mode==1) { /*store length*/ for(eed= em->edges.first; eed; eed= eed->next) { - if (!(eed->f & SELECT) && !eed->h && ( fabs(base_length-VecLenf(eed->v1->co, eed->v2->co)) <= thresh ) ) { - EM_select_edge(eed, 1); - selcount++; - } + eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co); } - } else if (mode==2) { /* same direction */ - float base_dir[3], dir[3], angle; - VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co); - for(eed= em->edges.first; eed; eed= eed->next) { - if (!(eed->f & SELECT) && !eed->h) { - VecSubf(dir, eed->v1->co, eed->v2->co); - angle= VecAngle2(base_dir, dir); - - if (angle>90) /* use the smallest angle between the edges */ - angle= fabs(angle-180.0f); - - if (angle<=thresh) { - EM_select_edge(eed, 1); - selcount++; - } - } - } - } else if (mode==3) { /* face users */ - EditFace *efa; - + } else if (mode==3) { /*store face users*/ + EditFace *efa; /* cound how many faces each edge uses use tmp->l */ for(efa= em->faces.first; efa; efa= efa->next) { efa->e1->tmp.l++; @@ -914,14 +899,52 @@ void edgegroup_select(short mode) efa->e3->tmp.l++; if (efa->e4) efa->e4->tmp.l++; } - - for(eed= em->edges.first; eed; eed= eed->next) { - if ((!(eed->f & SELECT) && !eed->h) && (base_eed->tmp.l==eed->tmp.l)) { - EM_select_edge(eed, 1); - selcount++; + } + + for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) { + if (base_eed->f1) { + if (mode==1) { /* same length */ + for(eed= em->edges.first; eed; eed= eed->next) { + if ( + !(eed->f & SELECT) && + !eed->h && + fabs(base_eed->tmp.fp - eed->tmp.fp) <= thresh + ) { + EM_select_edge(eed, 1); + selcount++; + } + } + } else if (mode==2) { /* same direction */ + float base_dir[3], dir[3], angle; + VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co); + for(eed= em->edges.first; eed; eed= eed->next) { + if (!(eed->f & SELECT) && !eed->h) { + VecSubf(dir, eed->v1->co, eed->v2->co); + angle= VecAngle2(base_dir, dir); + + if (angle>90) /* use the smallest angle between the edges */ + angle= fabs(angle-180.0f); + + if (angle<=thresh) { + EM_select_edge(eed, 1); + selcount++; + } + } + } + } else if (mode==3) { /* face users */ + for(eed= em->edges.first; eed; eed= eed->next) { + if ( + !(eed->f & SELECT) && + !eed->h && + base_eed->tmp.l==eed->tmp.l + ) { + EM_select_edge(eed, 1); + selcount++; + } + } } } - } + } if (selcount) { //EM_select_flush(); /* dont use because it can end up selecting more edges and is not usefull*/ @@ -944,39 +967,25 @@ void vertgroup_select(short mode) EditVert *eve, *base_eve=NULL; unsigned int selcount=0; + short ok=0; float thresh=G.scene->toolsettings->doublimit; /* todo. better var for this */ - if (mode==2) { /* set all eve->tmp.l to 0 we use them later.*/ - for(eve= em->verts.first; eve; eve= eve->next) { - if (eve->f & SELECT && !eve->h) { - base_eve= eve; - } - eve->tmp.l=0; - } - } else { - for(eve= em->verts.first; eve; eve= eve->next) { - if (eve->f & SELECT && !eve->h) { - base_eve= eve; - break; - } + for(eve= em->verts.first; eve; eve= eve->next) { + if (eve->f & SELECT && !eve->h) { + eve->f1=1; + ok=1; + } else { + eve->f1=0; } + /* set all eve->tmp.l to 0 we use them later.*/ + eve->tmp.l=0; } - if (!base_eve) + if (!ok) return; - if (mode==1) { /* same normal */ - float angle; - for(eve= em->verts.first; eve; eve= eve->next) { - if (!(eve->f & SELECT) && !eve->h) { - angle= VecAngle2(base_eve->no, eve->no); - if (angle<=thresh) { - eve->f |= SELECT; - selcount++; - } - } - } - } else if (mode==2) { /* face users */ + + if (mode==2) { /* store face users */ EditFace *efa; /* count how many faces each edge uses use tmp->l */ @@ -986,35 +995,63 @@ void vertgroup_select(short mode) efa->v3->tmp.l++; if (efa->v4) efa->v4->tmp.l++; } - - for(eve= em->verts.first; eve; eve= eve->next) { - if ((!(eve->f & SELECT) && !eve->h) && (base_eve->tmp.l==eve->tmp.l)) { - eve->f |= SELECT; - selcount++; - } - } - } else if (mode==3) { /* vertex groups */ - short i,j; /*weight index*/ - if (!base_eve->totweight) - return; - - for(eve= em->verts.first; eve; eve= eve->next) { - if (!(eve->f & SELECT) && !eve->h && eve->totweight) { - /* do the extra check for selection in the following if, so were not - checking verts that may be alredy selected */ - for (i=0; base_eve->totweight >i && !(eve->f & SELECT); i++) { - for (j=0; eve->totweight >j; j++) { - if (base_eve->dw[i].def_nr==eve->dw[j].def_nr) { + } + + + for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) { + if (base_eve->f1) { + + if (mode==1) { /* same normal */ + float angle; + for(eve= em->verts.first; eve; eve= eve->next) { + if (!(eve->f & SELECT) && !eve->h) { + angle= VecAngle2(base_eve->no, eve->no); + if (angle<=thresh) { eve->f |= SELECT; selcount++; - break; } } } + } else if (mode==2) { /* face users */ + for(eve= em->verts.first; eve; eve= eve->next) { + if ( + !(eve->f & SELECT) && + !eve->h && + base_eve->tmp.l==eve->tmp.l + ) { + eve->f |= SELECT; + selcount++; + } + } + } else if (mode==3) { /* vertex groups */ + short i,j; /*weight index*/ + if (!base_eve->totweight) + return; + + for(eve= em->verts.first; eve; eve= eve->next) { + if ( + !(eve->f & SELECT) && + !eve->h && + eve->totweight + ) { + /* do the extra check for selection in the following if, so were not + checking verts that may be alredy selected */ + for (i=0; base_eve->totweight >i && !(eve->f & SELECT); i++) { + for (j=0; eve->totweight >j; j++) { + if (base_eve->dw[i].def_nr==eve->dw[j].def_nr) { + eve->f |= SELECT; + selcount++; + break; + } + } + } + } + } + } } - - } + } /* end basevert loop */ + if (selcount) { EM_select_flush(); /* so that selected verts, go onto select faces */ G.totedgesel+=selcount;