diff options
author | Ton Roosendaal <ton@blender.org> | 2004-09-24 16:40:37 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2004-09-24 16:40:37 +0400 |
commit | f59503682d1afdb29079dccd642b4191ff9ecc1e (patch) | |
tree | fed8a2a9682a6a1892d03528d9bd2b7b27c20e36 /source/blender/src/editmesh_mods.c | |
parent | ce12a0173c25fdb9cbe34aee194bdf62780230bc (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.c | 242 |
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; } } |