- basic code for fake-polygon support (called FGon in code). Disabled now
authorTon Roosendaal <ton@blender.org>
Fri, 24 Sep 2004 12:40:37 +0000 (12:40 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 24 Sep 2004 12:40:37 +0000 (12:40 +0000)
- 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...

source/blender/blenlib/BLI_editVert.h
source/blender/include/BIF_editmesh.h
source/blender/include/editmesh.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/src/drawobject.c
source/blender/src/editmesh.c
source/blender/src/editmesh_add.c
source/blender/src/editmesh_lib.c
source/blender/src/editmesh_mods.c
source/blender/src/space.c

index 0ff57f8cde7414f58609f488a2b598074385a05a..e47d82043b7687f80a0cdf8217274120942da195 100644 (file)
@@ -66,7 +66,8 @@ typedef struct EditEdge
        short f1, f2;   /* short, f1 is (ab)used in subdiv */
        unsigned char f, h, dir, seam;
        float crease;
-       int fast;               /* only 0 or 1, for editmesh_fastmalloc */
+       short fast;             /* only 0 or 1, for editmesh_fastmalloc */
+       short fgoni;            /* index for fgon, for search */
        HashEdge hash;
 } EditEdge;
 
@@ -80,7 +81,8 @@ typedef struct EditFace
        struct TFace tf;        /* a copy of original tface. */
        unsigned char mat_nr, flag;
        unsigned char f, f1, h, puno;
-       short fast;                     /* only 0 or 1, for editmesh_fastmalloc */
+       unsigned char fast;                     /* only 0 or 1, for editmesh_fastmalloc */
+       unsigned char fgonf;            /* flag for fgon options */
 } EditFace;
 
 typedef struct EditMesh
index fe11e0b684e5616f5ca2e5066d61ca7bc35ba375..632283f9a534ec18ddc68a038a49e7e384a44229 100644 (file)
@@ -43,6 +43,12 @@ struct Mesh;
 struct bDeformGroup;
 struct View3D;
 
+// edge and face flag both
+#define EM_FGON                2
+// face flag
+#define EM_FGON_DRAW   1
+
+
 /* ******************* editmesh.c */
 extern void make_editMesh(void);
 extern void load_editMesh(void);
index bb69b033cb7fd23ce1d87f5b8cbdd41a0fd41b6c..927c8d401568406885416f5ede5e2c302412a14d 100644 (file)
@@ -41,6 +41,7 @@
 #define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
 
 
+
 /* ******************* editmesh.c */
 extern void free_editvert(EditVert *eve);
 extern void free_editedge(EditEdge *eed);
@@ -82,6 +83,7 @@ extern float convex(float *v1, float *v2, float *v3, float *v4);
 
 /* ******************* editmesh_mods.c */
 extern EditEdge *findnearestedge(short *dist);
+extern void make_fgon(void);
 
 /* ******************* editmesh_tools.c */
 
index 426c06366cafe04225f9d6be727dbe62aff4d372..0a186765caee93e394deb9594085802966ff911d 100644 (file)
@@ -80,6 +80,8 @@ typedef struct MSticky {
 /* medge->flag (1=SELECT)*/
 #define ME_EDGEDRAW            2
 #define ME_SEAM         4
+#define ME_FGON                        8
+                                               // reserve 16 for ME_HIDE
 
 /* puno = vertexnormal (mface) */
 #define ME_FLIPV1              1
index bba7864a6cddb90dff2ac3813f22ddf45278ee1a..ddfef9c6cb0719e837f44ad812143d48d8f832e4 100644 (file)
@@ -1153,7 +1153,8 @@ static void draw_vertices(short sel)
                        bglBegin(GL_POINTS);
                        for(efa= em->faces.first; efa; efa= efa->next) {
                                if(efa->h==0) {
-                                       if(sel == (efa->f & SELECT)) {
+                                       if(efa->fgonf==EM_FGON);
+                                       else if(sel == (efa->f & SELECT)) {
                                                bglVertex3fv(efa->cent);
                                        }
                                }
@@ -1183,7 +1184,8 @@ static void draw_vertices(short sel)
                bglBegin(GL_POINTS);
                for(efa= em->faces.first; efa; efa= efa->next) {
                        if(efa->h==0) {
-                               if(sel == (efa->f & SELECT)) {
+                               if(efa->fgonf==EM_FGON);
+                               else if(sel == (efa->f & SELECT)) {
                                        bglVertex3fv(efa->cent);
                                }
                        }
@@ -2521,27 +2523,50 @@ static void drawmeshwire(Object *ob)
                else if(G.scene->selectmode == SCE_SELECT_FACE) {
                        /* draw faces twice, to have selected ones on top */
                        BIF_ThemeColor(TH_WIRE);
+                       glBegin(GL_LINES);
                        for(efa= em->faces.first; efa; efa= efa->next) {
                                if(efa->h==0 && (efa->f & SELECT)==0) { 
-                                       glBegin(GL_LINE_LOOP);
-                                       glVertex3fv(efa->v1->co);
-                                       glVertex3fv(efa->v2->co);
-                                       glVertex3fv(efa->v3->co);
-                                       if(efa->v4) glVertex3fv(efa->v4->co);
-                                       glEnd();
+                                       if(efa->e1->h==0) {
+                                               glVertex3fv(efa->v1->co);
+                                               glVertex3fv(efa->v2->co);
+                                       }
+                                       if(efa->e2->h==0) {
+                                               glVertex3fv(efa->v2->co);
+                                               glVertex3fv(efa->v3->co);
+                                       }
+                                       if(efa->e3->h==0) {
+                                               glVertex3fv(efa->e3->v1->co);
+                                               glVertex3fv(efa->e3->v2->co);
+                                       }
+                                       if(efa->e4 && efa->e4->h==0) {
+                                               glVertex3fv(efa->e4->v1->co);
+                                               glVertex3fv(efa->e4->v2->co);
+                                       }
                                }
                        }
+                       
                        BIF_ThemeColor(TH_EDGE_SELECT);
                        for(efa= em->faces.first; efa; efa= efa->next) {
                                if(efa->h==0 && (efa->f & SELECT)) { 
-                                       glBegin(GL_LINE_LOOP);
-                                       glVertex3fv(efa->v1->co);
-                                       glVertex3fv(efa->v2->co);
-                                       glVertex3fv(efa->v3->co);
-                                       if(efa->v4) glVertex3fv(efa->v4->co);
-                                       glEnd();
+                                       if(efa->e1->h==0) {
+                                               glVertex3fv(efa->v1->co);
+                                               glVertex3fv(efa->v2->co);
+                                       }
+                                       if(efa->e2->h==0) {
+                                               glVertex3fv(efa->v2->co);
+                                               glVertex3fv(efa->v3->co);
+                                       }
+                                       if(efa->e3->h==0) {
+                                               glVertex3fv(efa->e3->v1->co);
+                                               glVertex3fv(efa->e3->v2->co);
+                                       }
+                                       if(efa->e4 && efa->e4->h==0) {
+                                               glVertex3fv(efa->e4->v1->co);
+                                               glVertex3fv(efa->e4->v2->co);
+                                       }
                                }
                        }
+                       glEnd();
                }       
                else if( (G.f & G_DRAWEDGES) || (G.scene->selectmode & SCE_SELECT_EDGE) ) {     
                        /* Use edge highlighting */
index 18f815ff15ec8609417c4cd8d06d0bf604112d0e..cc1f675a4bdd25d61833dbd5987a938c13e6d3d3 100644 (file)
@@ -246,18 +246,20 @@ EditEdge *addedgelist(EditVert *v1, EditVert *v2, EditEdge *example)
        eed= findedgelist(v1, v2);
 
        if(eed==NULL) {
-
+       
                eed= (EditEdge *)callocedge(sizeof(EditEdge), 1);
                eed->v1= v1;
                eed->v2= v2;
                BLI_addtail(&em->edges, eed);
                eed->dir= swap;
                insert_hashedge(eed);
+               
                /* copy edge data:
                   rule is to do this with addedgelist call, before addfacelist */
                if(example) {
                        eed->crease= example->crease;
                        eed->seam = example->seam;
+                       eed->h |= (example->h & EM_FGON);
                }
        }
 
@@ -330,12 +332,21 @@ EditFace *addfacelist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed
        EditEdge *e1, *e2=0, *e3=0, *e4=0;
 
        /* add face to list and do the edges */
-       e1= addedgelist(v1, v2, NULL);
-       e2= addedgelist(v2, v3, NULL);
-       if(v4) e3= addedgelist(v3, v4, NULL); 
-       else e3= addedgelist(v3, v1, NULL);
-       if(v4) e4= addedgelist(v4, v1, NULL);
-
+       if(example) {
+               e1= addedgelist(v1, v2, example->e1);
+               e2= addedgelist(v2, v3, example->e2);
+               if(v4) e3= addedgelist(v3, v4, example->e3); 
+               else e3= addedgelist(v3, v1, example->e3);
+               if(v4) e4= addedgelist(v4, v1, example->e4);
+       }
+       else {
+               e1= addedgelist(v1, v2, NULL);
+               e2= addedgelist(v2, v3, NULL);
+               if(v4) e3= addedgelist(v3, v4, NULL); 
+               else e3= addedgelist(v3, v1, NULL);
+               if(v4) e4= addedgelist(v4, v1, NULL);
+       }
+       
        if(v1==v2 || v2==v3 || v1==v3) return NULL;
        if(e2==0) return NULL;
 
@@ -704,6 +715,8 @@ void make_editMesh()
                                
                                if(medge->flag & ME_SEAM) eed->seam= 1;
                                if(medge->flag & SELECT) eed->f |= SELECT;
+                               if(medge->flag & ME_FGON) eed->h= EM_FGON;      // 2 different defines!
+                               if(medge->flag & ME_HIDE) eed->h |= 1;
                        }
 
                }
@@ -743,6 +756,7 @@ void make_editMesh()
                                        efa->f |= SELECT;
                                        if(me->medge==NULL) EM_select_face(efa, 1);
                                }
+                               if(mface->flag & ME_HIDE) efa->h= 1;
                        }
 
                        if(me->tface) tface++;
@@ -750,15 +764,12 @@ void make_editMesh()
                }
        }
        
-       /* flush hide flags */
-       
-       for(eed= em->edges.first; eed; eed= eed->next) {
-               if(eed->v1->h || eed->v2->h) eed->h= 1;
-               else eed->h= 0;
-       }       
-       for(efa= em->faces.first; efa; efa= efa->next) {
-               if(efa->e1->h || efa->e2->h || efa->e3->h) efa->h= 1;
-               else if(efa->e4 && efa->e4->h) efa->h= 1;
+       /* flush hide flags when no medge */
+       if(me->medge==NULL) {
+               for(eed= em->edges.first; eed; eed= eed->next) {
+                       if(eed->v1->h || eed->v2->h) eed->h |= 1;
+                       else eed->h &= ~1;
+               }       
        }
        
        MEM_freeN(evlist);
@@ -1009,6 +1020,8 @@ void load_editMesh(void)
                        medge->flag= eed->f & SELECT;
                        if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
                        if(eed->seam) medge->flag |= ME_SEAM;
+                       if(eed->h & EM_FGON) medge->flag |= ME_FGON;    // different defines yes
+                       if(eed->h & 1) medge->flag |= ME_HIDE;
                        
                        medge->crease= (char)(255.0*eed->crease);
 
@@ -1030,10 +1043,12 @@ void load_editMesh(void)
                        
                mface->mat_nr= efa->mat_nr;
                mface->puno= efa->puno;
+               
                mface->flag= efa->flag;
                /* bit 0 of flag is already taken for smooth... */
                if(efa->f & 1) mface->flag |= ME_FACE_SEL;
                else mface->flag &= ~ME_FACE_SEL;
+               if(efa->h) mface->flag |= ME_HIDE;
                
                /* mat_nr in vertex */
                if(me->totcol>1) {
index 2186735ecd3d755aaad0ea73974f8f4787feac07..8421228fb2a0d6e523eabcb72cf5dcd4c336a8a0 100644 (file)
@@ -190,7 +190,11 @@ void addedgeface_mesh(void)
                makeDispList(G.obedit);
                return;
        }
-       if(amount<2 || amount>4) {
+       else if(amount > 4) {
+               //make_fgon();
+               return;
+       }
+       else if(amount<2) {
                error("Incorrect number of vertices to make edge/face");
                return;
        }
index 263f860a7b2a9d2cd1d2a7aeacb54aeda4cc9521..3ea520cf57103609f29cba81ec24d4a2986f16bd 100644 (file)
@@ -704,6 +704,8 @@ short extrudeflag_vert(short flag)
                }
                eve= nextve;
        }
+       // since its vertex select mode now, it also deselects higher order
+       EM_selectmode_flush();
 
        return 1;
 }
index bcfa7c303c46f1a4472e8f6d6e96c7f4dd1483f4..7cd35e1421d54f5a82efccc56e3028cdf0310646 100644 (file)
@@ -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;
                }
        }
index aa13f4e939477f05ebf4693d00d171e8aed6bb5f..e3ffb6483f4d3681a0914037ff406fce067400b9 100644 (file)
@@ -637,9 +637,7 @@ void BIF_undo_push(char *str)
 }
 
 void BIF_undo(void)
-{
-       extern void undo_curve_step(int step);  // editcurve.c
-       
+{      
        if(G.obedit) {
                if(G.obedit->type==OB_MESH)
                        undo_editmode_step(1);
@@ -662,8 +660,6 @@ void BIF_undo(void)
 
 void BIF_redo(void)
 {
-       extern void undo_curve_step(int step);  // editcurve.c
-
        if(G.obedit) {
                if(G.obedit->type==OB_MESH)
                        undo_editmode_step(-1);