Two nice workflow improvements;

- Zbuffer clipped selection
Based on same algos as for drawing (blender polygon offset) vertices, edges
and faces now are clipped for draw and selection when Zbuffer is used.
Note that it works for endpoint vertices of edges, and for facecenters.
Also works for border and circle-select

- Optimal draw subsurfs
This now draws optimal with faces and edges selected/unselected, hiding the
original 'cage' (mesh) completely.
TODO: edge select, which still uses original (invisible) edge.

http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
This commit is contained in:
Ton Roosendaal 2004-09-25 13:42:31 +00:00
parent cfe9a95755
commit 6f074f6f46
16 changed files with 408 additions and 207 deletions

@ -61,6 +61,8 @@ struct Bone;
struct Mesh;
struct TFace;
struct EditMesh;
struct EditEdge;
struct EditFace;
typedef struct DispListMesh DispListMesh;
struct DispListMesh {
@ -70,6 +72,8 @@ struct DispListMesh {
struct MCol *mcol;
struct MFace *mface;
struct TFace *tface;
struct EditEdge **editedge; // added for subsurf, drawobject.c
struct EditFace **editface; // added for subsurf, drawobject.c
int flag;
};

@ -211,11 +211,13 @@ DispListMesh *displistmesh_from_mesh(Mesh *me, float *extverts)
void displistmesh_free(DispListMesh *dlm)
{
// also check on mvert and mface, can be NULL after decimator (ton)
if( dlm->mvert) MEM_freeN(dlm->mvert);
if( dlm->medge) MEM_freeN(dlm->medge);
if (dlm->mvert) MEM_freeN(dlm->mvert);
if (dlm->medge) MEM_freeN(dlm->medge);
if (dlm->mface) MEM_freeN(dlm->mface);
if (dlm->mcol) MEM_freeN(dlm->mcol);
if (dlm->tface) MEM_freeN(dlm->tface);
if (dlm->editedge) MEM_freeN(dlm->editedge);
if (dlm->editface) MEM_freeN(dlm->editface);
MEM_freeN(dlm);
}

@ -187,6 +187,7 @@ struct _HyperEdge {
HyperVert *ep;
int flag; // added for drawing optimal
float sharp; // sharpness weight
EditEdge *ee; // for selection state
LinkNode *faces;
};
@ -270,7 +271,8 @@ static HyperVert *hypermesh_add_vert(HyperMesh *hme, float *co, float *orig) {
return hv;
}
static HyperEdge *hypermesh_add_edge(HyperMesh *hme, HyperVert *v1, HyperVert *v2, int flag, float sharp) {
static HyperEdge *hypermesh_add_edge(HyperMesh *hme,
HyperVert *v1, HyperVert *v2, int flag, float sharp, EditEdge *ee) {
HyperEdge *he= BLI_memarena_alloc(hme->arena, sizeof(*he));
BLI_linklist_prepend_arena(&v1->edges, he, hme->arena);
@ -282,6 +284,7 @@ static HyperEdge *hypermesh_add_edge(HyperMesh *hme, HyperVert *v1, HyperVert *v
he->faces= NULL;
he->sharp = sharp;
he->flag= flag;
he->ee= ee;
he->next= hme->edges;
hme->edges= he;
@ -308,7 +311,7 @@ static HyperFace *hypermesh_add_face(HyperMesh *hme, HyperVert **verts, int nver
HyperEdge *e= hypervert_find_edge(v, last);
if (!e)
e= hypermesh_add_edge(hme, v, last, flag, 0);
e= hypermesh_add_edge(hme, v, last, flag, 0, NULL);
f->verts[j]= v;
f->edges[j]= e;
@ -369,7 +372,7 @@ static HyperMesh *hypermesh_from_mesh(Mesh *me, float *extverts, int subdivLevel
if(med->flag & ME_SEAM) flag |= HE_SEAM;
hypermesh_add_edge(hme, vert_tbl[med->v1], vert_tbl[med->v2], flag,
creasefac*((float)med->crease) );
creasefac*((float)med->crease), NULL);
}
}
@ -410,7 +413,7 @@ static HyperMesh *hypermesh_from_mesh(Mesh *me, float *extverts, int subdivLevel
*((unsigned int*) f->vcol[j])= *((unsigned int*) &mcol[j]);
}
} else if(medge==NULL) {
hypermesh_add_edge(hme, vert_tbl[mf->v1], vert_tbl[mf->v2], DR_OPTIM, 0.0);
hypermesh_add_edge(hme, vert_tbl[mf->v1], vert_tbl[mf->v2], DR_OPTIM, 0.0, NULL);
}
}
@ -436,7 +439,7 @@ static HyperMesh *hypermesh_from_editmesh(EditMesh *em, int subdivLevels) {
* then restore real prev links later.
*/
for (ee= em->edges.first; ee; ee= ee->next) {
if(ee->v1->h==0 && ee->v2->h==0) {
if(ee->h==0) {
if(ee->v1->f1) {
ee->v1->prev= (EditVert*) hypermesh_add_vert(hme, ee->v1->co, ee->v1->co);
ee->v1->f1= 0;
@ -448,14 +451,13 @@ static HyperMesh *hypermesh_from_editmesh(EditMesh *em, int subdivLevels) {
flag= DR_OPTIM;
if(ee->seam) flag |= HE_SEAM;
hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev, flag,
creasefac*ee->crease);
creasefac*ee->crease, ee);
}
}
for (ef= em->faces.first; ef; ef= ef->next) {
if(ef->v1->h || ef->v2->h || ef->v3->h);
else if(ef->v4 && ef->v4->h);
else {
if(ef->h==0) {
int nverts= ef->v4?4:3;
HyperVert *verts[4];
HyperFace *f;
@ -685,8 +687,8 @@ static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) {
}
for (e= me->edges; e; e= e->next) {
hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag, e->sharp>1.0?e->sharp-1.0:0.0);
hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag, e->sharp>1.0?e->sharp-1.0:0.0);
hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag, e->sharp>1.0?e->sharp-1.0:0.0, e->ee);
hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag, e->sharp>1.0?e->sharp-1.0:0.0, e->ee);
}
for (f= me->faces; f; f= f->next) {
@ -791,8 +793,8 @@ static void hypermesh_simple_subdivide(HyperMesh *me, HyperMesh *nme) {
}
for (e= me->edges; e; e= e->next) { /* Add original edges */
hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag, 0.0);
hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag, 0.0);
hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag, 0.0, e->ee);
hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag, 0.0, e->ee);
}
for (f= me->faces; f; f= f->next) {
@ -949,7 +951,11 @@ static DispListMesh *hypermesh_to_displistmesh(HyperMesh *hme, short flag) {
dlm->mvert= MEM_callocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert");
dlm->medge= MEM_callocN(dlm->totedge*sizeof(*dlm->medge), "dlm->medge");
dlm->mface= MEM_mallocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface");
/* these two blocks for live update of selection in editmode */
if (hme->orig_me==NULL) {
dlm->editedge= MEM_callocN(dlm->totedge*sizeof(EditEdge *), "dlm->editface");
dlm->editface= MEM_mallocN(dlm->totface*sizeof(EditFace *), "dlm->editedge");
}
if (hme->orig_me) {
dlm->flag= hme->orig_me->flag;
} else {
@ -969,9 +975,11 @@ static DispListMesh *hypermesh_to_displistmesh(HyperMesh *hme, short flag) {
/* we use by default edges for displistmesh now */
med= dlm->medge;
for (e= hme->edges; e; e= e->next, med++) {
for (i=0, e= hme->edges; e; e= e->next, med++, i++) {
med->v1= (int) e->v[0]->nmv;
med->v2= (int) e->v[1]->nmv;
if (hme->orig_me==NULL) dlm->editedge[i]= e->ee;
if(e->flag & DR_OPTIM) med->flag |= ME_EDGEDRAW;
if(e->flag & HE_SEAM) med->flag |= ME_SEAM;
@ -1026,6 +1034,9 @@ static DispListMesh *hypermesh_to_displistmesh(HyperMesh *hme, short flag) {
mf->mat_nr= origef->mat_nr;
mf->flag= origef->flag;
mf->puno= 0;
// for subsurf draw in editmode
dlm->editface[i]= origef;
}
/* although not used by 3d display, still needed for wire-render */

@ -91,6 +91,7 @@ extern void vertexnormals(int testflip);
/* ******************* editmesh_mods.c */
extern void EM_select_face_fgon(struct EditFace *efa, int sel);
extern int EM_zbuffer_visible(float *co, short xs, short ys);
extern void vertexnoise(void);
extern void vertexsmooth(void);

@ -193,6 +193,8 @@ void bglEnd(void);
void bglVertex3fv(float *vec);
void bglVertex2fv(float *vec);
/* own working polygon offset */
void bglPolygonOffset(float dist);
#endif /* BIF_GLUTIL_H */

@ -122,6 +122,7 @@ typedef struct View3D {
#define V3D_WEIGHTPAINT 512
#define V3D_ALIGN 1024
#define V3D_SELECT_OUTLINE 2048
#define V3D_ZBUF_SELECT 4096
/* View3D->around */
#define V3D_CENTRE 0

@ -499,7 +499,6 @@ void draw_tfaces3D(Object *ob, Mesh *me)
float *v1, *v2, *v3, *v4;
float *av1= NULL, *av2= NULL, *av3= NULL, *av4= NULL, *extverts= NULL;
int a, activeFaceInSelection= 0;
extern void bPolygonOffset(short val);
if(me==0 || me->tface==0) return;
@ -508,7 +507,7 @@ void draw_tfaces3D(Object *ob, Mesh *me)
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
bPolygonOffset(1);
bglPolygonOffset(G.vd->dist);
/* Draw (Hidden) Edges */
if(G.f & G_DRAWEDGES || G.f & G_HIDDENEDGES){
@ -632,7 +631,7 @@ void draw_tfaces3D(Object *ob, Mesh *me)
/* Draw Stippled Outline for selected faces */
mface= me->mface;
tface= me->tface;
bPolygonOffset(1);
bglPolygonOffset(G.vd->dist);
for(a=me->totface; a>0; a--, mface++, tface++) {
if(mface->v3==0) continue;
if(tface->flag & TF_HIDE) continue;
@ -705,10 +704,7 @@ void draw_tfaces3D(Object *ob, Mesh *me)
setlinestyle(0);
}
/* We added 2 offsets, so go back 2, and disable */
bPolygonOffset(-1);
bPolygonOffset(-1);
bPolygonOffset(0);
bglPolygonOffset(0.0); // resets correctly now, even after calling accumulated offsets
}
static int set_gl_light(Object *ob)

@ -1115,6 +1115,7 @@ static void draw_vertices(short sel)
float size, fsize;
char col[3], fcol[3];
/* if not V3D_ZBUF_SELECT: */
/* draws in zbuffer mode twice, to show invisible vertices transparent */
size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
@ -1129,52 +1130,86 @@ static void draw_vertices(short sel)
}
if(G.zbuf) {
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
glPointSize(size>2.1?size/2.0: size);
glColor4ub(col[0], col[1], col[2], 100);
if(G.vd->flag & V3D_ZBUF_SELECT);
else {
glDisable(GL_DEPTH_TEST);
bglBegin(GL_POINTS);
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
glPointSize(size>2.1?size/2.0: size);
glColor4ub(col[0], col[1], col[2], 100);
bglBegin(GL_POINTS);
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co);
}
bglEnd();
}
bglEnd();
}
if(G.scene->selectmode & SCE_SELECT_FACE) {
glPointSize(fsize>2.1?fsize/2.0: fsize);
glColor4ub(fcol[0], fcol[1], fcol[2], 100);
bglBegin(GL_POINTS);
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0) {
if(efa->fgonf==EM_FGON);
else if(sel == (efa->f & SELECT)) {
bglVertex3fv(efa->cent);
if(G.scene->selectmode & SCE_SELECT_FACE) {
glPointSize(fsize>2.1?fsize/2.0: fsize);
glColor4ub(fcol[0], fcol[1], fcol[2], 100);
bglBegin(GL_POINTS);
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0) {
if(efa->fgonf==EM_FGON);
else if(sel == (efa->f & SELECT)) {
bglVertex3fv(efa->cent);
}
}
}
bglEnd();
}
bglEnd();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
if(0) {// test
float mat[4][4], persmat[4][4], vec4[4];
float zval;
glFinish(); // maybe for pending polygons
// remake because of polygon offs
glMatrixMode(GL_PROJECTION);
glGetFloatv(GL_PROJECTION_MATRIX, (float *)mat);
glMatrixMode(GL_MODELVIEW);
Mat4MulMat4(persmat, G.vd->viewmat, mat);
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0 && (eve->f & SELECT) ) {
VECCOPY(vec4, eve->co);
vec4[3]= 1.0;
Mat4MulVec4fl(persmat, vec4);
vec4[2]/= vec4[3];
vec4[2]= 0.5 + vec4[2]/2;
// test; read 9 pixels
glReadPixels(curarea->winrct.xmin+eve->xs, curarea->winrct.ymin+eve->ys, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &zval);
//printf("my proj %f zbuf %f mydiff %f\n", vec4[2], zval, vec4[2]-zval);
if( vec4[2]-zval > 0.0) eve->xs= 3200;
}
}
}
glPointSize(size);
glColor3ub(col[0], col[1], col[2]);
bglBegin(GL_POINTS);
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->xs!=3200)
if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co);
}
bglEnd();
}
if(G.scene->selectmode & SCE_SELECT_FACE) {
@ -2444,6 +2479,26 @@ static void draw_static_particle_system(Object *ob, PartEff *paf)
}
static void glVertex_efa_edges(EditFace *efa)
{
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);
}
}
static void drawmeshwire(Object *ob)
{
EditMesh *em = G.editMesh;
@ -2461,10 +2516,13 @@ static void drawmeshwire(Object *ob)
me= get_mesh(ob);
if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
DispList *dl= find_displist(&me->disp, DL_MESH);
DispListMesh *dlm= NULL;
if(dl) dlm= dl->mesh;
if( (me->flag & ME_OPT_EDGES) && (me->flag & ME_SUBSURF) && me->subdiv) handles= 1;
if(handles==0 && (G.f & (G_FACESELECT+G_DRAWFACES))) { /* transp faces */
if( (G.f & (G_FACESELECT+G_DRAWFACES))) { /* transp faces */
char col1[4], col2[4];
BIF_GetThemeColor4ubv(TH_FACE, col1);
@ -2474,95 +2532,102 @@ static void drawmeshwire(Object *ob)
glEnable(GL_BLEND);
glDepthMask(0); // disable write in zbuffer, needed for nice transp
efa= em->faces.first;
while(efa) {
if(efa->h==0) {
if(efa->f & SELECT) glColor4ub(col2[0], col2[1], col2[2], col2[3]);
else glColor4ub(col1[0], col1[1], col1[2], col1[3]);
glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
glVertex3fv(efa->v1->co);
glVertex3fv(efa->v2->co);
glVertex3fv(efa->v3->co);
if(efa->v4) glVertex3fv(efa->v4->co);
glEnd();
if(dlm && handles) {
for(a=0, mface= dlm->mface; a<dlm->totface; a++, mface++) {
if(mface->v3) {
efa= dlm->editface[a];
if(efa->f & SELECT) glColor4ub(col2[0], col2[1], col2[2], col2[3]);
else glColor4ub(col1[0], col1[1], col1[2], col1[3]);
glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
glVertex3fv(dlm->mvert[mface->v1].co);
glVertex3fv(dlm->mvert[mface->v2].co);
glVertex3fv(dlm->mvert[mface->v3].co);
if (mface->v4) glVertex3fv(dlm->mvert[mface->v4].co);
glEnd();
}
}
efa= efa->next;
}
else {
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0) {
if(efa->f & SELECT) glColor4ub(col2[0], col2[1], col2[2], col2[3]);
else glColor4ub(col1[0], col1[1], col1[2], col1[3]);
glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
glVertex3fv(efa->v1->co);
glVertex3fv(efa->v2->co);
glVertex3fv(efa->v3->co);
if(efa->v4) glVertex3fv(efa->v4->co);
glEnd();
}
}
}
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
}
// in editmode it now draws the greyed out part, or optimized
if(mesh_uses_displist(me)) {
/* dont draw the subsurf when solid... then this is a 'drawextra' */
if(handles==0 && ob->dt>OB_WIRE && G.vd->drawtype>OB_WIRE);
else {
if(handles) BIF_ThemeColor(TH_WIRE);
else BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
drawDispListwire(&me->disp);
/* don't draw in edge/face mode */
if(handles && (G.scene->selectmode & SCE_SELECT_VERTEX)==0);
else {
if(handles) BIF_ThemeColor(TH_WIRE);
else BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
drawDispListwire(&me->disp);
}
}
}
if(handles); // then no edges draw
else if(G.f & G_DRAWCREASES) { /* Use crease edge Highlighting */
eed= em->edges.first;
if(G.f & G_DRAWCREASES) { /* Use crease edge Highlighting */
glBegin(GL_LINES);
while(eed) {
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
BIF_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
glVertex3fv(eed->v1->co);
glVertex3fv(eed->v2->co);
}
eed= eed->next;
}
glEnd();
}
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) {
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);
if(dlm && handles) {
MEdge *medge= dlm->medge;
MVert *mvert= dlm->mvert;
for (a=0; a<dlm->totedge; a++, medge++) {
if(medge->flag & ME_EDGEDRAW) {
eed= dlm->editedge[a];
if(eed) {
if(eed->f & SELECT) BIF_ThemeColor(TH_EDGE_SELECT);
else BIF_ThemeColor(TH_WIRE);
glVertex3fv(mvert[medge->v1].co);
glVertex3fv(mvert[medge->v2].co);
}
}
}
}
BIF_ThemeColor(TH_EDGE_SELECT);
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0 && (efa->f & SELECT)) {
if(efa->e1->h==0) {
glVertex3fv(efa->v1->co);
glVertex3fv(efa->v2->co);
else {
/* draw faces twice, to have selected ones on top */
BIF_ThemeColor(TH_WIRE);
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0 && (efa->f & SELECT)==0) {
glVertex_efa_edges(efa);
}
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)) {
glVertex_efa_edges(efa);
}
}
}
@ -2575,54 +2640,65 @@ static void drawmeshwire(Object *ob)
BIF_GetThemeColor3ubv(TH_EDGE_SELECT, colhi);
BIF_GetThemeColor3ubv(TH_WIRE, col);
eed= em->edges.first;
/* (bleeding edges) to illustrate selection is defined on vertex basis */
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
/* but cannot do with subdivided edges... */
if(dlm==NULL && (G.scene->selectmode & SCE_SELECT_VERTEX)) {
glShadeModel(GL_SMOOTH);
glBegin(GL_LINES);
while(eed) {
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
if(eed->v1->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
else glColor3ub(col[0], col[1], col[2]);
glVertex3fv(eed->v1->co);
if(eed->v2->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
else glColor3ub(col[0], col[1], col[2]);
glVertex3fv(eed->v2->co);
}
eed= eed->next;
}
glEnd();
glShadeModel(GL_FLAT);
}
else {
glBegin(GL_LINES);
while(eed) {
if(eed->h==0) {
if(eed->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
else glColor3ub(col[0], col[1], col[2]);
if(dlm && handles) {
MEdge *medge= dlm->medge;
MVert *mvert= dlm->mvert;
glVertex3fv(eed->v1->co);
glVertex3fv(eed->v2->co);
for (a=0; a<dlm->totedge; a++, medge++) {
if(medge->flag & ME_EDGEDRAW) {
eed= dlm->editedge[a];
if(eed && eed->h==0) {
if(eed->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
else glColor3ub(col[0], col[1], col[2]);
glVertex3fv(mvert[medge->v1].co);
glVertex3fv(mvert[medge->v2].co);
}
}
}
eed= eed->next;
}
else {
glBegin(GL_LINES);
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
if(eed->f & SELECT) glColor3ub(colhi[0], colhi[1], colhi[2]);
else glColor3ub(col[0], col[1], col[2]);
glVertex3fv(eed->v1->co);
glVertex3fv(eed->v2->co);
}
}
}
glEnd();
}
glEnd();
glShadeModel(GL_FLAT);
}
else {
else if(handles==0) {
BIF_ThemeColor(TH_WIRE);
eed= em->edges.first;
glBegin(GL_LINES);
while(eed) {
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
glVertex3fv(eed->v1->co);
glVertex3fv(eed->v2->co);
}
eed= eed->next;
}
glEnd();
}
@ -2632,13 +2708,11 @@ static void drawmeshwire(Object *ob)
glLineWidth(2);
glBegin(GL_LINES);
eed= em->edges.first;
while(eed) {
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0 && eed->seam) {
glVertex3fv(eed->v1->co);
glVertex3fv(eed->v2->co);
}
eed= eed->next;
}
glEnd();
@ -3708,38 +3782,6 @@ static int ob_from_decimator(Object *ob)
return 0;
}
/* true or false */
void bPolygonOffset(short val)
{
static float winmat[16], ofs=0.0;
if(val) {
// glEnable(GL_POLYGON_OFFSET_FILL);
// glPolygonOffset(-1.0, -1.0);
/* hack below is to mimic polygon offset */
glMatrixMode(GL_PROJECTION);
glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat);
if(winmat[15]>0.5) ofs= 0.00005*G.vd->dist; // ortho tweaking
else ofs= 0.001;
if(val== -1) ofs= -ofs;
winmat[14]-= ofs;
glLoadMatrixf(winmat);
glMatrixMode(GL_MODELVIEW);
}
else {
glMatrixMode(GL_PROJECTION);
winmat[14]+= ofs;
glLoadMatrixf(winmat);
glMatrixMode(GL_MODELVIEW);
}
}
/* draws wire outline */
static void drawSolidSelect(Object *ob, ListBase *lb)
{
@ -3789,14 +3831,14 @@ static void drawWireExtra(Object *ob, ListBase *lb)
}
else BIF_ThemeColor(TH_WIRE);
bPolygonOffset(1);
bglPolygonOffset(1);
glDepthMask(0); // disable write in zbuffer, selected edge wires show better
if(ob->type==OB_MESH) drawmeshwire(ob);
else drawDispListwire(lb);
glDepthMask(1);
bPolygonOffset(0);
bglPolygonOffset(0);
}
static void draw_extra_wire(Object *ob)

@ -270,6 +270,8 @@ void init_gl_stuff(void)
glPixelTransferi(GL_BLUE_BIAS, 0);
glPixelTransferi(GL_ALPHA_SCALE, 1);
glPixelTransferi(GL_ALPHA_BIAS, 0);
glPixelTransferi(GL_DEPTH_BIAS, 0);
glPixelTransferi(GL_DEPTH_SCALE, 1);
a= 0;
for(x=0; x<32; x++) {

@ -749,7 +749,7 @@ void make_editMesh()
}
efa->mat_nr= mface->mat_nr;
efa->flag= mface->flag;
efa->flag= mface->flag & ~ME_HIDE;
/* select face flag, if no edges we flush down */
if(mface->flag & ME_FACE_SEL) {
@ -757,6 +757,7 @@ void make_editMesh()
if(me->medge==NULL) EM_select_face(efa, 1);
}
if(mface->flag & ME_HIDE) efa->h= 1;
}
if(me->tface) tface++;

@ -99,6 +99,47 @@ editmesh_mods.c, UI level access, no geometry changes
/* ****************************** SELECTION ROUTINES **************** */
/* return 1 if visible */
int EM_zbuffer_visible(float *co, short xs, short ys)
{
static float persmat[4][4];
float zval, vec4[4];
if(G.vd->drawtype<OB_SOLID && (G.vd->flag & V3D_ZBUF_SELECT)==0) return 1;
if(co==NULL) { // init
float pmat[4][4], vmat[4][4];
areawinset(curarea->win);
persp(PERSP_VIEW);
mymultmatrix(G.obedit->obmat);
bglPolygonOffset(G.vd->dist); // sets proj matrix
glGetFloatv(GL_PROJECTION_MATRIX, (float *)pmat);
glGetFloatv(GL_MODELVIEW_MATRIX, (float *)vmat);
Mat4MulMat4(persmat, vmat, pmat);
bglPolygonOffset(0.0); // restores proj matrix
myloadmatrix(G.vd->viewmat);
return 0;
}
// clip on window edge */
if(xs<0 || ys<0 || xs>=curarea->winx || ys>= curarea->winy) return 0;
VECCOPY(vec4, co);
vec4[3]= 1.0;
Mat4MulVec4fl(persmat, vec4);
vec4[2]/= vec4[3];
vec4[2]= 0.5 + vec4[2]/2;
glReadPixels(curarea->winrct.xmin+xs, curarea->winrct.ymin+ys, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &zval);
//printf("my proj %f zbuf %f mydiff %f\n", vec4[2], zval, vec4[2]-zval);
if( vec4[2] > zval) return 0;
return 1;
}
static EditVert *findnearestvert(short *dist, short sel)
{
@ -112,6 +153,7 @@ static EditVert *findnearestvert(short *dist, short sel)
/* do projection */
calc_meshverts_ext(); /* drawobject.c */
EM_zbuffer_visible(NULL, 0, 0); /* NULL = init */
/* we count from acto->next to last, and from first to acto */
/* does acto exist? */
@ -130,9 +172,11 @@ static EditVert *findnearestvert(short *dist, short sel)
temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
if( (eve->f & 1)==sel ) temp+=5;
if(temp< *dist) {
act= eve;
*dist= temp;
if(*dist<4) break;
if(EM_zbuffer_visible(eve->co, eve->xs, eve->ys)) {
act= eve;
*dist= temp;
if(*dist<4) break;
}
}
}
eve= eve->next;
@ -145,9 +189,11 @@ static EditVert *findnearestvert(short *dist, short sel)
temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
if( (eve->f & 1)==sel ) temp+=5;
if(temp< *dist) {
act= eve;
if(temp<4) break;
*dist= temp;
if(EM_zbuffer_visible(eve->co, eve->xs, eve->ys)) {
act= eve;
if(temp<4) break;
*dist= temp;
}
}
if(eve== acto) break;
}
@ -177,6 +223,8 @@ EditEdge *findnearestedge(short *dist)
}
calc_meshverts_ext_f2(); /*sets (eve->f & 2) for vertices that aren't visible*/
EM_zbuffer_visible(NULL, 0, 0); /* NULL = init */
getmouseco_areawin(mval);
closest=NULL;
@ -196,8 +244,12 @@ EditEdge *findnearestedge(short *dist)
distance= (short)PdistVL2Dfl(mval2, v1, v2);
if(distance < *dist) {
*dist= distance;
closest= eed;
if(EM_zbuffer_visible(eed->v1->co, eed->v1->xs, eed->v1->ys)) {
if(EM_zbuffer_visible(eed->v2->co, eed->v2->xs, eed->v2->ys)) {
*dist= distance;
closest= eed;
}
}
}
}
eed= eed->next;
@ -224,6 +276,7 @@ static EditFace *findnearestface(short *dist)
/* do projection */
calc_mesh_facedots_ext();
EM_zbuffer_visible(NULL, 0, 0); /* NULL = init */
/* we count from acto->next to last, and from first to acto */
/* does acto exist? */
@ -241,8 +294,10 @@ static EditFace *findnearestface(short *dist)
if(efa->h==0 && efa->fgonf!=EM_FGON) {
temp= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
if(temp< *dist) {
act= efa;
*dist= temp;
if(EM_zbuffer_visible(efa->cent, efa->xs, efa->ys)) {
act= efa;
*dist= temp;
}
}
}
efa= efa->next;
@ -254,8 +309,10 @@ static EditFace *findnearestface(short *dist)
if(efa->h==0 && efa->fgonf!=EM_FGON) {
temp= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
if(temp< *dist) {
act= efa;
*dist= temp;
if(EM_zbuffer_visible(efa->cent, efa->xs, efa->ys)) {
act= efa;
*dist= temp;
}
}
if(efa== acto) break;
}
@ -294,7 +351,7 @@ static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
}
if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
if(efa->fgonf==0) {
if(0) {//efa->fgonf==0) {
if(efa->f & SELECT) BIF_ThemeColor(TH_EDGE_SELECT);
else BIF_ThemeColor(TH_WIRE);
@ -637,6 +694,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= eed->v2->h= 1;
EM_select_edge(eed, 0);
}
}
@ -654,6 +712,15 @@ 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 |= 1;
efa->e2->h |= 1;
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);
}
}
@ -682,7 +749,7 @@ void reveal_mesh(void)
}
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h) {
if(eed->h & 1) {
eed->h &= ~1;
eed->f |= SELECT;
}

@ -793,13 +793,17 @@ void borderselect(void)
EditEdge *eed;
EditFace *efa;
EM_zbuffer_visible(NULL, 0, 0); // init
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
calc_meshverts_ext(); /* clips, drawobject.c */
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->h==0 && eve->xs>rect.xmin && eve->xs<rect.xmax) {
if(eve->ys>rect.ymin && eve->ys<rect.ymax) {
if(val==LEFTMOUSE) eve->f|= 1;
else eve->f&= 254;
if(EM_zbuffer_visible(eve->co, eve->xs, eve->ys)) {
if(val==LEFTMOUSE) eve->f|= 1;
else eve->f&= 254;
}
}
}
}
@ -812,8 +816,12 @@ void borderselect(void)
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
if( edge_fully_inside_rect(rect, eed->v1->xs, eed->v1->ys, eed->v2->xs, eed->v2->ys)) {
EM_select_edge(eed, val==LEFTMOUSE);
done = 1;
if(EM_zbuffer_visible(eed->v1->co, eed->v1->xs, eed->v1->ys)) {
if(EM_zbuffer_visible(eed->v2->co, eed->v2->xs, eed->v2->ys)) {
EM_select_edge(eed, val==LEFTMOUSE);
done = 1;
}
}
}
}
}
@ -821,8 +829,13 @@ void borderselect(void)
if(done==0) {
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
if( edge_inside_rect(rect, eed->v1->xs, eed->v1->ys, eed->v2->xs, eed->v2->ys))
EM_select_edge(eed, val==LEFTMOUSE);
if( edge_inside_rect(rect, eed->v1->xs, eed->v1->ys, eed->v2->xs, eed->v2->ys)) {
if(EM_zbuffer_visible(eed->v1->co, eed->v1->xs, eed->v1->ys)) {
if(EM_zbuffer_visible(eed->v2->co, eed->v2->xs, eed->v2->ys)) {
EM_select_edge(eed, val==LEFTMOUSE);
}
}
}
}
}
}
@ -833,7 +846,9 @@ void borderselect(void)
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0 && efa->xs>rect.xmin && efa->xs<rect.xmax) {
if(efa->ys>rect.ymin && efa->ys<rect.ymax) {
EM_select_face_fgon(efa, val==LEFTMOUSE);
if(EM_zbuffer_visible(efa->cent, efa->xs, efa->ys)) {
EM_select_face_fgon(efa, val==LEFTMOUSE);
}
}
}
}
@ -1039,6 +1054,8 @@ void mesh_selectionCB(int selecting, Object *editobj, short *mval, float rad)
EditEdge *eed;
EditFace *efa;
float x, y, r;
EM_zbuffer_visible(NULL, 0, 0); // init
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
calc_meshverts_ext(); /* drawobject.c */
@ -1049,8 +1066,10 @@ void mesh_selectionCB(int selecting, Object *editobj, short *mval, float rad)
y= eve->ys-mval[1];
r= sqrt(x*x+y*y);
if(r<=rad) {
if(selecting==LEFTMOUSE) eve->f|= 1;
else eve->f&= 254;
if(EM_zbuffer_visible(eve->co, eve->xs, eve->ys)) {
if(selecting==LEFTMOUSE) eve->f|= 1;
else eve->f&= 254;
}
}
}
eve= eve->next;
@ -1064,7 +1083,11 @@ void mesh_selectionCB(int selecting, Object *editobj, short *mval, float rad)
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0) {
if( edge_inside_circle(mval[0], mval[1], (short)rad, eed->v1->xs, eed->v1->ys, eed->v2->xs, eed->v2->ys)) {
EM_select_edge(eed, selecting==LEFTMOUSE);
if(EM_zbuffer_visible(eed->v1->co, eed->v1->xs, eed->v1->ys)) {
if(EM_zbuffer_visible(eed->v2->co, eed->v2->xs, eed->v2->ys)) {
EM_select_edge(eed, selecting==LEFTMOUSE);
}
}
}
}
}
@ -1078,7 +1101,9 @@ void mesh_selectionCB(int selecting, Object *editobj, short *mval, float rad)
y= efa->ys-mval[1];
r= sqrt(x*x+y*y);
if(r<=rad) {
EM_select_face_fgon(efa, selecting==LEFTMOUSE);
if(EM_zbuffer_visible(efa->cent, efa->xs, efa->ys)) {
EM_select_face_fgon(efa, selecting==LEFTMOUSE);
}
}
}
}

@ -477,4 +477,42 @@ void bglEnd(void)
}
/* *************** glPolygonOffset hack ************* */
/* dist is only for ortho now... */
void bglPolygonOffset(float dist)
{
static float winmat[16], offset=0.0;
if(dist!=0.0) {
float offs;
// glEnable(GL_POLYGON_OFFSET_FILL);
// glPolygonOffset(-1.0, -1.0);
/* hack below is to mimic polygon offset */
glMatrixMode(GL_PROJECTION);
glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat);
if(winmat[15]>0.5) offs= 0.00005*dist; // ortho tweaking
else offs= 0.001; // should be clipping value or so...
winmat[14]-= offs;
offset+= offs;
glLoadMatrixf(winmat);
glMatrixMode(GL_MODELVIEW);
}
else {
glMatrixMode(GL_PROJECTION);
winmat[14]+= offset;
offset= 0.0;
glLoadMatrixf(winmat);
glMatrixMode(GL_MODELVIEW);
}
}

@ -3925,8 +3925,13 @@ void view3d_buttons(void)
uiDefIconButS(block, TOG|BIT|1, B_SEL_EDGE, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
xco+= XIC;
uiDefIconButS(block, TOG|BIT|2, B_SEL_FACE, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
xco+= XIC+20;
xco+= XIC;
uiBlockEndAlign(block);
if(G.vd->drawtype > OB_WIRE) {
uiDefIconButS(block, TOG|BIT|12, B_REDR, ICON_ORTHO, xco,0,XIC,YIC, &G.vd->flag, 1.0, 0.0, 0, 0, "Clip selection with Z buffer");
xco+= XIC;
}
xco+= 20;
}
uiDefIconBut(block, BUT, B_VIEWRENDER, ICON_SCENE_DEHLT, xco,0,XIC,YIC, NULL, 0, 1.0, 0, 0, "Render this window (hold CTRL for anim)");

@ -107,10 +107,14 @@ void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey)
glGetIntegerv(GL_BLUE_BITS, &b);
mainwin_color_depth= r + g + b;
if(G.f & G_DEBUG) {
printf("Color depth r %d g %d b %d\n", (int)r, (int)g, (int)b);
glGetIntegerv(GL_AUX_BUFFERS, &r);
printf("Aux buffers: %d\n", (int)r);
}
}
/* XXXXXXXXXXXXXXXX very hacky, not allowed to release
/* XXXXXXXXXXXXXXXX very hacky, not allowed to release again after 2.24
* again after 2.24
*/
void mywindow_build_and_set_renderwin(void)

@ -181,8 +181,8 @@ void project_short(float *vec, short *adr) /* clips */
fy= (curarea->winy/2)+(curarea->winy/2)*vec4[1]/vec4[3];
if(fy>0.0 && fy< (float)curarea->winy) {
adr[0]= floor(fx+0.5);
adr[1]= floor(fy+0.5);
adr[0]= floor(fx);
adr[1]= floor(fy);
}
}
}
@ -206,8 +206,8 @@ void project_short_noclip(float *vec, short *adr)
fy= (curarea->winy/2)+(curarea->winy/2)*vec4[1]/vec4[3];
if(fy>-32700.0 && fy<32700.0) {
adr[0]= floor(fx+0.5);
adr[1]= floor(fy+0.5);
adr[0]= floor(fx);
adr[1]= floor(fy);
}
}
}