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:
authorTon Roosendaal <ton@blender.org>2004-09-24 16:40:37 +0400
committerTon Roosendaal <ton@blender.org>2004-09-24 16:40:37 +0400
commitf59503682d1afdb29079dccd642b4191ff9ecc1e (patch)
treefed8a2a9682a6a1892d03528d9bd2b7b27c20e36 /source/blender/src/editmesh_mods.c
parentce12a0173c25fdb9cbe34aee194bdf62780230bc (diff)
- basic code for fake-polygon support (called FGon in code). Disabled now
- hide flags now save correctly in mesh, to restore after going in/out editmode - after an extrude, faces/edges could have wrong select flags (only in vertex select mode) - new rule for addfacelist(); this now copies edges too, if an example is provided. That prevents a lot of awkward code, still testing if it goes as desired though...
Diffstat (limited to 'source/blender/src/editmesh_mods.c')
-rw-r--r--source/blender/src/editmesh_mods.c242
1 files changed, 230 insertions, 12 deletions
diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c
index bcfa7c303c4..7cd35e1421d 100644
--- a/source/blender/src/editmesh_mods.c
+++ b/source/blender/src/editmesh_mods.c
@@ -396,6 +396,33 @@ static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa)
return (*eve || *eed || *efa);
}
+void EM_select_face_fgon(EditFace *efa, int val)
+{
+ EditMesh *em = G.editMesh;
+ short index=0;
+
+ if(efa->fgonf==0) EM_select_face(efa, val);
+ else {
+ if(efa->e1->fgoni) index= efa->e1->fgoni;
+ if(efa->e2->fgoni) index= efa->e2->fgoni;
+ if(efa->e3->fgoni) index= efa->e3->fgoni;
+ if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni;
+
+ if(index==0) printf("wrong fgon select\n");
+
+ // select all ngon faces with index
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->fgonf) {
+ if(efa->e1->fgoni==index || efa->e2->fgoni==index ||
+ efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) {
+ EM_select_face(efa, val);
+ }
+ }
+ }
+ }
+}
+
+
/* here actual select happens */
void mouse_mesh(void)
{
@@ -409,10 +436,10 @@ void mouse_mesh(void)
if(efa) {
if( (efa->f & SELECT)==0 ) {
- EM_select_face(efa, 1);
+ EM_select_face_fgon(efa, 1);
}
else if(G.qual & LR_SHIFTKEY) {
- EM_select_face(efa, 0);
+ EM_select_face_fgon(efa, 0);
}
}
else if(eed) {
@@ -566,6 +593,204 @@ void selectconnected_mesh(int qual)
}
+/* results in:
+ - faces having ->fgonf flag set (also for draw)
+ - edges having ->fgoni index set (for select)
+*/
+
+static float editface_area(EditFace *efa)
+{
+ if(efa->v4) return AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+ else return AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co);
+}
+
+void fgon_flags()
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa, *efan, *efamax;
+ EditEdge *eed;
+ ListBase listb={NULL, NULL};
+ float size, maxsize;
+ short done, curindex= 1;
+
+ // for each face with fgon edge AND not fgon flag set
+ for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0; // index
+ for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0; // flag
+
+ // for speed & simplicity, put fgon face candidates in new listbase
+ efa= em->faces.first;
+ while(efa) {
+ efan= efa->next;
+ if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) ||
+ (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) {
+ BLI_remlink(&em->faces, efa);
+ BLI_addtail(&listb, efa);
+ }
+ efa= efan;
+ }
+
+ // find an undone face with fgon edge
+ for(efa= listb.first; efa; efa= efa->next) {
+ if(efa->fgonf==0) {
+
+ // init this face
+ efa->fgonf= EM_FGON;
+ if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex;
+ if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex;
+ if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex;
+ if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex;
+
+ // we search for largest face, to give facedot drawing rights
+ maxsize= editface_area(efa);
+ efamax= efa;
+
+ // now flush curendex over edges and set faceflags
+ done= 1;
+ while(done==1) {
+ done= 0;
+
+ for(efan= listb.first; efan; efan= efan->next) {
+ if(efan->fgonf==0) {
+ // if one if its edges has index set, do other too
+ if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) ||
+ (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) {
+
+ efan->fgonf= EM_FGON;
+ if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex;
+ if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex;
+ if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex;
+ if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex;
+
+ size= editface_area(efan);
+ if(size>maxsize) {
+ efamax= efan;
+ maxsize= size;
+ }
+ done= 1;
+ }
+ }
+ }
+ }
+
+ efamax->fgonf |= EM_FGON_DRAW;
+ curindex++;
+
+ }
+ }
+
+ // put fgon face candidates back in listbase
+ efa= listb.first;
+ while(efa) {
+ efan= efa->next;
+ BLI_remlink(&listb, efa);
+ BLI_addtail(&em->faces, efa);
+ efa= efan;
+ }
+}
+
+
+/* selected faces get hidden edges */
+void make_fgon(void)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ EditEdge *eed;
+ EditVert *eve;
+ float *nor=NULL, dot; // reference
+ int done=0;
+
+ /* tagging edges. rule is:
+ - edge used by exactly 2 selected faces
+ - no vertices allowed with only tagged edges (return)
+ - face normals should not differ too much
+
+ */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0; // amount of selected
+ eed->f2= 0; // amount of unselected
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ if(nor==NULL) nor= efa->n;
+ if(efa->e1->f1 < 3) efa->e1->f1++;
+ if(efa->e2->f1 < 3) efa->e2->f1++;
+ if(efa->e3->f1 < 3) efa->e3->f1++;
+ if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++;
+ }
+ else {
+ if(efa->e1->f2 < 3) efa->e1->f2++;
+ if(efa->e2->f2 < 3) efa->e2->f2++;
+ if(efa->e3->f2 < 3) efa->e3->f2++;
+ if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++;
+ }
+ }
+ // now eed->f1 becomes tagged edge
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1==2 && eed->f2==0) eed->f1= 1;
+ else eed->f1= 0;
+ }
+
+ // no vertices allowed with only tagged edges
+ for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1) {
+ eed->v1->f1 |= 1;
+ eed->v2->f1 |= 1;
+ }
+ else {
+ eed->v1->f1 |= 2;
+ eed->v2->f1 |= 2;
+ }
+ }
+ for(eve= em->verts.first; eve; eve= eve->next) {
+ if(eve->f1==1) break;
+ }
+ if(eve) {
+ error("Cannot make polygon with interior vertices");
+ return;
+ }
+
+ // check co-planar
+ if(nor==NULL) {
+ error("No faces selected to make FGon");
+ return;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->f & SELECT) {
+ dot= nor[0]*efa->n[0]+nor[1]*efa->n[1]+nor[2]*efa->n[2];
+ if(dot<0.9 && dot > -0.9) break;
+ }
+ }
+ if(efa) {
+ error("Not a set of co-planar faces to make FGon");
+ return;
+ }
+
+ // and there we go
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f1) {
+ eed->h |= EM_FGON;
+ done= 1;
+ }
+ }
+
+ if(done==0) {
+ error("Didn't find FGon to create");
+ }
+ else {
+ Mesh *me= G.obedit->data;
+ // signal to save edges with ngon flags
+ if(!me->medge)
+ me->medge= MEM_callocN(sizeof(MEdge), "fake mesh edge");
+
+ fgon_flags(); // redo flags and indices for fgons
+
+ allqueue(REDRAWVIEW3D, 0);
+ makeDispList(G.obedit);
+ BIF_undo_push("Make FGon");
+ }
+}
/* swap is 0 or 1, if 1 it hides not selected */
@@ -591,7 +816,7 @@ void hide_mesh(int swap)
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->v1->h || eed->v2->h) {
- eed->h= 1;
+ eed->h |= 1;
eed->f &= ~SELECT;
}
else eed->h= 0;
@@ -609,9 +834,7 @@ void hide_mesh(int swap)
for(eed= em->edges.first; eed; eed= eed->next) {
if((eed->f & SELECT)!=swap) {
- eed->h= 1;
- eed->v1->h= 1;
- eed->v2->h= 1;
+ eed->h |= 1;
EM_select_edge(eed, 0);
}
}
@@ -629,11 +852,6 @@ void hide_mesh(int swap)
for(efa= em->faces.first; efa; efa= efa->next) {
if((efa->f & SELECT)!=swap) {
efa->h= 1;
- efa->e1->h= efa->e2->h= efa->e3->h= 1;
- if(efa->e4) efa->e4->h= 1;
- efa->v1->h= efa->v2->h= efa->v3->h= 1;
- if(efa->v4) efa->v4->h= 1;
-
EM_select_face(efa, 0);
}
}
@@ -663,7 +881,7 @@ void reveal_mesh(void)
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h) {
- eed->h= 0;
+ eed->h &= ~1;
eed->f |= SELECT;
}
}