/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include #include #ifdef HAVE_CONFIG_H #include #endif #ifdef _WIN32 #include "BLI_winstuff.h" #endif #include "MEM_guardedalloc.h" #include "BMF_Api.h" #include "IMB_imbuf.h" #include "MTC_matrixops.h" #include "DNA_camera_types.h" #include "DNA_curve_types.h" #include "DNA_constraint_types.h" // for drawing constraint #include "DNA_effect_types.h" #include "DNA_ipo_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_meta_types.h" #include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" #include "DNA_world_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" #include "BKE_utildefines.h" #include "BKE_curve.h" #include "BKE_constraint.h" // for the get_constraint_target function #include "BKE_deform.h" // lattice_modifier() #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_global.h" #include "BKE_ipo.h" #include "BKE_lattice.h" #include "BKE_mesh.h" #include "BKE_material.h" #include "BKE_mball.h" #include "BKE_object.h" #include "BIF_gl.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" #include "BIF_editarmature.h" #include "BIF_editika.h" #include "BIF_editmesh.h" #include "BIF_glutil.h" #include "BIF_resources.h" #include "BDR_drawmesh.h" #include "BDR_drawobject.h" #include "BDR_editobject.h" #include "BSE_view.h" #include "BSE_drawview.h" #include "BSE_trans_types.h" #include "blendef.h" #include "mydevice.h" #include "nla.h" #include "BKE_deform.h" /* pretty stupid */ /* extern Lattice *editLatt; already in BKE_lattice.h */ /* editcurve.c */ extern ListBase editNurb; /* editmball.c */ extern ListBase editelems; /* more or less needed forwards */ static void drawmeshwire(Object *ob); /***/ // Materials start counting at # one.... #define MAXMATBUF (MAXMAT + 1) static float matbuf[MAXMATBUF][2][4]; static void init_gl_materials(Object *ob) { extern Material defmaterial; // render module abuse... Material *ma; int a; if(ob->totcol==0) { matbuf[0][0][0]= defmaterial.r; matbuf[0][0][1]= defmaterial.g; matbuf[0][0][2]= defmaterial.b; matbuf[0][0][3]= 1.0; matbuf[0][1][0]= defmaterial.specr; matbuf[0][1][1]= defmaterial.specg; matbuf[0][1][2]= defmaterial.specb; matbuf[0][1][3]= 1.0; /* do material 1 too, for displists! */ VECCOPY(matbuf[1][0], matbuf[0][0]); VECCOPY(matbuf[1][1], matbuf[0][1]); } for(a=1; a<=ob->totcol; a++) { ma= give_current_material(ob, a); if(ma==NULL) ma= &defmaterial; if(aref+ma->emit)*ma->r; matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; matbuf[a][0][3]= 1.0; matbuf[a][1][0]= ma->spec*ma->specr; matbuf[a][1][1]= ma->spec*ma->specg; matbuf[a][1][2]= ma->spec*ma->specb; matbuf[a][1][3]= 1.0; } } } static void set_gl_material(int nr) { if(nrobmat, vecrot); getmouseco_areawin(mval); project_float(vecrot, cent); // no overflow in extreme cases persp(PERSP_WIN); glDrawBuffer(GL_FRONT); BIF_ThemeColor(TH_WIRE); setlinestyle(3); glBegin(GL_LINE_STRIP); glVertex2sv(mval); glVertex2fv(cent); glEnd(); setlinestyle(0); persp(PERSP_VIEW); glFlush(); // flush display for frontbuffer glDrawBuffer(GL_BACK); } void drawaxes(float size) { int axis; for (axis=0; axis<3; axis++) { float v1[3]= {0.0, 0.0, 0.0}; float v2[3]= {0.0, 0.0, 0.0}; int arrow_axis= (axis==0)?1:0; glBegin(GL_LINES); v2[axis]= size; glVertex3fv(v1); glVertex3fv(v2); v1[axis]= size*0.8; v1[arrow_axis]= -size*0.125; glVertex3fv(v1); glVertex3fv(v2); v1[arrow_axis]= size*0.125; glVertex3fv(v1); glVertex3fv(v2); glEnd(); v2[axis]+= size*0.125; glRasterPos3fv(v2); // patch for 3d cards crashing on glSelect for text drawing (IBM) if((G.f & G_PICKSEL) == 0) { if (axis==0) BMF_DrawString(G.font, "x"); else if (axis==1) BMF_DrawString(G.font, "y"); else BMF_DrawString(G.font, "z"); } } } #if 0 static void drawgourcube(void) { float n[3]; n[0]=0; n[1]=0; n[2]=0; glBegin(GL_QUADS); n[0]= -1.0; glNormal3fv(n); glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]); n[0]=0; glEnd(); glBegin(GL_QUADS); n[1]= -1.0; glNormal3fv(n); glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]); n[1]=0; glEnd(); glBegin(GL_QUADS); n[0]= 1.0; glNormal3fv(n); glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]); n[0]=0; glEnd(); glBegin(GL_QUADS); n[1]= 1.0; glNormal3fv(n); glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]); n[1]=0; glEnd(); glBegin(GL_QUADS); n[2]= 1.0; glNormal3fv(n); glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]); n[2]=0; glEnd(); glBegin(GL_QUADS); n[2]= -1.0; glNormal3fv(n); glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]); glEnd(); } #endif static void drawcube(void) { glBegin(GL_LINE_STRIP); glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]); glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[7]); glVertex3fv(cube[4]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(cube[1]); glVertex3fv(cube[5]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(cube[2]); glVertex3fv(cube[6]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(cube[3]); glVertex3fv(cube[7]); glEnd(); } #if 0 static void drawcube_size(float *size) { glPushMatrix(); glScalef(size[0], size[1], size[2]); glBegin(GL_LINE_STRIP); glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]); glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[7]); glVertex3fv(cube[4]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(cube[1]); glVertex3fv(cube[5]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(cube[2]); glVertex3fv(cube[6]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(cube[3]); glVertex3fv(cube[7]); glEnd(); glPopMatrix(); } #endif static void tekenshadbuflimits(Lamp *la, float mat[][4]) { float sta[3], end[3], lavec[3]; lavec[0]= -mat[2][0]; lavec[1]= -mat[2][1]; lavec[2]= -mat[2][2]; Normalise(lavec); sta[0]= mat[3][0]+ la->clipsta*lavec[0]; sta[1]= mat[3][1]+ la->clipsta*lavec[1]; sta[2]= mat[3][2]+ la->clipsta*lavec[2]; end[0]= mat[3][0]+ la->clipend*lavec[0]; end[1]= mat[3][1]+ la->clipend*lavec[1]; end[2]= mat[3][2]+ la->clipend*lavec[2]; glBegin(GL_LINE_STRIP); glVertex3fv(sta); glVertex3fv(end); glEnd(); glPointSize(3.0); bglBegin(GL_POINTS); bglVertex3fv(sta); bglVertex3fv(end); bglEnd(); glPointSize(1.0); } static void spotvolume(float *lvec, float *vvec, float inp) { /* camera is at 0,0,0 */ float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,hoek; Normalise(lvec); Normalise(vvec); /* is this the correct vector ? */ Crossf(temp,vvec,lvec); /* equation for a plane through vvec en lvec */ Crossf(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */ Normalise(plane); /* now we've got two equations: one of a cone and one of a plane, but we have three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */ /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */ /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/ /* translating this comment to english didnt really help me understanding the math! :-) (ton) */ q[1] = plane[1] ; q[2] = -plane[0] ; q[3] = 0 ; Normalise(&q[1]); hoek = saacos(plane[2])/2.0; co = cos(hoek); si = sqrt(1-co*co); q[0] = co; q[1] *= si; q[2] *= si; q[3] = 0; QuatToMat3(q,mat1); /* rotate lamp vector now over acos(inp) degrees */ vvec[0] = lvec[0] ; vvec[1] = lvec[1] ; vvec[2] = lvec[2] ; Mat3One(mat2); co = inp; si = sqrt(1-inp*inp); mat2[0][0] = co; mat2[1][0] = -si; mat2[0][1] = si; mat2[1][1] = co; Mat3MulMat3(mat3,mat2,mat1); mat2[1][0] = si; mat2[0][1] = -si; Mat3MulMat3(mat4,mat2,mat1); Mat3Transp(mat1); Mat3MulMat3(mat2,mat1,mat3); Mat3MulVecfl(mat2,lvec); Mat3MulMat3(mat2,mat1,mat4); Mat3MulVecfl(mat2,vvec); return; } static void drawlamp(Object *ob) { Lamp *la; float vec[3], lvec[3], vvec[3],x,y,z; la= ob->data; vec[0]=vec[1]=vec[2]= 0.0; setlinestyle(4); /* yafray: for photonlight also draw lightcone as for spot */ if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) { lvec[0]=lvec[1]= 0.0; lvec[2] = 1.0; x = G.vd->persmat[0][2]; y = G.vd->persmat[1][2]; z = G.vd->persmat[2][2]; vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2]; vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2]; vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2]; y = cos( M_PI*la->spotsize/360.0 ); spotvolume(lvec, vvec, y); x = -la->dist; lvec[0] *= x ; lvec[1] *= x ; lvec[2] *= x; vvec[0] *= x ; vvec[1] *= x ; vvec[2] *= x; glBegin(GL_LINE_STRIP); glVertex3fv(vvec); glVertex3fv(vec); glVertex3fv(lvec); glEnd(); z = x*sqrt(1.0 - y*y); x *= y; glTranslatef(0.0 , 0.0 , x); if(la->mode & LA_SQUARE) { vvec[0]= fabs(z); vvec[1]= fabs(z); vvec[2]= 0.0; glBegin(GL_LINE_LOOP); glVertex3fv(vvec); vvec[1]= -fabs(z); glVertex3fv(vvec); vvec[0]= -fabs(z); glVertex3fv(vvec); vvec[1]= fabs(z); glVertex3fv(vvec); glEnd(); } else circ(0.0, 0.0, fabs(z)); } else if ELEM(la->type, LA_HEMI, LA_SUN) { glBegin(GL_LINE_STRIP); glVertex3fv(vec); vec[2]= -la->dist; glVertex3fv(vec); glEnd(); } else { if(la->type==LA_AREA) { setlinestyle(0); if(la->area_shape==LA_AREA_SQUARE) fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5); else if(la->area_shape==LA_AREA_RECT) fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5); setlinestyle(3); glBegin(GL_LINE_STRIP); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,-la->dist); glEnd(); setlinestyle(0); } else if(la->mode & LA_SPHERE) { float tmat[4][4], imat[4][4]; vec[0]= vec[1]= vec[2]= 0.0; mygetmatrix(tmat); Mat4Invert(imat, tmat); drawcircball(vec, la->dist, imat); } } myloadmatrix(G.vd->viewmat); VECCOPY(vec, ob->obmat[3]); setlinestyle(3); glBegin(GL_LINE_STRIP); glVertex3fv(vec); vec[2]= 0; glVertex3fv(vec); glEnd(); setlinestyle(0); if(la->type==LA_SPOT && (la->mode & LA_SHAD) ) { tekenshadbuflimits(la, ob->obmat); } } static void draw_limit_line(float sta, float end, unsigned int col) { glBegin(GL_LINES); glVertex3f(0.0, 0.0, -sta); glVertex3f(0.0, 0.0, -end); glEnd(); glPointSize(3.0); glBegin(GL_POINTS); cpack(col); glVertex3f(0.0, 0.0, -sta); glVertex3f(0.0, 0.0, -end); glEnd(); glPointSize(1.0); } /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */ static void draw_focus_cross(float dist, float size) { glBegin(GL_LINES); glVertex3f(-size, 0.f, -dist); glVertex3f(size, 0.f, -dist); glVertex3f(0.f, -size, -dist); glVertex3f(0.f, size, -dist); glEnd(); } void drawcamera(Object *ob) { /* a standing up pyramid with (0,0,0) as top */ Camera *cam; World *wrld; float vec[8][4], tmat[4][4], fac, facx, facy, depth; cam= ob->data; /* this code only works for perspective */ if(G.vd->persp==2 && ob==G.vd->camera && cam->type==CAM_ORTHO) return; glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); /* that way it's always visible */ fac= cam->drawsize; if(G.vd->persp>=2 && ob==G.vd->camera) fac= cam->clipsta+0.1; depth= - fac*cam->lens/16.0; facx= fac*1.28; facy= fac*1.024; vec[0][0]= 0; vec[0][1]= 0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */ vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth; vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth; vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth; vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth; glBegin(GL_LINE_LOOP); glVertex3fv(vec[0]); glVertex3fv(vec[1]); glVertex3fv(vec[2]); glVertex3fv(vec[0]); glVertex3fv(vec[3]); glVertex3fv(vec[4]); glEnd(); glBegin(GL_LINES); glVertex3fv(vec[2]); glVertex3fv(vec[3]); glEnd(); glBegin(GL_LINES); glVertex3fv(vec[4]); glVertex3fv(vec[1]); glEnd(); if(G.vd->persp>=2) return; /* arrow on top */ vec[0][2]= depth; glBegin(GL_QUADS); vec[0][0]= -0.2*cam->drawsize; vec[0][1]= cam->drawsize; glVertex3fv(vec[0]); vec[0][0]= 0.2*cam->drawsize; glVertex3fv(vec[0]); vec[0][1]= 1.6*cam->drawsize; glVertex3fv(vec[0]); vec[0][0]= -0.2*cam->drawsize; glVertex3fv(vec[0]); glEnd(); glBegin(GL_TRIANGLES); vec[0][0]= -0.4*cam->drawsize; vec[0][1]= 1.6*cam->drawsize; glVertex3fv(vec[0]); vec[0][0]= 0.0; vec[0][1]= 2.0*cam->drawsize; glVertex3fv(vec[0]); vec[0][0]= 0.4*cam->drawsize; vec[0][1]= 1.6*cam->drawsize; glVertex3fv(vec[0]); glEnd(); if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) { myloadmatrix(G.vd->viewmat); Mat4CpyMat4(vec, ob->obmat); Mat4Ortho(vec); mymultmatrix(vec); MTC_Mat4SwapMat4(G.vd->persmat, tmat); mygetsingmatrix(G.vd->persmat); if(cam->flag & CAM_SHOWLIMITS) { draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF); /* yafray: dof focus point */ if (G.scene->r.renderer==R_YAFRAY) draw_focus_cross(cam->YF_dofdist, cam->drawsize); } wrld= G.scene->world; if(cam->flag & CAM_SHOWMIST) if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF); MTC_Mat4SwapMat4(G.vd->persmat, tmat); } } static void tekenvertslatt(short sel) { Lattice *lt; BPoint *bp; float size; int a, uxt, u, vxt, v, wxt, w; size= BIF_GetThemeValuef(TH_VERTEX_SIZE); glPointSize(size); if(sel) BIF_ThemeColor(TH_VERTEX_SELECT); else BIF_ThemeColor(TH_VERTEX); bglBegin(GL_POINTS); bp= editLatt->def; lt= editLatt; if(lt->flag & LT_OUTSIDE) { for(w=0; wpntsw; w++) { if(w==0 || w==lt->pntsw-1) wxt= 1; else wxt= 0; for(v=0; vpntsv; v++) { if(v==0 || v==lt->pntsv-1) vxt= 1; else vxt= 0; for(u=0; upntsu; u++, bp++) { if(u==0 || u==lt->pntsu-1) uxt= 1; else uxt= 0; if(uxt || vxt || wxt) { if(bp->hide==0) { if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec); } } } } } } else { a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { if(bp->hide==0) { if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec); } bp++; } } glPointSize(1.0); bglEnd(); } static void calc_lattverts(void) { BPoint *bp; float mat[4][4]; int a; MTC_Mat4SwapMat4(G.vd->persmat, mat); mygetsingmatrix(G.vd->persmat); bp= editLatt->def; a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; while(a--) { project_short(bp->vec, bp->s); bp++; } MTC_Mat4SwapMat4(G.vd->persmat, mat); } void calc_lattverts_ext(void) { areawinset(curarea->win); persp(PERSP_VIEW); mymultmatrix(G.obedit->obmat); calc_lattverts(); myloadmatrix(G.vd->viewmat); } static void drawlattice(Object *ob) { Lattice *lt; BPoint *bp, *bpu; int u, v, w, dv, dw, uxt, vxt, wxt; lt= ob->data; if(ob==G.obedit) { bp= editLatt->def; cpack(0x004000); } else { lattice_modifier(ob, 's'); bp= lt->def; } dv= lt->pntsu; dw= dv*lt->pntsv; if(lt->flag & LT_OUTSIDE) { for(w=0; wpntsw; w++) { if(w==0 || w==lt->pntsw-1) wxt= 1; else wxt= 0; for(v=0; vpntsv; v++) { if(v==0 || v==lt->pntsv-1) vxt= 1; else vxt= 0; for(u=0, bpu=0; upntsu; u++, bp++) { if(u==0 || u==lt->pntsu-1) uxt= 1; else uxt= 0; if(uxt || vxt || wxt) { if(w && (uxt || vxt)) { glBegin(GL_LINE_STRIP); glVertex3fv( (bp-dw)->vec ); glVertex3fv(bp->vec); glEnd(); } if(v && (uxt || wxt)) { glBegin(GL_LINES); glVertex3fv( (bp-dv)->vec ); glVertex3fv(bp->vec); glEnd(); } if(u && (vxt || wxt)) { glBegin(GL_LINES); glVertex3fv(bpu->vec); glVertex3fv(bp->vec); glEnd(); } } bpu= bp; } } } } else { for(w=0; wpntsw; w++) { for(v=0; vpntsv; v++) { for(u=0, bpu=0; upntsu; u++, bp++) { if(w) { glBegin(GL_LINES); glVertex3fv( (bp-dw)->vec ); glVertex3fv(bp->vec); glEnd(); } if(v) { glBegin(GL_LINES); glVertex3fv( (bp-dv)->vec ); glVertex3fv(bp->vec); glEnd(); } if(u) { glBegin(GL_LINES); glVertex3fv(bpu->vec); glVertex3fv(bp->vec); glEnd(); } bpu= bp; } } } } if(ob==G.obedit) { calc_lattverts(); if(G.zbuf) glDisable(GL_DEPTH_TEST); tekenvertslatt(0); tekenvertslatt(1); if(G.zbuf) glEnable(GL_DEPTH_TEST); } else lattice_modifier(ob, 'e'); } /* ***************** ******************** */ int subsurf_optimal(Object *ob) { if(ob->type==OB_MESH) { Mesh *me= ob->data; if( (me->flag & ME_OPT_EDGES) && (me->flag & ME_SUBSURF) && me->subdiv) return 1; } return 0; } void calc_mesh_facedots_ext(void) { EditMesh *em = G.editMesh; EditFace *efa; float mat[4][4]; if(em->faces.first==NULL) return; efa= em->faces.first; areawinset(curarea->win); persp(PERSP_VIEW); mymultmatrix(G.obedit->obmat); MTC_Mat4SwapMat4(G.vd->persmat, mat); mygetsingmatrix(G.vd->persmat); efa= em->faces.first; while(efa) { if( efa->h==0) { project_short(efa->cent, &(efa->xs)); } efa= efa->next; } MTC_Mat4SwapMat4(G.vd->persmat, mat); myloadmatrix(G.vd->viewmat); } /* window coord, assuming all matrices are set OK */ static void calc_meshverts(void) { EditMesh *em = G.editMesh; EditVert *eve; float mat[4][4]; if(em->verts.first==0) return; eve= em->verts.first; MTC_Mat4SwapMat4(G.vd->persmat, mat); mygetsingmatrix(G.vd->persmat); if(subsurf_optimal(G.obedit)) { // separate loop for speed for(eve= em->verts.first; eve; eve= eve->next) { if(eve->h==0 && eve->ssco) project_short(eve->ssco, &(eve->xs)); } } else { for(eve= em->verts.first; eve; eve= eve->next) { if(eve->h==0) project_short(eve->co, &(eve->xs)); } } MTC_Mat4SwapMat4(G.vd->persmat, mat); } /* window coord for current window, sets matrices temporal */ void calc_meshverts_ext(void) { areawinset(curarea->win); persp(PERSP_VIEW); mymultmatrix(G.obedit->obmat); calc_meshverts(); myloadmatrix(G.vd->viewmat); } /* window coord for current window, sets matrices temporal, sets (eve->f & 2) when not visible */ void calc_meshverts_ext_f2(void) { EditMesh *em = G.editMesh; EditVert *eve; float mat[4][4]; int optimal= subsurf_optimal(G.obedit); if(em->verts.first==0) return; eve= em->verts.first; /* matrices */ areawinset(curarea->win); persp(PERSP_VIEW); mymultmatrix(G.obedit->obmat); MTC_Mat4SwapMat4(G.vd->persmat, mat); mygetsingmatrix(G.vd->persmat); for(eve= em->verts.first; eve; eve= eve->next) { eve->f &= ~2; if(eve->h==0) { if(optimal && eve->ssco) project_short_noclip(eve->ssco, &(eve->xs)); else project_short_noclip(eve->co, &(eve->xs)); if( eve->xs >= 0 && eve->ys >= 0 && eve->xswinx && eve->yswiny); else eve->f |= 2; } } /* restore */ MTC_Mat4SwapMat4(G.vd->persmat, mat); myloadmatrix(G.vd->viewmat); } static void calc_Nurbverts(Nurb *nurb) { Nurb *nu; BezTriple *bezt; BPoint *bp; float mat[4][4]; int a; MTC_Mat4SwapMat4(G.vd->persmat, mat); mygetsingmatrix(G.vd->persmat); nu= nurb; while(nu) { if((nu->type & 7)==1) { bezt= nu->bezt; a= nu->pntsu; while(a--) { project_short(bezt->vec[0], bezt->s[0]); project_short(bezt->vec[1], bezt->s[1]); project_short(bezt->vec[2], bezt->s[2]); bezt++; } } else { bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { project_short(bp->vec, bp->s); bp++; } } nu= nu->next; } MTC_Mat4SwapMat4(G.vd->persmat, mat); } void calc_nurbverts_ext(void) { areawinset(curarea->win); persp(PERSP_VIEW); mymultmatrix(G.obedit->obmat); calc_Nurbverts(editNurb.first); myloadmatrix(G.vd->viewmat); } static void draw_vertices(int optimal, int sel) { EditMesh *em = G.editMesh; EditVert *eve; EditFace *efa; float size, fsize; char col[3], fcol[3]; /* if not V3D_ZBUF_SELECT: */ /* draws in zbuffer mode twice, to show invisible vertices transparent */ if(G.zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select size= BIF_GetThemeValuef(TH_VERTEX_SIZE); fsize= BIF_GetThemeValuef(TH_FACEDOT_SIZE); if(sel) { BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, col); BIF_GetThemeColor3ubv(TH_FACE_DOT, fcol); } else { BIF_GetThemeColor3ubv(TH_VERTEX, col); BIF_GetThemeColor3ubv(TH_WIRE, fcol); } if(G.zbuf) { if(G.vd->flag & V3D_ZBUF_SELECT); else { 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); bglBegin(GL_POINTS); if(optimal) { for(eve= em->verts.first; eve; eve= eve->next) { if(eve->h==0 && (eve->f & SELECT)==sel ) if(eve->ssco) bglVertex3fv(eve->ssco); } } else { for(eve= em->verts.first; eve; eve= eve->next) { if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co); } } 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); } } } bglEnd(); } glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); } } if(G.scene->selectmode & SCE_SELECT_VERTEX) { glPointSize(size); glColor3ub(col[0], col[1], col[2]); bglBegin(GL_POINTS); if(optimal) { for(eve= em->verts.first; eve; eve= eve->next) { if(eve->h==0 && (eve->f & SELECT)==sel ) if(eve->ssco) bglVertex3fv(eve->ssco); } } else { for(eve= em->verts.first; eve; eve= eve->next) { if(eve->h==0 && (eve->f & SELECT)==sel ) bglVertex3fv(eve->co); } } bglEnd(); } if(G.scene->selectmode & SCE_SELECT_FACE) { glPointSize(fsize); glColor3ub(fcol[0], fcol[1], fcol[2]); 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(); } if(G.zbuf) glDepthMask(1); glPointSize(1.0); } /* ************** DRAW DISPLIST ****************** */ /* DispListMesh, comes from subsurf or decimator */ static void displistmesh_draw_wire(DispListMesh *dlm) { MVert *mvert= dlm->mvert; MEdge *medge; int i, optim; if(dlm->medge) { optim= dlm->flag & ME_OPT_EDGES; medge= dlm->medge; glBegin(GL_LINES); for (i=0; itotedge; i++, medge++) { if(optim==0 || (medge->flag & ME_EDGEDRAW)) { glVertex3fv(mvert[medge->v1].co); glVertex3fv(mvert[medge->v2].co); } } glEnd(); } else { for (i=0; itotface; i++) { MFace *mf= &dlm->mface[i]; glBegin(GL_LINE_LOOP); glVertex3fv(dlm->mvert[mf->v1].co); glVertex3fv(dlm->mvert[mf->v2].co); if (mf->v3) { glVertex3fv(dlm->mvert[mf->v3].co); if (mf->v4) glVertex3fv(dlm->mvert[mf->v4].co); } glEnd(); } } } static void displistmesh_draw_solid(DispListMesh *dlm, float *nors) { int lmode, lshademodel= -1, lmat_nr= -1; int i; #define PASSVERT(ind) { \ if (lshademodel==GL_SMOOTH) \ glNormal3sv(dlm->mvert[(ind)].no); \ glVertex3fv(dlm->mvert[(ind)].co); \ } glBegin(lmode= GL_QUADS); for (i=0; itotface; i++) { MFace *mf= &dlm->mface[i]; if (mf->v3) { int nmode= mf->v4?GL_QUADS:GL_TRIANGLES; int nshademodel= (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT; if (nmode!=lmode) { glEnd(); glBegin(lmode= nmode); } if (nshademodel!=lshademodel) { glEnd(); glShadeModel(lshademodel= nshademodel); glBegin(lmode); } if (mf->mat_nr!=lmat_nr) { glEnd(); set_gl_material((lmat_nr= mf->mat_nr)+1); glBegin(lmode); } if (lshademodel==GL_FLAT) glNormal3fv(&nors[i*3]); PASSVERT(mf->v1); PASSVERT(mf->v2); PASSVERT(mf->v3); if (mf->v4) PASSVERT(mf->v4); } } glEnd(); #undef PASSVERT } static void displistmesh_draw_shaded(DispListMesh *dlm, unsigned char *vcols1, unsigned char *vcols2) { int i, lmode; glShadeModel(GL_SMOOTH); if (vcols2) glEnable(GL_CULL_FACE); #define PASSVERT(vidx, fidx) { \ unsigned char *col= &colbase[fidx*4]; \ glColor3ub(col[3], col[2], col[1]); \ glVertex3fv(dlm->mvert[(vidx)].co); \ } glBegin(lmode= GL_QUADS); for (i=0; itotface; i++) { MFace *mf= &dlm->mface[i]; if (mf->v3) { int nmode= mf->v4?GL_QUADS:GL_TRIANGLES; unsigned char *colbase= &vcols1[i*16]; if (nmode!=lmode) { glEnd(); glBegin(lmode= nmode); } PASSVERT(mf->v1, 0); PASSVERT(mf->v2, 1); PASSVERT(mf->v3, 2); if (mf->v4) PASSVERT(mf->v4, 3); if (vcols2) { unsigned char *colbase= &vcols2[i*16]; if (mf->v4) PASSVERT(mf->v4, 3); PASSVERT(mf->v3, 2); PASSVERT(mf->v2, 1); PASSVERT(mf->v1, 0); } } } glEnd(); if (vcols2) glDisable(GL_CULL_FACE); #undef PASSVERT } /***/ static int draw_index_wire= 1; static int index3_nors_incr= 1; static void drawDispListwire(ListBase *dlbase) { DispList *dl; int parts, nr, ofs, *index; float *data; if(dlbase==0) return; dl= dlbase->first; while(dl) { data= dl->verts; switch(dl->type) { case DL_SEGM: parts= dl->parts; while(parts--) { nr= dl->nr; glBegin(GL_LINE_STRIP); while(nr--) { glVertex3fv(data); data+=3; } glEnd(); } break; case DL_POLY: parts= dl->parts; while(parts--) { nr= dl->nr; glBegin(GL_LINE_LOOP); while(nr--) { glVertex3fv(data); data+=3; } glEnd(); } break; case DL_SURF: parts= dl->parts; while(parts--) { nr= dl->nr; if(dl->flag & DL_CYCL_U) glBegin(GL_LINE_LOOP); else glBegin(GL_LINE_STRIP); while(nr--) { glVertex3fv(data); data+=3; } glEnd(); } ofs= 3*dl->nr; nr= dl->nr; while(nr--) { data= ( dl->verts )+3*nr; parts= dl->parts; if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP); else glBegin(GL_LINE_STRIP); while(parts--) { glVertex3fv(data); data+=ofs; } glEnd(); } break; case DL_INDEX3: if(draw_index_wire) { parts= dl->parts; data= dl->verts; index= dl->index; while(parts--) { glBegin(GL_LINE_LOOP); glVertex3fv(data+3*index[0]); glVertex3fv(data+3*index[1]); glVertex3fv(data+3*index[2]); glEnd(); index+= 3; } } break; case DL_INDEX4: if(draw_index_wire) { parts= dl->parts; data= dl->verts; index= dl->index; while(parts--) { glBegin(GL_LINE_LOOP); glVertex3fv(data+3*index[0]); glVertex3fv(data+3*index[1]); glVertex3fv(data+3*index[2]); if(index[3]) glVertex3fv(data+3*index[3]); glEnd(); index+= 4; } } break; case DL_MESH: displistmesh_draw_wire(dl->mesh); break; } dl= dl->next; } } static void drawDispListsolid(ListBase *lb, Object *ob) { DispList *dl; int parts, ofs, p1, p2, p3, p4, a, b, *index; float *data, *v1, *v2, *v3, *v4; float *ndata, *n1, *n2, *n3, *n4; if(lb==0) return; glEnable(GL_LIGHTING); if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); else glFrontFace(GL_CCW); if(ob->type==OB_MBALL) { // mball always smooth shaded glShadeModel(GL_SMOOTH); } dl= lb->first; while(dl) { data= dl->verts; ndata= dl->nors; switch(dl->type) { case DL_SURF: set_gl_material(dl->col+1); if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); for(a=0; aparts; a++) { DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts); v1= data+ 3*p1; v2= data+ 3*p2; v3= data+ 3*p3; v4= data+ 3*p4; n1= ndata+ 3*p1; n2= ndata+ 3*p2; n3= ndata+ 3*p3; n4= ndata+ 3*p4; glBegin(GL_QUAD_STRIP); glNormal3fv(n2); glVertex3fv(v2); glNormal3fv(n4); glVertex3fv(v4); for(; bnr; b++) { glNormal3fv(n1); glVertex3fv(v1); glNormal3fv(n3); glVertex3fv(v3); v2= v1; v1+= 3; v4= v3; v3+= 3; n2= n1; n1+= 3; n4= n3; n3+= 3; } glEnd(); } break; case DL_INDEX3: parts= dl->parts; data= dl->verts; ndata= dl->nors; index= dl->index; set_gl_material(dl->col+1); /* voor polys only one normal needed */ if(index3_nors_incr==0) { while(parts--) { glBegin(GL_TRIANGLES); glNormal3fv(ndata); glVertex3fv(data+3*index[0]); glVertex3fv(data+3*index[1]); glVertex3fv(data+3*index[2]); glEnd(); index+= 3; } } else { while(parts--) { glBegin(GL_TRIANGLES); ofs= 3*index[0]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); ofs= 3*index[1]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); ofs= 3*index[2]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); glEnd(); index+= 3; } } break; case DL_INDEX4: parts= dl->parts; data= dl->verts; ndata= dl->nors; index= dl->index; set_gl_material(dl->col+1); while(parts--) { glBegin(index[3]?GL_QUADS:GL_TRIANGLES); ofs= 3*index[0]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); ofs= 3*index[1]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); ofs= 3*index[2]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); if(index[3]) { ofs= 3*index[3]; glNormal3fv(ndata+ofs); glVertex3fv(data+ofs); } glEnd(); index+= 4; } break; case DL_MESH: if (!dl->nors) addnormalsDispList(ob, lb); displistmesh_draw_solid(dl->mesh, dl->nors); break; } dl= dl->next; } glShadeModel(GL_FLAT); glDisable(GL_LIGHTING); glFrontFace(GL_CCW); } static void drawDispListshaded(ListBase *lb, Object *ob) { DispList *dl, *dlob; int parts, p1, p2, p3, p4, a, b, *index; float *data, *v1, *v2, *v3, *v4;/* , *extverts=0 */ unsigned int *cdata, *c1, *c2, *c3, *c4; char *cp; if(lb==0) return; glShadeModel(GL_SMOOTH); dl= lb->first; dlob= ob->disp.first; while(dl && dlob) { cdata= dlob->col1; data= dl->verts; if(cdata==0) break; switch(dl->type) { case DL_SURF: for(a=0; aparts; a++) { DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts); v1= data+ 3*p1; v2= data+ 3*p2; v3= data+ 3*p3; v4= data+ 3*p4; c1= cdata+ p1; c2= cdata+ p2; c3= cdata+ p3; c4= cdata+ p4; for(; bnr; b++) { glBegin(GL_QUADS); cp= (char *)c1; glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(v1); cp= (char *)c2; glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(v2); cp= (char *)c4; glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(v4); cp= (char *)c3; glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(v3); glEnd(); v2= v1; v1+= 3; v4= v3; v3+= 3; c2= c1; c1++; c4= c3; c3++; } } break; case DL_INDEX3: parts= dl->parts; index= dl->index; while(parts--) { glBegin(GL_TRIANGLES); cp= (char *)(cdata+index[0]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[0]); cp= (char *)(cdata+index[1]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[1]); cp= (char *)(cdata+index[2]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[2]); glEnd(); index+= 3; } break; case DL_INDEX4: parts= dl->parts; index= dl->index; while(parts--) { glBegin(index[3]?GL_QUADS:GL_TRIANGLES); cp= (char *)(cdata+index[0]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[0]); cp= (char *)(cdata+index[1]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[1]); cp= (char *)(cdata+index[2]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[2]); if(index[3]) { cp= (char *)(cdata+index[3]); glColor3ub(cp[3], cp[2], cp[1]); glVertex3fv(data+3*index[3]); } glEnd(); index+= 4; } break; case DL_MESH: displistmesh_draw_shaded(dl->mesh, (unsigned char*) dlob->col1, (unsigned char*) dlob->col2); break; } dl= dl->next; dlob= dlob->next; } glShadeModel(GL_FLAT); } static void drawmeshsolid(Object *ob, float *nors) { EditMesh *em = G.editMesh; Mesh *me; DispList *dl; MVert *mvert; TFace *tface; MFace *mface; EditFace *efa; float *extverts=0, *v1, *v2, *v3, *v4; int glmode, setsmooth=0, a, start, end, matnr= -1, vertexpaint, do_wire=0; short no[3], *n1, *n2, *n3, *n4 = NULL; vertexpaint= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0)); me= get_mesh(ob); if(me==0) return; glShadeModel(GL_FLAT); glEnable(GL_LIGHTING); init_gl_materials(ob); two_sided( me->flag & ME_TWOSIDED ); if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); else glFrontFace(GL_CCW); mface= me->mface; if( (G.f & G_FACESELECT) && ob==((G.scene->basact) ? (G.scene->basact->object) : 0)) tface= me->tface; else tface= 0; mvert= me->mvert; a= me->totface; /* SOLVE */ /* if ELEM(ob->type, OB_SECTOR, OB_LIFE) glEnable(GL_CULL_FACE); */ if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) { efa= em->faces.first; while(efa) { if(efa->h==0) { if(efa->mat_nr!=matnr) { matnr= efa->mat_nr; set_gl_material(matnr+1); } if(efa->v4) { glBegin(GL_QUADS); glNormal3fv(efa->n); glVertex3fv(efa->v1->co); glVertex3fv(efa->v2->co); glVertex3fv(efa->v3->co); glVertex3fv(efa->v4->co); glEnd(); } else { glBegin(GL_TRIANGLES); glNormal3fv(efa->n); glVertex3fv(efa->v1->co); glVertex3fv(efa->v2->co); glVertex3fv(efa->v3->co); glEnd(); } } efa= efa->next; } glDisable(GL_LIGHTING); glShadeModel(GL_FLAT); } else { /* [nors] should never be zero, but is weak code... the displist system needs a make over (ton) Face select and vertex paint calls drawmeshsolid() with nors = NULL! It's still weak code but hey, as ton says, the whole system needs a good thrashing! ;) (aphex) */ start= 0; end= me->totface; set_buildvars(ob, &start, &end); mface+= start; if(tface) tface+= start; dl= find_displist(&ob->disp, DL_VERTS); if(dl) extverts= dl->verts; glBegin(GL_QUADS); glmode= GL_QUADS; for(a=start; av3==0) do_wire= 1; else { if(tface && (tface->flag & TF_HIDE)) { glBegin(GL_LINE_LOOP); glVertex3fv( (mvert+mface->v1)->co); glVertex3fv( (mvert+mface->v2)->co); glVertex3fv( (mvert+mface->v3)->co); if(mface->v4) glVertex3fv( (mvert+mface->v1)->co); glEnd(); tface++; } else { if(extverts) { v1= extverts+3*mface->v1; v2= extverts+3*mface->v2; v3= extverts+3*mface->v3; if(mface->v4) v4= extverts+3*mface->v4; else v4= 0; } else { v1= (mvert+mface->v1)->co; v2= (mvert+mface->v2)->co; v3= (mvert+mface->v3)->co; if(mface->v4) v4= (mvert+mface->v4)->co; else v4= 0; } if(tface) { if(tface->mode & TF_TWOSIDE) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); } /* this GL_QUADS joke below was tested for speed: a factor 2! */ if(v4) {if(glmode==GL_TRIANGLES) {glmode= GL_QUADS; glEnd(); glBegin(GL_QUADS);}} else {if(glmode==GL_QUADS) {glmode= GL_TRIANGLES; glEnd(); glBegin(GL_TRIANGLES);}} if(mface->mat_nr!=matnr) { glEnd(); matnr= mface->mat_nr; set_gl_material(matnr+1); glBegin(glmode); } if( (me->flag & ME_AUTOSMOOTH)==0 && (mface->flag & ME_SMOOTH)) { if(setsmooth==0) { glEnd(); glShadeModel(GL_SMOOTH); glBegin(glmode); setsmooth= 1; } n1= (mvert+mface->v1)->no; n2= (mvert+mface->v2)->no; n3= (mvert+mface->v3)->no; if(v4) n4= (mvert+mface->v4)->no; if(mface->puno & ME_FLIPV1) { no[0]= -n1[0]; no[1]= -n1[1]; no[2]= -n1[2]; glNormal3sv(no); } else glNormal3sv(n1); glVertex3fv( v1 ); if(mface->puno & ME_FLIPV2) { no[0]= -n2[0]; no[1]= -n2[1]; no[2]= -n2[2]; glNormal3sv(no); } else glNormal3sv(n2); glVertex3fv( v2 ); if(mface->puno & ME_FLIPV3) { no[0]= -n3[0]; no[1]= -n3[1]; no[2]= -n3[2]; glNormal3sv(no); } else glNormal3sv(n3); glVertex3fv( v3 ); if(v4) { if(mface->puno & ME_FLIPV4) { no[0]= -n4[0]; no[1]= -n4[1]; no[2]= -n4[2]; glNormal3sv(no); } else glNormal3sv(n4); glVertex3fv( v4 ); } } else { if(setsmooth==1) { glEnd(); glShadeModel(GL_FLAT); glBegin(glmode); setsmooth= 0; } glNormal3fv(nors); glVertex3fv( v1 ); glVertex3fv( v2 ); glVertex3fv( v3 ); if(v4) glVertex3fv( v4 ); } } if(tface) tface++; } } glEnd(); if(do_wire) { start= 0; end= me->totface; set_buildvars(ob, &start, &end); mface= ((MFace *)me->mface)+start; BIF_ThemeColor(TH_WIRE); glBegin(GL_LINES); for(a=0; av3==0) { glVertex3fv((mvert+mface->v1)->co); glVertex3fv((mvert+mface->v2)->co); } } glEnd(); } } glDisable(GL_LIGHTING); glFrontFace(GL_CCW); } #if 0 // WIP: experiment with cleaner draw, but cant make it for this release (ton) static void drawmesh_vpaint(Object *ob) { Mesh *me= ob->data; MVert *mvert; MFace *mface; TFace *tface; int totface, a, glmode; char *mcol; if(mesh_uses_displist(me)) { DispList *dl= find_displist(&me->disp, DL_MESH); DispListMesh *dlm= dl->mesh; if(dlm==NULL) return; if(dlm->tface==NULL && dlm->mcol==NULL) return; mvert= dlm->mvert; mface= dlm->mface; totface= dlm->totface; mcol= (char *)dlm->mcol; tface= dlm->tface; } else { if(me->tface==NULL && me->mcol==NULL) return; mvert= me->mvert; mface= me->mface; totface= me->totface; mcol= (char *)me->mcol; tface= me->tface; } glShadeModel(GL_SMOOTH); glBegin(GL_QUADS); glmode= GL_QUADS; for(a=0; av3) { if(mface->v4) {if(glmode==GL_TRIANGLES) {glmode= GL_QUADS; glEnd(); glBegin(GL_QUADS);}} else {if(glmode==GL_QUADS) {glmode= GL_TRIANGLES; glEnd(); glBegin(GL_TRIANGLES);}} glColor3ub(mcol[3], mcol[2], mcol[1]); glVertex3fv( (mvert+mface->v1)->co ); glColor3ub(mcol[7], mcol[6], mcol[5]); glVertex3fv( (mvert+mface->v2)->co ); glColor3ub(mcol[11], mcol[10], mcol[9]); glVertex3fv( (mvert+mface->v3)->co ); if(mface->v4) { glColor3ub(mcol[15], mcol[14], mcol[13]); glVertex3fv( (mvert+mface->v4)->co ); } } mcol+=16; } } else { tface++; } } glEnd(); glShadeModel(GL_FLAT); } #endif static void drawmeshshaded(Object *ob, unsigned int *col1, unsigned int *col2) { Mesh *me; MVert *mvert; MFace *mface; TFace *tface; DispList *dl; float *extverts=0, *v1, *v2, *v3, *v4; int a, start, end, twoside; char *cp1, *cp2 = NULL; int lglmode; glShadeModel(GL_SMOOTH); glDisable(GL_LIGHTING); me= ob->data; mface= me->mface; /* then it does not draw hide */ if( (G.f & G_FACESELECT) && ob==((G.scene->basact) ? (G.scene->basact->object) : 0)) tface= me->tface; else tface= 0; mvert= me->mvert; a= me->totface; twoside= me->flag & ME_TWOSIDED; if(col2==0) twoside= 0; if(twoside) glEnable(GL_CULL_FACE); start= 0; end= me->totface; set_buildvars(ob, &start, &end); mface+= start; if(tface) tface+= start; col1+= 4*start; if(col2) col2+= 4*start; dl= find_displist(&ob->disp, DL_VERTS); if(dl) extverts= dl->verts; glBegin(lglmode= GL_QUADS); cp1= (char *)col1; if(col2) cp2= (char *)col2; for(a=start; av3) { if(tface && (tface->flag & TF_HIDE)) tface++; else { int nglmode= mface->v4?GL_QUADS:GL_TRIANGLES; if (nglmode!=lglmode) { glEnd(); glBegin(lglmode= nglmode); } if(extverts) { v1= extverts+3*mface->v1; v2= extverts+3*mface->v2; v3= extverts+3*mface->v3; if(mface->v4) v4= extverts+3*mface->v4; else v4= 0; } else { v1= (mvert+mface->v1)->co; v2= (mvert+mface->v2)->co; v3= (mvert+mface->v3)->co; if(mface->v4) v4= (mvert+mface->v4)->co; else v4= 0; } if(tface) { if(tface->mode & TF_TWOSIDE) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); } glColor3ub(cp1[3], cp1[2], cp1[1]); glVertex3fv( v1 ); glColor3ub(cp1[7], cp1[6], cp1[5]); glVertex3fv( v2 ); glColor3ub(cp1[11], cp1[10], cp1[9]); glVertex3fv( v3 ); if(v4) { glColor3ub(cp1[15], cp1[14], cp1[13]); glVertex3fv( v4 ); } if(twoside) { glColor3ub(cp2[11], cp2[10], cp2[9]); glVertex3fv( v3 ); glColor3ub(cp2[7], cp2[6], cp2[5]); glVertex3fv( v2 ); glColor3ub(cp2[3], cp2[2], cp2[1]); glVertex3fv( v1 ); if(mface->v4) { glColor3ub(cp2[15], cp2[14], cp2[13]); glVertex3fv( v4 ); } } } } if(col2) cp2+= 16; } glEnd(); glShadeModel(GL_FLAT); if(twoside) glDisable(GL_CULL_FACE); } static void drawDispList(Object *ob, int dt) { ListBase *lb=0; DispList *dl; Mesh *me; Curve *cu; int solid; solid= (dt > OB_WIRE); switch(ob->type) { case OB_MESH: me= get_mesh(ob); if(me==0) return; if(me->bb==0) tex_space_mesh(me); if(me->totface>4) if(boundbox_clip(ob->obmat, me->bb)==0) return; if(dt==OB_SOLID ) { lb= &me->disp; if(lb->first==NULL) addnormalsDispList(ob, lb); dl= lb->first; if(dl==NULL) return; if(dl->nors==NULL) addnormalsDispList(ob, lb); if(mesh_uses_displist(me)) { int vertexpaint= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0)); /* vertexpaint only true when selecting */ if (vertexpaint) { drawmeshsolid(ob, NULL); } else { init_gl_materials(ob); two_sided(me->flag & ME_TWOSIDED); drawDispListsolid(lb, ob); } } else { drawmeshsolid(ob, dl->nors); } } else if(dt==OB_SHADED) { if( G.f & G_WEIGHTPAINT && me->dvert) { unsigned char *wtcol, *curwt; MFace *curface; int i; unsigned char r,g,b; float val1,val2,val3,val4=0; wtcol = curwt= MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap"); memset (wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4); for (i=0, curface=(MFace*)me->mface; itotface; i++, curface++){ val1 = get_mvert_weight (ob, curface->v1, ob->actdef-1); val2 = get_mvert_weight (ob, curface->v2, ob->actdef-1); val3 = get_mvert_weight (ob, curface->v3, ob->actdef-1); if (curface->v4) val4 = get_mvert_weight (ob, curface->v4, ob->actdef-1); color_temperature (val1, &r, &g, &b); *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r; color_temperature (val2, &r, &g, &b); *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r; color_temperature (val3, &r, &g, &b); *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r; color_temperature (val4, &r, &g, &b); *curwt++=0; *curwt++=b; *curwt++=g; *curwt++=r; } drawmeshshaded(ob, (unsigned int*)wtcol, 0); MEM_freeN (wtcol); } else if( G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) { /* in order: vertexpaint already made mcol */ if(me->mcol) { drawmeshshaded(ob, (unsigned int *)me->mcol, 0); } else if(me->tface) { tface_to_mcol(me); drawmeshshaded(ob, (unsigned int *)me->mcol, 0); MEM_freeN(me->mcol); me->mcol= 0; } else drawmeshwire(ob); } else { dl= ob->disp.first; if(dl==0 || dl->col1==0) { shadeDispList(ob); dl= ob->disp.first; } if(dl) { if(mesh_uses_displist(me)) { drawDispListshaded(&me->disp, ob); } else { drawmeshshaded(ob, dl->col1, dl->col2); } } } } if(ob==((G.scene->basact) ? (G.scene->basact->object) : 0) && (G.f & G_FACESELECT)) { draw_tfaces3D(ob, me); } break; case OB_FONT: case OB_CURVE: cu= ob->data; lb= &cu->disp; if(lb->first==0) makeDispList(ob); if(solid) { dl= lb->first; if(dl==0) return; /* rule: dl->type INDEX3 is always first in list */ if(dl->type!=DL_INDEX3) { if(ob==G.obedit) curve_to_filledpoly(ob->data, &editNurb, lb); else curve_to_filledpoly(ob->data, &cu->nurb, lb); dl= lb->first; } if(dl->nors==0) addnormalsDispList(ob, lb); index3_nors_incr= 0; if( displist_has_faces(lb)==0) { draw_index_wire= 0; drawDispListwire(lb); draw_index_wire= 1; } else { if(dt==OB_SHADED) { if(ob->disp.first==0) shadeDispList(ob); drawDispListshaded(lb, ob); } else { init_gl_materials(ob); two_sided(0); drawDispListsolid(lb, ob); } if(ob==G.obedit) { cpack(0); draw_index_wire= 0; drawDispListwire(lb); draw_index_wire= 1; } } index3_nors_incr= 1; } else { draw_index_wire= 0; drawDispListwire(lb); draw_index_wire= 1; } break; case OB_SURF: lb= &((Curve *)ob->data)->disp; if(lb->first==0) makeDispList(ob); if(solid) { dl= lb->first; if(dl==0) return; if(dl->nors==0) addnormalsDispList(ob, lb); if(dt==OB_SHADED) { if(ob->disp.first==0) shadeDispList(ob); drawDispListshaded(lb, ob); } else { init_gl_materials(ob); two_sided(0); drawDispListsolid(lb, ob); } } else { drawDispListwire(lb); } break; case OB_MBALL: if( is_basis_mball(ob)) { lb= &ob->disp; if(lb->first==0) makeDispList(ob); if(solid) { if(dt==OB_SHADED) { dl= lb->first; if(dl && dl->col1==0) shadeDispList(ob); drawDispListshaded(lb, ob); } else { init_gl_materials(ob); two_sided(0); drawDispListsolid(lb, ob); } } else{ /* MetaBalls use DL_INDEX4 type of DispList */ drawDispListwire(lb); } } break; } } /* ******************************** */ static void draw_particle_system(Object *ob, PartEff *paf) { Particle *pa; float ptime, ctime, vec[3], vec1[3]; int a; pa= paf->keys; if(pa==0) { build_particle_system(ob); pa= paf->keys; if(pa==0) return; } myloadmatrix(G.vd->viewmat); if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf; else ptime= 0.0; ctime= bsystem_time(ob, 0, (float)(G.scene->r.cfra), ptime); glPointSize(1.0); if(paf->stype!=PAF_VECT) glBegin(GL_POINTS); for(a=0; atotpart; a++, pa+=paf->totkey) { if(ctime > pa->time) { if(ctime < pa->time+pa->lifetime) { if(paf->stype==PAF_VECT) { where_is_particle(paf, pa, ctime, vec); where_is_particle(paf, pa, ctime+1.0, vec1); glBegin(GL_LINE_STRIP); glVertex3fv(vec); glVertex3fv(vec1); glEnd(); } else { where_is_particle(paf, pa, ctime, vec); glVertex3fv(vec); } } } } if(paf->stype!=PAF_VECT) glEnd(); mymultmatrix(ob->obmat); // bring back local matrix for dtx } static void draw_static_particle_system(Object *ob, PartEff *paf) { Particle *pa; float ctime, mtime, vec[3], vec1[3]; int a; pa= paf->keys; if(pa==0) { build_particle_system(ob); pa= paf->keys; if(pa==0) return; } glPointSize(1.0); if(paf->stype!=PAF_VECT) glBegin(GL_POINTS); for(a=0; atotpart; a++, pa+=paf->totkey) { where_is_particle(paf, pa, pa->time, vec1); mtime= pa->time+pa->lifetime+paf->staticstep-1; for(ctime= pa->time; ctimestaticstep) { /* make sure hair grows until the end.. */ if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime; if(paf->stype==PAF_VECT) { where_is_particle(paf, pa, ctime+1, vec); glBegin(GL_LINE_STRIP); glVertex3fv(vec); glVertex3fv(vec1); glEnd(); VECCOPY(vec1, vec); } else { where_is_particle(paf, pa, ctime, vec); glVertex3fv(vec); } } } if(paf->stype!=PAF_VECT) glEnd(); } /* edges are supposed to be drawn already */ static void drawmeshwire_creases(void) { EditMesh *em = G.editMesh; EditEdge *eed; float fac, *v1, *v2, vec[3]; glLineWidth(3.0); glBegin(GL_LINES); for(eed= em->edges.first; eed; eed= eed->next) { if(eed->h==0 && eed->crease!=0.0) { if(eed->f & SELECT) BIF_ThemeColor(TH_EDGE_SELECT); else BIF_ThemeColor(TH_WIRE); v1= eed->v1->co; v2= eed->v2->co; VECSUB(vec, v2, v1); fac= 0.5 + eed->crease/2.0; glVertex3f(v1[0] + fac*vec[0], v1[1] + fac*vec[1], v1[2] + fac*vec[2] ); glVertex3f(v2[0] - fac*vec[0], v2[1] - fac*vec[1], v2[2] - fac*vec[2] ); } } glEnd(); glLineWidth(1.0); } 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_wirextra(DispListMesh *dlm, int optimal, char alpha) { EditMesh *em= G.editMesh; EditFace *efa; EditEdge *eed; int a; char wire[4], sel[4]; /* since this function does transparant... */ BIF_GetThemeColor3ubv(TH_EDGE_SELECT, sel); BIF_GetThemeColor3ubv(TH_WIRE, wire); wire[3]= alpha; sel[3]= alpha; if(G.scene->selectmode == SCE_SELECT_FACE) { glBegin(GL_LINES); if(dlm && optimal) { MEdge *medge= dlm->medge; MVert *mvert= dlm->mvert; for (a=0; atotedge; a++, medge++) { if(medge->flag & ME_EDGEDRAW) { eed= dlm->editedge[a]; if(eed && eed->h==0) { if(eed->f & SELECT) glColor4ubv(sel); else glColor4ubv(wire); glVertex3fv(mvert[medge->v1].co); glVertex3fv(mvert[medge->v2].co); } } } } else { /* draw faces twice, to have selected ones on top */ /* we draw unselected the edges though, so they show in face mode */ glColor4ubv(wire); for(eed= em->edges.first; eed; eed= eed->next) { if(eed->h==0) { glVertex3fv(eed->v1->co); glVertex3fv(eed->v2->co); } } glColor4ubv(sel); for(efa= em->faces.first; efa; efa= efa->next) { if(efa->h==0 && (efa->f & SELECT)) { glVertex_efa_edges(efa); } } } glEnd(); } else if( (G.f & G_DRAWEDGES) || (G.scene->selectmode & SCE_SELECT_EDGE) ) { /* Use edge highlighting */ /* (bleeding edges) to illustrate selection is defined on vertex basis */ /* but cannot do with subdivided edges... */ if( (dlm==NULL || optimal==0) && (G.scene->selectmode & SCE_SELECT_VERTEX)) { glShadeModel(GL_SMOOTH); glBegin(GL_LINES); for(eed= em->edges.first; eed; eed= eed->next) { if(eed->h==0) { if(eed->v1->f & SELECT) glColor4ubv(sel); else glColor4ubv(wire); glVertex3fv(eed->v1->co); if(eed->v2->f & SELECT) glColor4ubv(sel); else glColor4ubv(wire); glVertex3fv(eed->v2->co); } } glEnd(); glShadeModel(GL_FLAT); } else { glBegin(GL_LINES); if(dlm && optimal) { MEdge *medge= dlm->medge; MVert *mvert= dlm->mvert; for (a=0; atotedge; a++, medge++) { if(medge->flag & ME_EDGEDRAW) { eed= dlm->editedge[a]; if(eed && eed->h==0) { if(eed->f & SELECT) glColor4ubv(sel); else glColor4ubv(wire); glVertex3fv(mvert[medge->v1].co); glVertex3fv(mvert[medge->v2].co); } } } } else { glBegin(GL_LINES); for(eed= em->edges.first; eed; eed= eed->next) { if(eed->h==0) { if(eed->f & SELECT) glColor4ubv(sel); else glColor4ubv(wire); glVertex3fv(eed->v1->co); glVertex3fv(eed->v2->co); } } } glEnd(); } } else { glColor4ubv(wire); glBegin(GL_LINES); if(dlm && optimal) { MEdge *medge= dlm->medge; MVert *mvert= dlm->mvert; for (a=0; atotedge; a++, medge++) { if(medge->flag & ME_EDGEDRAW) { eed= dlm->editedge[a]; if(eed && eed->h==0) { glVertex3fv(mvert[medge->v1].co); glVertex3fv(mvert[medge->v2].co); } } } } else { for(eed= em->edges.first; eed; eed= eed->next) { if(eed->h==0) { glVertex3fv(eed->v1->co); glVertex3fv(eed->v2->co); } } } glEnd(); } } static void drawmeshwire_seams(DispListMesh *dlm, int optimal) { EditMesh *em= G.editMesh; EditEdge *eed; BIF_ThemeColor(TH_EDGE_SEAM); glLineWidth(2); if(dlm && optimal) { MEdge *medge= dlm->medge; MVert *mvert= dlm->mvert; int a; glBegin(GL_LINES); for (a=0; atotedge; a++, medge++) { if(medge->flag & ME_EDGEDRAW) { eed= dlm->editedge[a]; if(eed && eed->h==0 && eed->seam) { glVertex3fv(mvert[medge->v1].co); glVertex3fv(mvert[medge->v2].co); } } } glEnd(); } else { glBegin(GL_LINES); for(eed= em->edges.first; eed; eed= eed->next) { if(eed->h==0 && eed->seam) { glVertex3fv(eed->v1->co); glVertex3fv(eed->v2->co); } } glEnd(); } cpack(0x0); glLineWidth(1); } static void drawmeshwire(Object *ob) { EditMesh *em = G.editMesh; extern float editbutsize; /* buttons.c */ Mesh *me; MVert *mvert; MFace *mface; DispList *dl; Material *ma; EditFace *efa; float fvec[3], *f1, *f2, *f3, *f4, *extverts=NULL; int a, start, end, test, ok, optimal=0; 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; optimal= subsurf_optimal(ob); if( (G.f & (G_FACESELECT+G_DRAWFACES))) { /* transp faces */ char col1[4], col2[4]; BIF_GetThemeColor4ubv(TH_FACE, col1); BIF_GetThemeColor4ubv(TH_FACE_SELECT, col2); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glDepthMask(0); // disable write in zbuffer, needed for nice transp if(dlm && optimal) { for(a=0, mface= dlm->mface; atotface; 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(mface->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(); } } } 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(ob->dt>OB_WIRE && G.vd->drawtype>OB_WIRE); else { BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7); drawDispListwire(&me->disp); } } /* here starts all fancy draw-extra over */ if(G.f & G_DRAWSEAMS) drawmeshwire_seams(dlm, optimal); /* show wires in transparant when no zbuf clipping for select */ if(G.zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); drawmeshwire_wirextra(dlm, optimal, 85); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); } drawmeshwire_wirextra(dlm, optimal, 255); if(G.f & G_DRAWCREASES) drawmeshwire_creases(); if(ob!=G.obedit) return; calc_meshverts(); draw_vertices(optimal, 0); draw_vertices(optimal, 1); if(G.f & G_DRAWNORMALS) { /* normals */ /*cpack(0xDDDD22);*/ BIF_ThemeColor(TH_NORMAL); glBegin(GL_LINES); efa= em->faces.first; while(efa) { if(efa->h==0 && efa->fgonf!=EM_FGON) { VECCOPY(fvec, efa->cent); glVertex3fv(fvec); fvec[0]+= editbutsize*efa->n[0]; fvec[1]+= editbutsize*efa->n[1]; fvec[2]+= editbutsize*efa->n[2]; glVertex3fv(fvec); } efa= efa->next; } glEnd(); } } else { /* Object mode draw */ if(me==NULL) return; if(me->bb==NULL) tex_space_mesh(me); if(me->totface>4) if(boundbox_clip(ob->obmat, me->bb)==0) return; /* check for drawing vertices only */ ok= 0; if(me->totface==0 && me->totedge==0) ok= 1; else { ma= give_current_material(ob, 1); if(ma && (ma->mode & MA_HALO)) ok= 1; } mvert= me->mvert; mface= me->mface; dl= find_displist(&ob->disp, DL_VERTS); if(dl) extverts= dl->verts; if(ok) { start= 0; end= me->totvert; set_buildvars(ob, &start, &end); glPointSize(1.5); glBegin(GL_POINTS); if(extverts) { extverts+= 3*start; for(a= start; aco); } } glEnd(); glPointSize(1.0); } else { if(mesh_uses_displist(me)) drawDispListwire(&me->disp); /* Subsurf */ else { /* build effect only works on faces */ start= 0; end= me->totface; set_buildvars(ob, &start, &end); mface+= start; /* now decide whether to draw edges block */ if(me->medge && start==0 && end==me->totface) { MEdge *medge= me->medge; glBegin(GL_LINES); for(a=me->totedge; a>0; a--, medge++) { if(medge->flag & ME_EDGEDRAW) { if(extverts) { f1= extverts+3*medge->v1; f2= extverts+3*medge->v2; } else { f1= (mvert+medge->v1)->co; f2= (mvert+medge->v2)->co; } glVertex3fv(f1); glVertex3fv(f2); } } glEnd(); } else { for(a=start; aedcode; if(test) { if(extverts) { f1= extverts+3*mface->v1; f2= extverts+3*mface->v2; } else { f1= (mvert+mface->v1)->co; f2= (mvert+mface->v2)->co; } if(mface->v4) { if(extverts) { f3= extverts+3*mface->v3; f4= extverts+3*mface->v4; } else { f3= (mvert+mface->v3)->co; f4= (mvert+mface->v4)->co; } if(test== ME_V1V2+ME_V2V3+ME_V3V4+ME_V4V1) { glBegin(GL_LINE_LOOP); glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f4); glEnd(); } else if(test== ME_V1V2+ME_V2V3+ME_V3V4) { glBegin(GL_LINE_STRIP); glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f4); glEnd(); } else if(test== ME_V2V3+ME_V3V4+ME_V4V1) { glBegin(GL_LINE_STRIP); glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f4); glVertex3fv(f1); glEnd(); } else if(test== ME_V3V4+ME_V4V1+ME_V1V2) { glBegin(GL_LINE_STRIP); glVertex3fv(f3); glVertex3fv(f4); glVertex3fv(f1); glVertex3fv(f2); glEnd(); } else if(test== ME_V4V1+ME_V1V2+ME_V2V3) { glBegin(GL_LINE_STRIP); glVertex3fv(f4); glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glEnd(); } else { if(test & ME_V1V2) { glBegin(GL_LINE_STRIP); glVertex3fv(f1); glVertex3fv(f2); glEnd(); } if(test & ME_V2V3) { glBegin(GL_LINE_STRIP); glVertex3fv(f2); glVertex3fv(f3); glEnd(); } if(test & ME_V3V4) { glBegin(GL_LINE_STRIP); glVertex3fv(f3); glVertex3fv(f4); glEnd(); } if(test & ME_V4V1) { glBegin(GL_LINE_STRIP); glVertex3fv(f4); glVertex3fv(f1); glEnd(); } } } else if(mface->v3) { if(extverts) f3= extverts+3*mface->v3; else f3= (mvert+mface->v3)->co; if(test== ME_V1V2+ME_V2V3+ME_V3V1) { glBegin(GL_LINE_LOOP); glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glEnd(); } else if(test== ME_V1V2+ME_V2V3) { glBegin(GL_LINE_STRIP); glVertex3fv(f1); glVertex3fv(f2); glVertex3fv(f3); glEnd(); } else if(test== ME_V2V3+ME_V3V1) { glBegin(GL_LINE_STRIP); glVertex3fv(f2); glVertex3fv(f3); glVertex3fv(f1); glEnd(); } else if(test== ME_V1V2+ME_V3V1) { glBegin(GL_LINE_STRIP); glVertex3fv(f3); glVertex3fv(f1); glVertex3fv(f2); glEnd(); } else { if(test & ME_V1V2) { glBegin(GL_LINE_STRIP); glVertex3fv(f1); glVertex3fv(f2); glEnd(); } if(test & ME_V2V3) { glBegin(GL_LINE_STRIP); glVertex3fv(f2); glVertex3fv(f3); glEnd(); } if(test & ME_V3V1) { glBegin(GL_LINE_STRIP); glVertex3fv(f3); glVertex3fv(f1); glEnd(); } } } else if(test & ME_V1V2) { glBegin(GL_LINE_STRIP); glVertex3fv(f1); glVertex3fv(f2); glEnd(); } } } } } } } } unsigned int nurbcol[8]= { 0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 }; static void tekenhandlesN(Nurb *nu, short sel) { BezTriple *bezt; float *fp; unsigned int *col; int a; if(nu->hide) return; if( (nu->type & 7)==1) { if(sel) col= nurbcol+4; else col= nurbcol; bezt= nu->bezt; a= nu->pntsu; while(a--) { if(bezt->hide==0) { if( (bezt->f2 & 1)==sel) { fp= bezt->vec[0]; cpack(col[bezt->h1]); glBegin(GL_LINE_STRIP); glVertex3fv(fp); glVertex3fv(fp+3); glEnd(); cpack(col[bezt->h2]); glBegin(GL_LINE_STRIP); glVertex3fv(fp+3); glVertex3fv(fp+6); glEnd(); } else if( (bezt->f1 & 1)==sel) { fp= bezt->vec[0]; cpack(col[bezt->h1]); glBegin(GL_LINE_STRIP); glVertex3fv(fp); glVertex3fv(fp+3); glEnd(); } else if( (bezt->f3 & 1)==sel) { fp= bezt->vec[1]; cpack(col[bezt->h2]); glBegin(GL_LINE_STRIP); glVertex3fv(fp); glVertex3fv(fp+3); glEnd(); } } bezt++; } } } static void tekenvertsN(Nurb *nu, short sel) { BezTriple *bezt; BPoint *bp; float size; int a; if(nu->hide) return; if(sel) BIF_ThemeColor(TH_VERTEX_SELECT); else BIF_ThemeColor(TH_VERTEX); size= BIF_GetThemeValuef(TH_VERTEX_SIZE); glPointSize(size); bglBegin(GL_POINTS); if((nu->type & 7)==1) { bezt= nu->bezt; a= nu->pntsu; while(a--) { if(bezt->hide==0) { if((bezt->f1 & 1)==sel) bglVertex3fv(bezt->vec[0]); if((bezt->f2 & 1)==sel) bglVertex3fv(bezt->vec[1]); if((bezt->f3 & 1)==sel) bglVertex3fv(bezt->vec[2]); } bezt++; } } else { bp= nu->bp; a= nu->pntsu*nu->pntsv; while(a--) { if(bp->hide==0) { if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec); } bp++; } } bglEnd(); glPointSize(1.0); } static void draw_editnurb(Object *ob, Nurb *nurb, int sel) { Nurb *nu; BPoint *bp, *bp1; int a, b, ofs; nu= nurb; while(nu) { if(nu->hide==0) { switch(nu->type & 7) { case CU_POLY: cpack(nurbcol[3]); bp= nu->bp; for(b=0; bpntsv; b++) { if(nu->flagu & 1) glBegin(GL_LINE_LOOP); else glBegin(GL_LINE_STRIP); for(a=0; apntsu; a++, bp++) { glVertex3fv(bp->vec); } if(nu->flagu & 1) glEnd(); else glEnd(); } break; case CU_NURBS: bp= nu->bp; for(b=0; bpntsv; b++) { bp1= bp; bp++; for(a=nu->pntsu-1; a>0; a--, bp++) { if(bp->hide==0 && bp1->hide==0) { if(sel) { if( (bp->f1 & 1) && ( bp1->f1 & 1) ) { cpack(nurbcol[5]); glBegin(GL_LINE_STRIP); glVertex3fv(bp->vec); glVertex3fv(bp1->vec); glEnd(); } } else { if( (bp->f1 & 1) && ( bp1->f1 & 1) ); else { cpack(nurbcol[1]); glBegin(GL_LINE_STRIP); glVertex3fv(bp->vec); glVertex3fv(bp1->vec); glEnd(); } } } bp1= bp; } } if(nu->pntsv > 1) { /* surface */ ofs= nu->pntsu; for(b=0; bpntsu; b++) { bp1= nu->bp+b; bp= bp1+ofs; for(a=nu->pntsv-1; a>0; a--, bp+=ofs) { if(bp->hide==0 && bp1->hide==0) { if(sel) { if( (bp->f1 & 1) && ( bp1->f1 & 1) ) { cpack(nurbcol[7]); glBegin(GL_LINE_STRIP); glVertex3fv(bp->vec); glVertex3fv(bp1->vec); glEnd(); } } else { if( (bp->f1 & 1) && ( bp1->f1 & 1) ); else { cpack(nurbcol[3]); glBegin(GL_LINE_STRIP); glVertex3fv(bp->vec); glVertex3fv(bp1->vec); glEnd(); } } } bp1= bp; } } } break; } } nu= nu->next; } } static void drawnurb(Object *ob, Nurb *nurb, int dt) { extern float editbutsize; /* buttons.c */ Curve *cu; Nurb *nu; BevPoint *bevp; BevList *bl; float vec[3]; int a, nr, skip; /* first non-selected handles */ nu= nurb; while(nu) { if((nu->type & 7)==CU_BEZIER) { tekenhandlesN(nu, 0); } nu= nu->next; } /* then DispList */ BIF_ThemeColor(TH_WIRE); cu= ob->data; drawDispList(ob, dt); draw_editnurb(ob, nurb, 0); draw_editnurb(ob, nurb, 1); if(cu->flag & CU_3D) { if(cu->bev.first==0) makeBevelList(ob); BIF_ThemeColor(TH_WIRE); bl= cu->bev.first; nu= nurb; while(nu && bl) { bevp= (BevPoint *)(bl+1); nr= bl->nr; skip= nu->resolu/16; while(nr-- > 0) { glBegin(GL_LINE_STRIP); vec[0]= bevp->x-editbutsize*bevp->mat[0][0]; vec[1]= bevp->y-editbutsize*bevp->mat[0][1]; vec[2]= bevp->z-editbutsize*bevp->mat[0][2]; glVertex3fv(vec); vec[0]= bevp->x+editbutsize*bevp->mat[0][0]; vec[1]= bevp->y+editbutsize*bevp->mat[0][1]; vec[2]= bevp->z+editbutsize*bevp->mat[0][2]; glVertex3fv(vec); glEnd(); bevp++; a= skip; while(a--) { bevp++; nr--; } } bl= bl->next; nu= nu->next; } } calc_Nurbverts(nurb); if(G.zbuf) glDisable(GL_DEPTH_TEST); nu= nurb; while(nu) { if((nu->type & 7)==1) tekenhandlesN(nu, 1); tekenvertsN(nu, 0); nu= nu->next; } nu= nurb; while(nu) { tekenvertsN(nu, 1); nu= nu->next; } if(G.zbuf) glEnable(GL_DEPTH_TEST); } static void tekentextcurs(void) { cpack(0); glBegin(GL_QUADS); glVertex2fv(G.textcurs[0]); glVertex2fv(G.textcurs[1]); glVertex2fv(G.textcurs[2]); glVertex2fv(G.textcurs[3]); glEnd(); } void drawspiral(float *cent, float rad, float tmat[][4], int start) { float vec[3], vx[3], vy[3]; int a, tot=32; char inverse=0; /* 32 values of sin function (still same result!) */ static float si[32] = {0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213, 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196, 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573, -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278, -0.57126821, -0.39435585, -0.20129852, 0.00000000}; /* 32 values of cos function (still same result!) */ static float co[32] ={1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525, 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661, -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598, -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691, 0.82076344, 0.91895781, 0.97952994, 1.00000000}; if (start < 0) { inverse = 1; start *= -1; } VECCOPY(vx, tmat[0]); VECCOPY(vy, tmat[1]); VecMulf(vx, rad); VecMulf(vy, rad); VECCOPY(vec, cent); if (inverse==0) { for(a=0; a31) start=-a + 1; glBegin(GL_LINES); glVertex3fv(vec); vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)a/(float)tot) + *(co+a+start) * (vy[0] * (float)a/(float)tot); vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)a/(float)tot) + *(co+a+start) * (vy[1] * (float)a/(float)tot); vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)a/(float)tot) + *(co+a+start) * (vy[2] * (float)a/(float)tot); glVertex3fv(vec); glEnd(); } } else { a=0; vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot); vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot); vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot); for(a=0; a31) start=-a + 1; glBegin(GL_LINES); glVertex3fv(vec); vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot); vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot); vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot); glVertex3fv(vec); glEnd(); } } } void drawcircball(float *cent, float rad, float tmat[][4]) { float vec[3], vx[3], vy[3]; int a, tot=32; /* 32 values of sin function (still same result!) */ static float si[32] = {0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213, 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196, 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573, -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278, -0.57126821, -0.39435585, -0.20129852, 0.00000000}; /* 32 values of cos function (still same result!) */ static float co[32] ={1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525, 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661, -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598, -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691, 0.82076344, 0.91895781, 0.97952994, 1.00000000}; VECCOPY(vx, tmat[0]); VECCOPY(vy, tmat[1]); VecMulf(vx, rad); VecMulf(vy, rad); glBegin(GL_LINE_LOOP); for(a=0; adata; if(ob==G.obedit) { BIF_ThemeColor(TH_WIRE); if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt); ml= editelems.first; } else { drawDispList(ob, dt); ml= mb->elems.first; } /* in case solid draw, reset wire colors */ if(ob!=G.obedit && (ob->flag & SELECT)) { if(ob==OBACT) BIF_ThemeColor(TH_ACTIVE); else BIF_ThemeColor(TH_SELECT); } else BIF_ThemeColor(TH_WIRE); mygetmatrix(tmat); Mat4Invert(imat, tmat); Normalise(imat[0]); Normalise(imat[1]); while(ml) { if(ob==G.obedit) { if(ml->flag & SELECT) cpack(0xA0A0F0); else cpack(0x3030A0); if(G.f & G_PICKSEL) { ml->selcol= code; glLoadName(code++); } } drawcircball(&(ml->x), ml->rad, imat); ml= ml->next; } } static void draw_forcefield(Object *ob) { float imat[4][4], tmat[4][4]; float vec[3]= {0.0, 0.0, 0.0}; if (ob->pd->forcefield == PFIELD_FORCE) { float ffall_val; mygetmatrix(tmat); Mat4Invert(imat, tmat); Normalise(imat[0]); Normalise(imat[1]); if (has_ipo_code(ob->ipo, OB_PD_FFALL)) ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra); else ffall_val = ob->pd->f_power; BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5); drawcircball(vec, 1.0, imat); BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val)); drawcircball(vec, 1.5, imat); BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val)); drawcircball(vec, 2.0, imat); } else if (ob->pd->forcefield == PFIELD_VORTEX) { float ffall_val, force_val; Mat4One(imat); if (has_ipo_code(ob->ipo, OB_PD_FFALL)) ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra); else ffall_val = ob->pd->f_power; if (has_ipo_code(ob->ipo, OB_PD_FSTR)) force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra); else force_val = ob->pd->f_strength; BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7); if (force_val < 0) { drawspiral(vec, 1.0, imat, 1); drawspiral(vec, 1.0, imat, 16); } else { drawspiral(vec, 1.0, imat, -1); drawspiral(vec, 1.0, imat, -16); } } } static void draw_bb_box(BoundBox *bb) { float *vec; vec= bb->vec[0]; glBegin(GL_LINE_STRIP); glVertex3fv(vec); glVertex3fv(vec+3);glVertex3fv(vec+6); glVertex3fv(vec+9); glVertex3fv(vec); glVertex3fv(vec+12);glVertex3fv(vec+15); glVertex3fv(vec+18); glVertex3fv(vec+21); glVertex3fv(vec+12); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(vec+3); glVertex3fv(vec+15); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(vec+6); glVertex3fv(vec+18); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(vec+9); glVertex3fv(vec+21); glEnd(); } void get_local_bounds(Object *ob, float *centre, float *size) { BoundBox *bb= NULL; /* uses boundbox, function used by Ketsji */ if(ob->type==OB_MESH) { bb= ( (Mesh *)ob->data )->bb; if(bb==0) { tex_space_mesh(ob->data); bb= ( (Mesh *)ob->data )->bb; } } else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { bb= ( (Curve *)ob->data )->bb; } else if(ob->type==OB_MBALL) { bb= ob->bb; } if(bb==NULL) { centre[0]= centre[1]= centre[2]= 0.0; VECCOPY(size, ob->size); } else { size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]); size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]); size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]); centre[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0; centre[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0; centre[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0; } } static void draw_bb_quadric(BoundBox *bb, short type) { float size[3], cent[3]; GLUquadricObj *qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]); size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]); size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]); cent[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0; cent[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0; cent[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0; glPushMatrix(); if(type==OB_BOUND_SPHERE) { glTranslatef(cent[0], cent[1], cent[2]); glScalef(size[0], size[1], size[2]); gluSphere(qobj, 1.0, 8, 5); } else if(type==OB_BOUND_CYLINDER) { float radius = size[0] > size[1] ? size[0] : size[1]; glTranslatef(cent[0], cent[1], cent[2]-size[2]); glScalef(radius, radius, 2.0*size[2]); gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1); } else if(type==OB_BOUND_CONE) { float radius = size[0] > size[1] ? size[0] : size[1]; glTranslatef(cent[0], cent[2]-size[2], cent[1]); glScalef(radius, 2.0*size[2], radius); glRotatef(-90., 1.0, 0.0, 0.0); gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); } glPopMatrix(); gluDeleteQuadric(qobj); } static void draw_bounding_volume(Object *ob) { BoundBox *bb=0; if(ob->type==OB_MESH) { bb= ( (Mesh *)ob->data )->bb; if(bb==0) { tex_space_mesh(ob->data); bb= ( (Mesh *)ob->data )->bb; } } else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { bb= ( (Curve *)ob->data )->bb; if(bb==0) { makeDispList(ob); bb= ( (Curve *)ob->data )->bb; } } else if(ob->type==OB_MBALL) { bb= ob->bb; if(bb==0) { makeDispList(ob); bb= ob->bb; } } else { drawcube(); return; } if(bb==0) return; if(ob->boundtype==OB_BOUND_BOX) draw_bb_box(bb); else draw_bb_quadric(bb, ob->boundtype); } static void drawtexspace(Object *ob) { Mesh *me; MetaBall *mb; Curve *cu; BoundBox bb; float *vec, *loc, *size; if(ob->type==OB_MESH) { me= ob->data; size= me->size; loc= me->loc; } else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { cu= ob->data; size= cu->size; loc= cu->loc; } else if(ob->type==OB_MBALL) { mb= ob->data; size= mb->size; loc= mb->loc; } else return; bb.vec[0][0]=bb.vec[1][0]=bb.vec[2][0]=bb.vec[3][0]= loc[0]-size[0]; bb.vec[4][0]=bb.vec[5][0]=bb.vec[6][0]=bb.vec[7][0]= loc[0]+size[0]; bb.vec[0][1]=bb.vec[1][1]=bb.vec[4][1]=bb.vec[5][1]= loc[1]-size[1]; bb.vec[2][1]=bb.vec[3][1]=bb.vec[6][1]=bb.vec[7][1]= loc[1]+size[1]; bb.vec[0][2]=bb.vec[3][2]=bb.vec[4][2]=bb.vec[7][2]= loc[2]-size[2]; bb.vec[1][2]=bb.vec[2][2]=bb.vec[5][2]=bb.vec[6][2]= loc[2]+size[2]; setlinestyle(2); vec= bb.vec[0]; glBegin(GL_LINE_STRIP); glVertex3fv(vec); glVertex3fv(vec+3);glVertex3fv(vec+6); glVertex3fv(vec+9); glVertex3fv(vec); glVertex3fv(vec+12);glVertex3fv(vec+15); glVertex3fv(vec+18); glVertex3fv(vec+21); glVertex3fv(vec+12); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(vec+3); glVertex3fv(vec+15); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(vec+6); glVertex3fv(vec+18); glEnd(); glBegin(GL_LINE_STRIP); glVertex3fv(vec+9); glVertex3fv(vec+21); glEnd(); setlinestyle(0); } static int ob_from_decimator(Object *ob) { /* note: this is a temporal solution, a reconstruction of the displist system should take care of it (ton) */ DispList *dl; dl= ob->disp.first; if(dl && dl->mesh) return 1; return 0; } /* draws wire outline */ static void drawSolidSelect(Object *ob, ListBase *lb) { if(ob->flag & SELECT) { glLineWidth(2.0); glDepthMask(0); if(ob->type==OB_MESH) { /* optimal draw gives ugly outline, so we temporally disable it */ Mesh *me= ob->data; if(me->totface) { DispList *dl= me->disp.first; DispListMesh *dlm=NULL; short flag= 0; if(dl && dl->mesh) { dlm= dl->mesh; flag= dlm->flag & ME_OPT_EDGES; dlm->flag &= ~ME_OPT_EDGES; } drawmeshwire(ob); if(dlm && flag) dlm->flag |= flag; } } else drawDispListwire(lb); glLineWidth(1.0); glDepthMask(1); } } static void draw_solid_select(Object *ob) { Curve *cu; if(ob->dtx & OB_DRAWWIRE) return; switch(ob->type) { case OB_MESH: drawSolidSelect(ob, NULL); break; case OB_FONT: case OB_CURVE: case OB_SURF: cu= ob->data; if(displist_has_faces(&cu->disp)) if(boundbox_clip(ob->obmat, cu->bb)) drawSolidSelect(ob, &cu->disp); break; case OB_MBALL: drawSolidSelect(ob, &ob->disp); break; } } static void drawWireExtra(Object *ob, ListBase *lb) { if(ob!=G.obedit && (ob->flag & SELECT)) { if(ob==OBACT) BIF_ThemeColor(TH_ACTIVE); else BIF_ThemeColor(TH_SELECT); } else BIF_ThemeColor(TH_WIRE); bglPolygonOffset(1.0); glDepthMask(0); // disable write in zbuffer, selected edge wires show better if(ob->type==OB_MESH) drawmeshwire(ob); else if(ob->type==OB_CURVE) { draw_index_wire= 0; drawDispListwire(lb); draw_index_wire= 1; } else drawDispListwire(lb); glDepthMask(1); bglPolygonOffset(0.0); } static void draw_extra_wire(Object *ob) { Curve *cu; switch(ob->type) { case OB_MESH: drawWireExtra(ob, NULL); break; case OB_FONT: case OB_CURVE: case OB_SURF: cu= ob->data; if(boundbox_clip(ob->obmat, cu->bb)) drawWireExtra(ob, &cu->disp); break; case OB_MBALL: drawWireExtra(ob, &ob->disp); break; } } /* should be called in view space */ static void draw_hooks(Object *ob) { ObHook *hook; float vec[3]; for(hook= ob->hooks.first; hook; hook= hook->next) { VecMat4MulVecfl(vec, ob->obmat, hook->cent); if(hook->parent) { setlinestyle(3); glBegin(GL_LINES); glVertex3fv(hook->parent->obmat[3]); glVertex3fv(vec); glEnd(); setlinestyle(0); } glPointSize(3.0); bglBegin(GL_POINTS); bglVertex3fv(vec); bglEnd(); glPointSize(1.0); } } void draw_object(Base *base) { PartEff *paf; Object *ob; Curve *cu; Mesh *me; ListBase elems; CfraElem *ce; float cfraont, axsize=1.0; unsigned int *rect, col=0; static int warning_recursive= 0; int sel, drawtype, colindex= 0, ipoflag; short dt, dtx, zbufoff= 0; ob= base->object; /* draw keys? */ if(base==(G.scene->basact) || (base->flag & (SELECT+BA_WASSEL))) { if(warning_recursive==0 && ob!=G.obedit) { if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) { float temp[7][3]; warning_recursive= 1; elems.first= elems.last= 0; make_cfra_list(ob->ipo, &elems); cfraont= (G.scene->r.cfra); drawtype= G.vd->drawtype; if(drawtype>OB_WIRE) G.vd->drawtype= OB_WIRE; sel= base->flag; memcpy(temp, &ob->loc, 7*3*sizeof(float)); ipoflag= ob->ipoflag; ob->ipoflag &= ~OB_OFFS_OB; set_no_parent_ipo(1); disable_speed_curve(1); if ((ob->ipoflag & OB_DRAWKEYSEL)==0) { ce= elems.first; while(ce) { if(!ce->sel) { (G.scene->r.cfra)= ce->cfra/G.scene->r.framelen; base->flag= 0; where_is_object_time(ob, (G.scene->r.cfra)); draw_object(base); } ce= ce->next; } } ce= elems.first; while(ce) { if(ce->sel) { (G.scene->r.cfra)= ce->cfra/G.scene->r.framelen; base->flag= SELECT; where_is_object_time(ob, (G.scene->r.cfra)); draw_object(base); } ce= ce->next; } set_no_parent_ipo(0); disable_speed_curve(0); base->flag= sel; ob->ipoflag= ipoflag; /* restore icu->curval */ (G.scene->r.cfra)= cfraont; memcpy(&ob->loc, temp, 7*3*sizeof(float)); where_is_object(ob); G.vd->drawtype= drawtype; BLI_freelistN(&elems); warning_recursive= 0; } } } /* patch? children objects with a timeoffs change the parents. How to solve! */ /* if( ((int)ob->ctime) != F_(G.scene->r.cfra)) where_is_object(ob); */ mymultmatrix(ob->obmat); /* which wire color */ if((G.f & G_PICKSEL) == 0) { project_short(ob->obmat[3], &base->sx); if(G.moving==1 && (base->flag & (SELECT+BA_PARSEL))) BIF_ThemeColor(TH_TRANSFORM); else { BIF_ThemeColor(TH_WIRE); if((G.scene->basact)==base) { if(base->flag & (SELECT+BA_WASSEL)) BIF_ThemeColor(TH_ACTIVE); } else { if(base->flag & (SELECT+BA_WASSEL)) BIF_ThemeColor(TH_SELECT); } // no theme yet if(ob->id.lib) { if(base->flag & (SELECT+BA_WASSEL)) colindex = 4; else colindex = 3; } else if(warning_recursive==1) { if(base->flag & (SELECT+BA_WASSEL)) colindex = 7; else colindex = 6; } } if(colindex) { col= colortab[colindex]; cpack(col); } } /* maximum drawtype */ dt= MIN2(G.vd->drawtype, ob->dt); if(G.zbuf==0 && dt>OB_WIRE) dt= OB_WIRE; dtx= 0; /* faceselect exception: also draw solid when dt==wire, except in editmode */ if(ob==((G.scene->basact) ? (G.scene->basact->object) : 0) && (G.f & (G_FACESELECT+G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT))) { if(ob->type==OB_MESH) { if(ob==G.obedit); else { dt= OB_SHADED; glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); zbufoff= 1; } } else { if(dt=OB_WIRE ) { dtx= ob->dtx; if(G.obedit==ob) { // the only 2 extra drawtypes alowed in editmode dtx= dtx & (OB_DRAWWIRE|OB_TEXSPACE); } else if(G.f & (G_FACESELECT)) { // unwanted combo dtx &= ~OB_DRAWWIRE; } if(G.f & G_DRAW_EXT) { if(ob->type==OB_EMPTY || ob->type==OB_CAMERA || ob->type==OB_LAMP) dt= OB_WIRE; } } /* exception for mesh..., needs to be here for outline draw */ if(ob->type==OB_MESH) { me= ob->data; /* check for need for displist (it's zero when parent, key, or hook changed) */ if(ob->disp.first==NULL) { if(ob->parent && ob->partype==PARSKEL) makeDispList(ob); else if(ob->parent && ob->parent->type==OB_LATTICE) makeDispList(ob); else if(ob->hooks.first) makeDispList(ob); else if(ob->softflag) makeDispList(ob); else if(me->disp.first==NULL && mesh_uses_displist(me)) makeDispList(ob); else if(ob->effect.first) { // as last check Effect *eff= ob->effect.first; if(eff->type==EFF_WAVE) makeDispList(ob); } } } /* draw outline for selected solid objects */ if(G.vd->flag & V3D_SELECT_OUTLINE) { if(dt>OB_WIRE && dttype) { case OB_MESH: me= ob->data; if(base->flag & OB_RADIO); else if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) { if(dt<=OB_WIRE) drawmeshwire(ob); else { if(mesh_uses_displist(me)) { init_gl_materials(ob); two_sided( me->flag & ME_TWOSIDED ); drawDispListsolid(&me->disp, ob); } else { drawmeshsolid(ob, 0); } dtx |= OB_DRAWWIRE; // draws edges, transp faces, subsurf optimal, vertices } if(ob==G.obedit && (G.f & G_PROPORTIONAL)) draw_prop_circle(); } else { Material *ma= give_current_material(ob, 1); if(ob_from_decimator(ob)) drawDispListwire(&ob->disp); else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else if(dt==OB_WIRE || me->totface==0) drawmeshwire(ob); else if(ma && (ma->mode & MA_HALO)) drawmeshwire(ob); else if(G.f & G_FACESELECT || G.vd->drawtype==OB_TEXTURE) { draw_tface_mesh(ob, ob->data, dt); } else drawDispList(ob, dt); } if( ob!=G.obedit) { paf = give_parteff(ob); if( paf ) { if(col) cpack(0xFFFFFF); /* for visibility */ if(paf->flag & PAF_STATIC) draw_static_particle_system(ob, paf); else if((G.f & G_PICKSEL) == 0) draw_particle_system(ob, paf); // selection errors happen to easy if(col) cpack(col); } } break; case OB_FONT: cu= ob->data; if(ob==G.obedit) { tekentextcurs(); cpack(0xFFFF90); drawDispList(ob, OB_WIRE); } else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt); break; case OB_CURVE: case OB_SURF: cu= ob->data; if(ob==G.obedit) { drawnurb(ob, editNurb.first, dt); if((G.f & G_PROPORTIONAL)) draw_prop_circle(); } else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt); break; case OB_MBALL: if(ob==G.obedit) drawmball(ob, dt); else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else drawmball(ob, dt); break; case OB_EMPTY: drawaxes(1.0); break; case OB_LAMP: /* does a myloadmatrix */ drawlamp(ob); if(dtx) mymultmatrix(ob->obmat); break; case OB_CAMERA: drawcamera(ob); break; case OB_LATTICE: drawlattice(ob); if(ob==G.obedit && (G.f & G_PROPORTIONAL)) draw_prop_circle(); break; case OB_ARMATURE: draw_armature (ob); break; default: drawaxes(1.0); } if(ob->pd && ob->pd->forcefield) draw_forcefield(ob); /* draw extra: after normal draw because of makeDispList */ if(dtx) { if(G.f & G_SIMULATION); else if(dtx & OB_AXIS) { drawaxes(axsize); } if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob); if(dtx & OB_TEXSPACE) drawtexspace(ob); if(dtx & OB_DRAWNAME) { // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing if((G.f & G_PICKSEL) == 0) { glRasterPos3f(0.0, 0.0, 0.0); BMF_DrawString(G.font, " "); BMF_DrawString(G.font, ob->id.name+2); } } if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp); if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) draw_extra_wire(ob); } if(dtgameflag & OB_ACTOR) && (ob->gameflag & OB_DYNAMIC)) { float tmat[4][4], imat[4][4], vec[3]; vec[0]= vec[1]= vec[2]= 0.0; mygetmatrix(tmat); Mat4Invert(imat, tmat); setlinestyle(2); drawcircball(vec, ob->inertia, imat); setlinestyle(0); } } myloadmatrix(G.vd->viewmat); if(zbufoff) glDisable(GL_DEPTH_TEST); if(warning_recursive) return; if(base->flag & OB_FROMDUPLI) return; if(base->flag & OB_RADIO) return; if(G.f & G_SIMULATION) return; if((G.f & (G_PICKSEL))==0) { ListBase *list; /* draw hook center and offset line */ if(ob->hooks.first && ob!=G.obedit) draw_hooks(ob); /* help lines and so */ if(ob!=G.obedit && ob->parent && (ob->parent->lay & G.vd->lay)) { setlinestyle(3); glBegin(GL_LINES); glVertex3fv(ob->obmat[3]); glVertex3fv(ob->orig); glEnd(); setlinestyle(0); } /* Drawing the constraint lines */ list = &ob->constraints; if (list){ extern void make_axis_color(char *col, char *col2, char axis); // drawview.c bConstraint *curcon; float size[3], tmat[4][4]; char col[4], col2[4]; BIF_GetThemeColor3ubv(TH_GRID, col); make_axis_color(col, col2, 'z'); glColor3ubv(col2); for (curcon = list->first; curcon; curcon=curcon->next){ if ((curcon->flag & CONSTRAINT_EXPAND)&&(curcon->type!=CONSTRAINT_TYPE_NULL)&&(constraint_has_target(curcon))){ get_constraint_target_matrix(curcon, TARGET_OBJECT, NULL, tmat, size, bsystem_time(ob, 0, (float)(G.scene->r.cfra), ob->sf)); setlinestyle(3); glBegin(GL_LINES); glVertex3fv(tmat[3]); glVertex3fv(ob->obmat[3]); glEnd(); setlinestyle(0); } } } /* object centers */ if(G.zbuf) glDisable(GL_DEPTH_TEST); if(ob->type == OB_LAMP) { if(ob->id.lib) { if(base->flag & SELECT) rect= rectllib_sel; else rect= rectllib_desel; } else if(ob->id.us>1) { if(base->flag & SELECT) rect= rectlus_sel; else rect= rectlus_desel; } else { if(base->flag & SELECT) rect= rectl_sel; else rect= rectl_desel; } draw_icon_centered(ob->obmat[3], rect, 9); } else { if(ob->id.lib || ob->id.us>1) { if(base->flag & SELECT) rect= rectu_sel; else rect= rectu_desel; } else { if(base->flag & SELECT) rect= rect_sel; /* The center of the active object (which need not * be selected) gets drawn as if it were selected */ else if(base==(G.scene->basact)) rect= rect_sel; else rect= rect_desel; } draw_icon_centered(ob->obmat[3], rect, 4); } if(G.zbuf) glEnable(GL_DEPTH_TEST); } else if((G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0) { glBegin(GL_POINTS); glVertex3fv(ob->obmat[3]); glEnd(); } } void draw_object_ext(Base *base) { if(G.vd==NULL || base==NULL) return; if(G.vd->drawtype > OB_WIRE) { G.zbuf= 1; glEnable(GL_DEPTH_TEST); } G.f |= G_DRAW_EXT; glDrawBuffer(GL_FRONT); persp(PERSP_VIEW); draw_object(base); G.f &= ~G_DRAW_EXT; glFlush(); /* reveil frontbuffer drawing */ glDrawBuffer(GL_BACK); if(G.zbuf) { G.zbuf= 0; glDisable(GL_DEPTH_TEST); } curarea->win_swap= WIN_FRONT_OK; } /* ***************** BACKBUF SEL (BBS) ********* */ static int bbs_mesh_verts(Object *ob, int offset) { EditVert *eve; int a= offset, optimal= subsurf_optimal(ob); glPointSize( BIF_GetThemeValuef(TH_VERTEX_SIZE) ); bglBegin(GL_POINTS); for(eve= G.editMesh->verts.first; eve; eve= eve->next, a++) { if(eve->h==0) { cpack( index_to_framebuffer(a) ); if(optimal && eve->ssco) bglVertex3fv(eve->ssco); else bglVertex3fv(eve->co); } } bglEnd(); glPointSize(1.0); return a; } /* two options, edgecolors or black */ static int bbs_mesh_wire(Object *ob, int offset) { EditEdge *eed; Mesh *me= ob->data; DispList *dl= find_displist(&me->disp, DL_MESH); DispListMesh *dlm= NULL; int index, b, retval, optimal=0; if(dl) dlm= dl->mesh; optimal= subsurf_optimal(ob); if(dlm && optimal) { MEdge *medge= dlm->medge; MVert *mvert= dlm->mvert; // tuck original indices in vn for(b=0, eed= G.editMesh->edges.first; eed; eed= eed->next, b++) eed->vn= (EditVert *)(b+offset); retval= b+offset; glBegin(GL_LINES); for (b=0; btotedge; b++, medge++) { if(medge->flag & ME_EDGEDRAW) { eed= dlm->editedge[b]; if(eed && eed->h==0) { index= (int)eed->vn; cpack(index_to_framebuffer(index)); glVertex3fv(mvert[medge->v1].co); glVertex3fv(mvert[medge->v2].co); } } } glEnd(); } else { index= offset; cpack(0); glBegin(GL_LINES); for(eed= G.editMesh->edges.first; eed; eed= eed->next, index++) { if(eed->h==0) { cpack(index_to_framebuffer(index)); glVertex3fv(eed->v1->co); glVertex3fv(eed->v2->co); } } glEnd(); retval= index; } return retval; } /* two options, facecolors or black */ static int bbs_mesh_solid(Object *ob, int facecol) { int glmode, a; cpack(0); if(ob==G.obedit) { Mesh *me= ob->data; EditFace *efa; DispList *dl= find_displist(&me->disp, DL_MESH); DispListMesh *dlm= NULL; int b; if(dl) dlm= dl->mesh; a= 0; if(dlm && dlm->editface) { EditFace *prevefa; MFace *mface; efa= NULL; // tuck original indices in efa->prev for(b=1, efa= G.editMesh->faces.first; efa; efa= efa->next, b++) efa->prev= (EditFace *)(b); a= b+1; // correct return value, next loop excludes hidden faces for(b=0, mface= dlm->mface; btotface; b++, mface++) { if(mface->v3) { if(facecol) { efa= dlm->editface[b]; cpack(index_to_framebuffer((int)efa->prev)); } glBegin(mface->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(); } } if(facecol && (G.scene->selectmode & SCE_SELECT_FACE)) { glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE)); bglBegin(GL_POINTS); for(efa= G.editMesh->faces.first; efa; efa= efa->next) { if(efa->h==0) { if(efa->fgonf==EM_FGON); else { cpack(index_to_framebuffer((int)efa->prev)); bglVertex3fv(efa->cent); } } } bglEnd(); } for (prevefa= NULL, efa= G.editMesh->faces.first; efa; prevefa= efa, efa= efa->next) efa->prev= prevefa; } else { a= 1; glBegin(GL_QUADS); glmode= GL_QUADS; for(efa= G.editMesh->faces.first; efa; efa= efa->next, a++) { if(efa->h==0) { if(efa->v4) {if(glmode==GL_TRIANGLES) {glmode= GL_QUADS; glEnd(); glBegin(GL_QUADS);}} else {if(glmode==GL_QUADS) {glmode= GL_TRIANGLES; glEnd(); glBegin(GL_TRIANGLES);}} if(facecol) { int i= index_to_framebuffer(a); cpack(i); } glVertex3fv(efa->v1->co); glVertex3fv(efa->v2->co); glVertex3fv(efa->v3->co); if(efa->v4) glVertex3fv(efa->v4->co); } } glEnd(); } if(facecol) return a; } else { Mesh *me= ob->data; MVert *mvert; MFace *mface; TFace *tface; DispList *dl; float *extverts=NULL; int a, totface, hastface, i; mvert= me->mvert; mface= me->mface; tface= me->tface; hastface = (me->tface != NULL); totface= me->totface; dl= find_displist(&ob->disp, DL_VERTS); if(dl) extverts= dl->verts; glBegin(GL_QUADS); glmode= GL_QUADS; for(a=0; av3) { if(facecol) { if(hastface && tface->flag & TF_HIDE) continue; i= index_to_framebuffer(a+1); cpack(i); } if(mface->v4) {if(glmode==GL_TRIANGLES) {glmode= GL_QUADS; glEnd(); glBegin(GL_QUADS);}} else {if(glmode==GL_QUADS) {glmode= GL_TRIANGLES; glEnd(); glBegin(GL_TRIANGLES);}} if(extverts) { glVertex3fv( extverts+3*mface->v1 ); glVertex3fv( extverts+3*mface->v2 ); glVertex3fv( extverts+3*mface->v3 ); if(mface->v4) glVertex3fv( extverts+3*mface->v4 ); } else { glVertex3fv( (mvert+mface->v1)->co ); glVertex3fv( (mvert+mface->v2)->co ); glVertex3fv( (mvert+mface->v3)->co ); if(mface->v4) glVertex3fv( (mvert+mface->v4)->co ); } } } glEnd(); } return 1; } void draw_object_backbufsel(Object *ob) { extern int em_solidoffs, em_wireoffs, em_vertoffs; // let linker solve it... from editmesh_mods.c mymultmatrix(ob->obmat); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); switch( ob->type) { case OB_MESH: if(G.obedit) { em_solidoffs= bbs_mesh_solid(ob, G.scene->selectmode & SCE_SELECT_FACE); bglPolygonOffset(1.0); // we draw edges always, for loop (select) tools em_wireoffs= bbs_mesh_wire(ob, em_solidoffs); if(G.scene->selectmode & SCE_SELECT_VERTEX) em_vertoffs= bbs_mesh_verts(ob, em_wireoffs); else em_vertoffs= em_wireoffs; bglPolygonOffset(0.0); } else bbs_mesh_solid(ob, 1); // 1= facecol, faceselect break; case OB_CURVE: case OB_SURF: break; } myloadmatrix(G.vd->viewmat); }