- 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...
This commit is contained in:
Ton Roosendaal
2004-09-24 12:40:37 +00:00
parent ce12a0173c
commit f59503682d
10 changed files with 322 additions and 50 deletions

View 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

View 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);

View 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 */

View 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

View 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 */

View 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) {

View 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;
}

View 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;
}

View 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;
}
}

View 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);