4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, full recode and added functions
25 * ***** END GPL LICENSE BLOCK *****
35 #include "MEM_guardedalloc.h"
37 #include "IMB_imbuf.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_boid_types.h"
44 #include "DNA_camera_types.h"
45 #include "DNA_curve_types.h"
46 #include "DNA_constraint_types.h" // for drawing constraint
47 #include "DNA_effect_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_meta_types.h"
54 #include "DNA_modifier_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_object_force.h"
57 #include "DNA_object_fluidsim.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_screen_types.h"
62 #include "DNA_smoke_types.h"
63 #include "DNA_userdef_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
67 #include "BLI_blenlib.h"
69 #include "BLI_editVert.h"
70 #include "BLI_edgehash.h"
73 #include "BKE_anim.h" //for the where_on_path function
74 #include "BKE_curve.h"
75 #include "BKE_constraint.h" // for the get_constraint_target function
76 #include "BKE_DerivedMesh.h"
77 #include "BKE_deform.h"
78 #include "BKE_displist.h"
79 #include "BKE_effect.h"
81 #include "BKE_global.h"
82 #include "BKE_image.h"
84 #include "BKE_lattice.h"
86 #include "BKE_material.h"
87 #include "BKE_mball.h"
88 #include "BKE_modifier.h"
89 #include "BKE_object.h"
90 #include "BKE_paint.h"
91 #include "BKE_particle.h"
92 #include "BKE_pointcache.h"
93 #include "BKE_property.h"
94 #include "BKE_softbody.h"
95 #include "BKE_smoke.h"
97 #include "BKE_utildefines.h"
98 #include "smoke_API.h"
101 #include "BIF_glutil.h"
103 #include "GPU_draw.h"
104 #include "GPU_material.h"
105 #include "GPU_extensions.h"
106 #include "gpu_buffers.h"
109 #include "ED_particle.h"
110 #include "ED_screen.h"
111 #include "ED_types.h"
114 #include "UI_resources.h"
115 #include "UI_interface_icons.h"
118 #include "wm_subwindow.h"
121 #include "view3d_intern.h" // own include
124 /* this condition has been made more complex since editmode can draw textures */
125 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
126 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
127 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
129 #define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
130 ( (sce->toolsettings->selectmode & SCE_SELECT_FACE) && \
131 (vd->drawtype<=OB_SOLID) && \
132 (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
135 static void draw_bounding_volume(Scene *scene, Object *ob);
137 static void drawcube_size(float size);
138 static void drawcircle_size(float size);
139 static void draw_empty_sphere(float size);
140 static void draw_empty_cone(float size);
143 /* ************* only use while object drawing **************
144 * or after running ED_view3d_init_mats_rv3d
146 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr, int local)
148 RegionView3D *rv3d= ar->regiondata;
149 float fx, fy, vec4[4];
153 /* clipplanes in eye space */
154 if(rv3d->rflag & RV3D_CLIPPING) {
155 if(view3d_test_clipping(rv3d, vec, local))
162 mul_m4_v4(rv3d->persmatob, vec4);
164 /* clipplanes in window space */
165 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
166 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
168 if( fx>0 && fx<ar->winx) {
170 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
172 if(fy>0.0 && fy< (float)ar->winy) {
173 adr[0]= (short)floor(fx);
174 adr[1]= (short)floor(fy);
180 /* only use while object drawing */
181 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
183 RegionView3D *rv3d= ar->regiondata;
184 float fx, fy, vec4[4];
191 mul_m4_v4(rv3d->persmatob, vec4);
193 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
194 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
196 if( fx>-32700 && fx<32700) {
198 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
200 if(fy>-32700.0 && fy<32700.0) {
201 adr[0]= (short)floor(fx);
202 adr[1]= (short)floor(fy);
208 /* ************************ */
210 /* check for glsl drawing */
212 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
214 if(!GPU_glsl_support())
218 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
220 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
223 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt >= OB_SHADED);
226 static int check_material_alpha(Base *base, Mesh *me, int glsl)
228 if(base->flag & OB_FROMDUPLI)
237 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
241 static unsigned int colortab[24]=
242 {0x0, 0xFF88FF, 0xFFBBFF,
243 0x403000, 0xFFFF88, 0xFFFFBB,
244 0x104040, 0x66CCCC, 0x77CCCC,
245 0x104010, 0x55BB55, 0x66FF66,
250 static float cube[8][3] = {
261 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
262 /* 32 values of sin function (still same result!) */
263 static float sinval[32] = {
298 /* 32 values of cos function (still same result!) */
299 static float cosval[32] ={
334 /* flag is same as for draw_object */
335 void drawaxes(float size, int flag, char drawtype)
338 float v1[3]= {0.0, 0.0, 0.0};
339 float v2[3]= {0.0, 0.0, 0.0};
340 float v3[3]= {0.0, 0.0, 0.0};
342 if(G.f & G_RENDER_SHADOW)
348 for (axis=0; axis<3; axis++) {
349 float v1[3]= {0.0, 0.0, 0.0};
350 float v2[3]= {0.0, 0.0, 0.0};
362 case OB_SINGLE_ARROW:
365 /* in positive z direction only */
372 glBegin(GL_TRIANGLES);
374 v2[0]= size*0.035; v2[1] = size*0.035;
375 v3[0]= size*-0.035; v3[1] = size*0.035;
376 v2[2]= v3[2]= size*0.75;
378 for (axis=0; axis<4; axis++) {
400 drawcircle_size(size);
403 case OB_EMPTY_SPHERE:
404 draw_empty_sphere(size);
408 draw_empty_cone(size);
413 for (axis=0; axis<3; axis++) {
414 float v1[3]= {0.0, 0.0, 0.0};
415 float v2[3]= {0.0, 0.0, 0.0};
416 int arrow_axis= (axis==0)?1:0;
425 v1[arrow_axis]= -size*0.125;
429 v1[arrow_axis]= size*0.125;
435 v2[axis]+= size*0.125;
437 // patch for 3d cards crashing on glSelect for text drawing (IBM)
438 if((flag & DRAW_PICKING) == 0) {
440 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "x", 0);
442 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "y", 0);
444 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "z", 0);
451 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
453 float vec[3], vx[3], vy[3];
456 VECCOPY(vx, tmat[0]);
457 VECCOPY(vy, tmat[1]);
462 for(a=0; a<tot; a++) {
463 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
464 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
465 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
471 /* circle for object centers, special_color is for library or ob users */
472 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int selstate, int special_color)
476 size= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
477 size*= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
479 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
480 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
484 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
486 else glColor4ub(0x55, 0xCC, 0xCC, 155);
489 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
490 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
491 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
493 drawcircball(GL_POLYGON, vec, size, rv3d->viewinv);
495 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
496 drawcircball(GL_LINE_LOOP, vec, size, rv3d->viewinv);
499 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
502 /* *********** text drawing for object/particles/armature ************* */
504 static ListBase CachedText[3];
505 static int CachedTextLevel= 0;
507 typedef struct ViewCachedString {
508 struct ViewCachedString *next, *prev;
509 float vec[3], col[4];
515 void view3d_cached_text_draw_begin()
517 ListBase *strings= &CachedText[CachedTextLevel];
518 strings->first= strings->last= NULL;
522 void view3d_cached_text_draw_add(float x, float y, float z, char *str, short xoffs)
524 ListBase *strings= &CachedText[CachedTextLevel-1];
525 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString), "ViewCachedString");
527 BLI_addtail(strings, vos);
528 BLI_strncpy(vos->str, str, 128);
532 glGetFloatv(GL_CURRENT_COLOR, vos->col);
536 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
538 RegionView3D *rv3d= ar->regiondata;
539 ListBase *strings= &CachedText[CachedTextLevel-1];
540 ViewCachedString *vos;
543 /* project first and test */
544 for(vos= strings->first; vos; vos= vos->next) {
546 mul_m4_v3(mat, vos->vec);
547 view3d_project_short_clip(ar, vos->vec, vos->mval, 0);
548 if(vos->mval[0]!=IS_CLIPPED)
553 if(rv3d->rflag & RV3D_CLIPPING)
555 glDisable(GL_CLIP_PLANE0+a);
558 ED_region_pixelspace(ar);
561 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
565 for(vos= strings->first; vos; vos= vos->next) {
566 if(vos->mval[0]!=IS_CLIPPED) {
567 glColor3fv(vos->col);
568 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], (depth_write)? 0.0f: 2.0f, vos->str);
573 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
579 if(rv3d->rflag & RV3D_CLIPPING)
581 glEnable(GL_CLIP_PLANE0+a);
585 BLI_freelistN(strings);
590 /* ******************** primitive drawing ******************* */
592 static void drawcube(void)
595 glBegin(GL_LINE_STRIP);
596 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
597 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
598 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
601 glBegin(GL_LINE_STRIP);
602 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
605 glBegin(GL_LINE_STRIP);
606 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
609 glBegin(GL_LINE_STRIP);
610 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
614 /* draws a cube on given the scaling of the cube, assuming that
615 * all required matrices have been set (used for drawing empties)
617 static void drawcube_size(float size)
619 glBegin(GL_LINE_STRIP);
620 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
621 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
622 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
625 glBegin(GL_LINE_STRIP);
626 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
629 glBegin(GL_LINE_STRIP);
630 glVertex3f(-size,size,size); glVertex3f(size,size,size);
633 glBegin(GL_LINE_STRIP);
634 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
638 /* this is an unused (old) cube-drawing function based on a given size */
640 static void drawcube_size(float *size)
644 glScalef(size[0], size[1], size[2]);
647 glBegin(GL_LINE_STRIP);
648 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
649 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
650 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
653 glBegin(GL_LINE_STRIP);
654 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
657 glBegin(GL_LINE_STRIP);
658 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
661 glBegin(GL_LINE_STRIP);
662 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
669 static void drawshadbuflimits(Lamp *la, float mat[][4])
671 float sta[3], end[3], lavec[3];
673 lavec[0]= -mat[2][0];
674 lavec[1]= -mat[2][1];
675 lavec[2]= -mat[2][2];
678 sta[0]= mat[3][0]+ la->clipsta*lavec[0];
679 sta[1]= mat[3][1]+ la->clipsta*lavec[1];
680 sta[2]= mat[3][2]+ la->clipsta*lavec[2];
682 end[0]= mat[3][0]+ la->clipend*lavec[0];
683 end[1]= mat[3][1]+ la->clipend*lavec[1];
684 end[2]= mat[3][2]+ la->clipend*lavec[2];
687 glBegin(GL_LINE_STRIP);
702 static void spotvolume(float *lvec, float *vvec, float inp)
704 /* camera is at 0,0,0 */
705 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
708 normalize_v3(vvec); /* is this the correct vector ? */
710 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
711 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
715 /* now we've got two equations: one of a cone and one of a plane, but we have
716 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
718 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
719 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
721 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
728 angle = saacos(plane[2])/2.0;
737 quat_to_mat3(mat1,q);
739 /* rotate lamp vector now over acos(inp) degrees */
747 si = sqrt(1-inp*inp);
753 mul_m3_m3m3(mat3,mat2,mat1);
757 mul_m3_m3m3(mat4,mat2,mat1);
760 mul_m3_m3m3(mat2,mat1,mat3);
761 mul_m3_v3(mat2,lvec);
762 mul_m3_m3m3(mat2,mat1,mat4);
763 mul_m3_v3(mat2,vvec);
768 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
771 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
772 float pixsize, lampsize;
773 float imat[4][4], curcol[4];
776 if(G.f & G_RENDER_SHADOW)
781 /* we first draw only the screen aligned & fixed scale stuff */
783 wmLoadMatrix(rv3d->viewmat);
785 /* lets calculate the scale: */
786 pixsize= rv3d->persmat[0][3]*ob->obmat[3][0]+ rv3d->persmat[1][3]*ob->obmat[3][1]+ rv3d->persmat[2][3]*ob->obmat[3][2]+ rv3d->persmat[3][3];
787 pixsize*= rv3d->pixsize;
788 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
790 /* and view aligned matrix: */
791 copy_m4_m4(imat, rv3d->viewinv);
792 normalize_v3(imat[0]);
793 normalize_v3(imat[1]);
796 glGetFloatv(GL_CURRENT_COLOR, curcol);
801 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
802 else glColor4ub(0x77, 0xCC, 0xCC, 155);
806 VECCOPY(vec, ob->obmat[3]);
808 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
810 drawcircball(GL_POLYGON, vec, lampsize, imat);
817 circrad = 3.0f*lampsize;
818 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
822 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
823 if (la->type!=LA_HEMI) {
824 if ((la->mode & LA_SHAD_RAY) ||
825 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
827 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
831 /* draw the pretty sun rays */
832 if(la->type==LA_SUN) {
833 float v1[3], v2[3], mat[3][3];
836 /* setup a 45 degree rotation matrix */
837 vec_rot_to_mat3( mat,imat[2], M_PI/4.0f);
840 VECCOPY(v1, imat[0]);
841 mul_v3_fl(v1, circrad*1.2f);
842 VECCOPY(v2, imat[0]);
843 mul_v3_fl(v2, circrad*2.5f);
846 glTranslatef(vec[0], vec[1], vec[2]);
851 for (axis=0; axis<8; axis++) {
859 glTranslatef(-vec[0], -vec[1], -vec[2]);
863 if (la->type==LA_LOCAL) {
864 if(la->mode & LA_SPHERE) {
865 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
867 /* yafray: for photonlight also draw lightcone as for spot */
870 glPopMatrix(); /* back in object space */
871 vec[0]= vec[1]= vec[2]= 0.0f;
873 if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
874 lvec[0]=lvec[1]= 0.0;
876 x = rv3d->persmat[0][2];
877 y = rv3d->persmat[1][2];
878 z = rv3d->persmat[2][2];
879 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
880 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
881 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
883 y = cos( M_PI*la->spotsize/360.0 );
884 spotvolume(lvec, vvec, y);
893 /* draw the angled sides of the cone */
894 glBegin(GL_LINE_STRIP);
900 z = x*sqrt(1.0 - y*y);
903 /* draw the circle/square at the end of the cone */
904 glTranslatef(0.0, 0.0 , x);
905 if(la->mode & LA_SQUARE) {
909 glBegin(GL_LINE_LOOP);
919 else circ(0.0, 0.0, fabs(z));
921 /* draw the circle/square representing spotbl */
922 if(la->type==LA_SPOT) {
923 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
924 /* hide line if it is zero size or overlaps with outer border,
925 previously it adjusted to always to show it but that seems
926 confusing because it doesn't show the actual blend size */
927 if (spotblcirc != 0 && spotblcirc != fabs(z))
928 circ(0.0, 0.0, spotblcirc);
932 else if ELEM(la->type, LA_HEMI, LA_SUN) {
934 /* draw the line from the circle along the dist */
935 glBegin(GL_LINE_STRIP);
942 if(la->type==LA_HEMI) {
943 /* draw the hemisphere curves */
944 short axis, steps, dir;
945 float outdist, zdist, mul;
946 vec[0]=vec[1]=vec[2]= 0.0;
947 outdist = 0.14; mul = 1.4; dir = 1;
950 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
951 for (axis=0; axis<4; axis++) {
952 float v[3]= {0.0, 0.0, 0.0};
955 glBegin(GL_LINE_STRIP);
957 for (steps=0; steps<6; steps++) {
958 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
959 /* make the arcs start at the edge of the energy circle */
960 if (steps == 0) v[0] = dir*circrad;
961 else v[0] = v[0] + dir*(steps*outdist);
962 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
963 /* make the arcs start at the edge of the energy circle */
964 if (steps == 0) v[1] = dir*circrad;
965 else v[1] = v[1] + dir*(steps*outdist);
968 v[2] = v[2] - steps*zdist;
976 /* flip the direction */
980 } else if(la->type==LA_AREA) {
982 if(la->area_shape==LA_AREA_SQUARE)
983 fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
984 else if(la->area_shape==LA_AREA_RECT)
985 fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
987 glBegin(GL_LINE_STRIP);
988 glVertex3f(0.0,0.0,-circrad);
989 glVertex3f(0.0,0.0,-la->dist);
993 /* and back to viewspace */
994 wmLoadMatrix(rv3d->viewmat);
995 VECCOPY(vec, ob->obmat[3]);
999 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1000 drawshadbuflimits(la, ob->obmat);
1003 UI_GetThemeColor4ubv(TH_LAMP, col);
1004 glColor4ub(col[0], col[1], col[2], col[3]);
1008 if (vec[2]>0) vec[2] -= circrad;
1009 else vec[2] += circrad;
1011 glBegin(GL_LINE_STRIP);
1023 glDisable(GL_BLEND);
1025 /* restore for drawing extra stuff */
1030 static void draw_limit_line(float sta, float end, unsigned int col)
1033 glVertex3f(0.0, 0.0, -sta);
1034 glVertex3f(0.0, 0.0, -end);
1040 glVertex3f(0.0, 0.0, -sta);
1041 glVertex3f(0.0, 0.0, -end);
1047 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1048 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1049 static void draw_focus_cross(float dist, float size)
1052 glVertex3f(-size, 0.f, -dist);
1053 glVertex3f(size, 0.f, -dist);
1054 glVertex3f(0.f, -size, -dist);
1055 glVertex3f(0.f, size, -dist);
1059 /* flag similar to draw_object() */
1060 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1062 /* a standing up pyramid with (0,0,0) as top */
1065 float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1068 if(G.f & G_RENDER_SHADOW)
1073 glDisable(GL_LIGHTING);
1074 glDisable(GL_CULL_FACE);
1076 if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1077 facx= 0.5*cam->ortho_scale*1.28;
1078 facy= 0.5*cam->ortho_scale*1.024;
1079 depth= -cam->clipsta-0.1;
1083 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1085 depth= - fac*cam->lens/16.0;
1090 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
1091 vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1092 vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1093 vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1094 vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1096 glBegin(GL_LINE_LOOP);
1097 glVertex3fv(vec[1]);
1098 glVertex3fv(vec[2]);
1099 glVertex3fv(vec[3]);
1100 glVertex3fv(vec[4]);
1104 if(rv3d->persp>=2 && ob==v3d->camera) return;
1106 glBegin(GL_LINE_STRIP);
1107 glVertex3fv(vec[2]);
1108 glVertex3fv(vec[0]);
1109 glVertex3fv(vec[1]);
1110 glVertex3fv(vec[4]);
1111 glVertex3fv(vec[0]);
1112 glVertex3fv(vec[3]);
1120 /* draw an outline arrow for inactive cameras and filled
1121 * for active cameras. We actually draw both outline+filled
1122 * for active cameras so the wire can be seen side-on */
1124 if (i==0) glBegin(GL_LINE_LOOP);
1125 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1128 vec[0][0]= -0.7*cam->drawsize;
1129 vec[0][1]= 1.1*cam->drawsize;
1130 glVertex3fv(vec[0]);
1133 vec[0][1]= 1.8*cam->drawsize;
1134 glVertex3fv(vec[0]);
1136 vec[0][0]= 0.7*cam->drawsize;
1137 vec[0][1]= 1.1*cam->drawsize;
1138 glVertex3fv(vec[0]);
1144 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1145 wmLoadMatrix(rv3d->viewmat);
1146 copy_m4_m4(vec, ob->obmat);
1150 swap_m4m4(rv3d->persmat, tmat);
1151 wmGetSingleMatrix(rv3d->persmat);
1153 if(cam->flag & CAM_SHOWLIMITS) {
1154 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1155 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1156 draw_focus_cross(dof_camera(ob), cam->drawsize);
1160 if(cam->flag & CAM_SHOWMIST)
1161 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1163 swap_m4m4(rv3d->persmat, tmat);
1168 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1170 BPoint *bp = lt->def;
1171 float *co = dl?dl->verts:NULL;
1174 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1175 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1176 bglBegin(GL_POINTS);
1178 for(w=0; w<lt->pntsw; w++) {
1179 int wxt = (w==0 || w==lt->pntsw-1);
1180 for(v=0; v<lt->pntsv; v++) {
1181 int vxt = (v==0 || v==lt->pntsv-1);
1182 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1183 int uxt = (u==0 || u==lt->pntsu-1);
1184 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1186 if((bp->f1 & SELECT)==sel) {
1187 bglVertex3fv(dl?co:bp->vec);
1199 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1201 Object *obedit= vc->obedit;
1202 Lattice *lt= obedit->data;
1203 BPoint *bp = lt->editlatt->def;
1204 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1205 float *co = dl?dl->verts:NULL;
1206 int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1207 short s[2] = {IS_CLIPPED, 0};
1209 ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1211 for (i=0; i<N; i++, bp++, co+=3) {
1213 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1214 if (s[0] != IS_CLIPPED)
1215 func(userData, bp, s[0], s[1]);
1220 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1222 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1226 MDeformWeight *mdw= ED_vgroup_weight_get (lt->dvert+index, use_wcol-1);
1228 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1234 glVertex3fv(&dl->verts[index*3]);
1236 glVertex3fv(lt->def[index].vec);
1240 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1241 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1243 Lattice *lt= ob->data;
1248 /* now we default make displist, this will modifiers work for non animated case */
1249 if(ob->disp.first==NULL)
1250 lattice_calc_modifiers(scene, ob);
1251 dl= find_displist(&ob->disp, DL_VERTS);
1256 if(ob->defbase.first && lt->dvert) {
1257 use_wcol= ob->actdef;
1258 glShadeModel(GL_SMOOTH);
1262 if(lt->editlatt) lt= lt->editlatt;
1265 for(w=0; w<lt->pntsw; w++) {
1266 int wxt = (w==0 || w==lt->pntsw-1);
1267 for(v=0; v<lt->pntsv; v++) {
1268 int vxt = (v==0 || v==lt->pntsv-1);
1269 for(u=0; u<lt->pntsu; u++) {
1270 int uxt = (u==0 || u==lt->pntsu-1);
1272 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1273 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1274 drawlattice__point(lt, dl, u, v, w, use_wcol);
1276 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1277 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1278 drawlattice__point(lt, dl, u, v, w, use_wcol);
1280 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1281 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1282 drawlattice__point(lt, dl, u, v, w, use_wcol);
1289 /* restoration for weight colors */
1291 glShadeModel(GL_FLAT);
1293 if( ((Lattice *)ob->data)->editlatt ) {
1294 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1296 lattice_draw_verts(lt, dl, 0);
1297 lattice_draw_verts(lt, dl, 1);
1299 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1303 /* ***************** ******************** */
1305 /* Note! - foreach funcs should be called while drawing or directly after
1306 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1307 * but would not give correct results with dupli's for eg. which dont
1308 * use the object matrix in the useual way */
1309 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1311 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1312 EditVert *eve = EM_get_vert_for_index(index);
1315 short s[2]= {IS_CLIPPED, 0};
1317 if (data->clipVerts) {
1318 view3d_project_short_clip(data->vc.ar, co, s, 1);
1320 view3d_project_short_noclip(data->vc.ar, co, s);
1323 if (s[0]!=IS_CLIPPED)
1324 data->func(data->userData, eve, s[0], s[1], index);
1328 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1330 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1331 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1335 data.userData = userData;
1336 data.clipVerts = clipVerts;
1339 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1341 EM_init_index_arrays(vc->em, 1, 0, 0);
1342 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1343 EM_free_index_arrays();
1348 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1350 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1351 EditEdge *eed = EM_get_edge_for_index(index);
1355 if (data->clipVerts==1) {
1356 view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1357 view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1359 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1360 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1362 if (data->clipVerts==2) {
1363 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1364 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1369 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1373 void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
1375 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1376 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1380 data.userData = userData;
1381 data.clipVerts = clipVerts;
1384 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1386 EM_init_index_arrays(vc->em, 0, 1, 0);
1387 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1388 EM_free_index_arrays();
1393 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1395 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1396 EditFace *efa = EM_get_face_for_index(index);
1399 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1400 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1402 data->func(data->userData, efa, s[0], s[1], index);
1406 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1408 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1409 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1413 data.userData = userData;
1416 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1418 EM_init_index_arrays(vc->em, 0, 0, 1);
1419 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1420 EM_free_index_arrays();
1425 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1427 Curve *cu= vc->obedit->data;
1428 short s[2] = {IS_CLIPPED, 0};
1432 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1434 for (nu= cu->editnurb->first; nu; nu=nu->next) {
1435 if(nu->type == CU_BEZIER) {
1436 for (i=0; i<nu->pntsu; i++) {
1437 BezTriple *bezt = &nu->bezt[i];
1441 if(cu->drawflag & CU_HIDE_HANDLES) {
1442 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1443 if (s[0] != IS_CLIPPED)
1444 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1446 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1447 if (s[0] != IS_CLIPPED)
1448 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1449 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1450 if (s[0] != IS_CLIPPED)
1451 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1452 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1453 if (s[0] != IS_CLIPPED)
1454 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1460 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1461 BPoint *bp = &nu->bp[i];
1464 view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1465 if (s[0] != IS_CLIPPED)
1466 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1473 /* ************** DRAW MESH ****************** */
1475 /* First section is all the "simple" draw routines,
1476 * ones that just pass some sort of primitive to GL,
1477 * with perhaps various options to control lighting,
1480 * These routines should not have user interface related
1484 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1486 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1487 EditFace *efa = EM_get_face_for_index(index);
1489 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1491 glVertex3f( cent[0] + no[0]*ts->normalsize,
1492 cent[1] + no[1]*ts->normalsize,
1493 cent[2] + no[2]*ts->normalsize);
1496 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1499 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1503 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1505 EditFace *efa = EM_get_face_for_index(index);
1506 int sel = *((int*) userData);
1508 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1512 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1514 bglBegin(GL_POINTS);
1515 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1519 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1521 Scene *scene= (Scene *)userData;
1522 ToolSettings *ts= scene->toolsettings;
1523 EditVert *eve = EM_get_vert_for_index(index);
1529 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1530 co[1] + no_f[1]*ts->normalsize,
1531 co[2] + no_f[2]*ts->normalsize);
1533 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1534 co[1] + no_s[1]*ts->normalsize/32767.0f,
1535 co[2] + no_s[2]*ts->normalsize/32767.0f);
1539 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1542 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1546 /* Draw verts with color set based on selection */
1547 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1549 struct { int sel; EditVert *eve_act; } * data = userData;
1550 EditVert *eve = EM_get_vert_for_index(index);
1552 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1553 /* draw active larger - need to stop/start point drawing for this :/ */
1554 if (eve==data->eve_act) {
1555 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1556 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1561 bglBegin(GL_POINTS);
1565 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1567 bglBegin(GL_POINTS);
1574 /* disabled because it crashes combined with e.g. subsurf modifier,
1575 * the derivedmesh can't be assumed to be an EditMeshDerivedMesh,
1576 * nor should this struct be copied around, it should be defined in
1577 * a single place only to avoid them getting out of sync */
1579 /* originally defined in DerivedMesh.c */
1584 float (*vertexCos)[3];
1585 float (*vertexNos)[3];
1586 float (*faceNos)[3];
1587 } EditMeshDerivedMesh;
1590 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1592 struct { int sel; EditVert *eve_act; } data;
1593 //GPUBuffer *buffer;
1596 data.eve_act = eve_act;
1599 /* first come the unselected vertices, then the selected */
1600 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 );
1602 if( (varray = GPU_buffer_lock_stream( buffer )) && bglPointHack() == 0 ) {
1603 EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1606 int numverts = 0, numselected = 0;
1607 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END };
1608 GPU_buffer_unlock( buffer );
1609 GPU_interleaved_setup( buffer, datatype );
1610 varray = GPU_buffer_lock_stream( buffer );
1613 for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
1614 if (eve->h==0 && (eve->f&SELECT)==data.sel) {
1615 if (eve==data.eve_act) {
1616 if (emdm->vertexCos) {
1617 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],emdm->vertexCos[i]);
1620 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],eve->co);
1624 if (emdm->vertexCos) {
1625 VECCOPY(&varray[3*numverts],emdm->vertexCos[i]);
1627 VECCOPY(&varray[3*numverts],eve->co);
1634 GPU_buffer_unlock( buffer );
1635 glDrawArrays(GL_POINTS,0,numverts);
1636 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1637 glDrawArrays(GL_POINTS,dm->getNumVerts(dm),numselected);
1638 UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX);
1639 GPU_buffer_unbind();
1643 bglBegin(GL_POINTS);
1644 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1648 GPU_buffer_free( buffer, 0 );
1652 /* Draw edges with color set based on selection */
1653 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1655 EditEdge *eed = EM_get_edge_for_index(index);
1656 //unsigned char **cols = userData, *col;
1657 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1661 if (eed==data->eed_act) {
1662 glColor4ubv(data->actCol);
1664 if (eed->f&SELECT) {
1667 col = data->baseCol;
1669 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1670 if (col[3]==0) return 0;
1679 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1681 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1683 data.baseCol = baseCol;
1684 data.selCol = selCol;
1685 data.actCol = actCol;
1686 data.eed_act = eed_act;
1687 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1691 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1693 return EM_get_edge_for_index(index)->h==0;
1695 static void draw_dm_edges(DerivedMesh *dm)
1697 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1700 /* Draw edges with color interpolated based on selection */
1701 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1703 return EM_get_edge_for_index(index)->h==0;
1705 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1707 EditEdge *eed = EM_get_edge_for_index(index);
1708 unsigned char **cols = userData;
1709 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1710 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1712 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1713 col0[1] + (col1[1]-col0[1])*t,
1714 col0[2] + (col1[2]-col0[2])*t,
1715 col0[3] + (col1[3]-col0[3])*t);
1718 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1720 unsigned char *cols[2] = {baseCol, selCol};
1722 int elemsize = sizeof(float)*3+sizeof(unsigned char)*4;
1723 EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1724 EditMesh *em= emdm->em;
1725 unsigned char *varray;
1729 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 );
1730 if( (varray = GPU_buffer_lock_stream( buffer )) ) {
1733 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1734 GPU_buffer_unlock( buffer );
1735 GPU_interleaved_setup( buffer, datatype );
1736 varray = GPU_buffer_lock_stream( buffer );
1737 for (i=0,eed= em->edges.first; eed; i++,eed= eed->next) {
1739 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1740 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1742 if( emdm->vertexCos ) {
1743 VECCOPY(((float *)&varray[elemsize*numedges*2]),emdm->vertexCos[(int) eed->v1->tmp.l]);
1746 VECCOPY(((float *)&varray[elemsize*numedges*2]),eed->v1->co);
1748 QUATCOPY(&varray[elemsize*numedges*2+sizeof(float)*3],col0);
1749 if( emdm->vertexCos ) {
1750 VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),emdm->vertexCos[(int) eed->v2->tmp.l]);
1753 VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),eed->v2->co);
1755 QUATCOPY(&varray[elemsize*numedges*2+elemsize+sizeof(float)*3],col1);
1759 GPU_buffer_unlock( buffer );
1760 glDrawArrays(GL_LINES,0,numedges*2);
1761 GPU_buffer_unbind();
1765 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1768 GPU_buffer_free( buffer, 0 );
1772 /* Draw only seam edges */
1773 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1775 EditEdge *eed = EM_get_edge_for_index(index);
1777 return (eed->h==0 && eed->seam);
1779 static void draw_dm_edges_seams(DerivedMesh *dm)
1781 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1784 /* Draw only sharp edges */
1785 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1787 EditEdge *eed = EM_get_edge_for_index(index);
1789 return (eed->h==0 && eed->sharp);
1791 static void draw_dm_edges_sharp(DerivedMesh *dm)
1793 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1797 /* Draw faces with color set based on selection
1798 * return 2 for the active face so it renders with stipple enabled */
1799 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1801 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1802 EditFace *efa = EM_get_face_for_index(index);
1806 if (efa == data->efa_act) {
1807 glColor4ubv(data->cols[2]);
1808 return 2; /* stipple */
1810 col = data->cols[(efa->f&SELECT)?1:0];
1811 if (col[3]==0) return 0;
1819 /* also draws the active face */
1820 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
1822 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1823 //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1827 unsigned char *varray;
1828 unsigned char black[] = { 0, 0, 0, 0 };
1830 int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4);
1831 data.cols[0] = baseCol;
1832 data.cols[1] = selCol;
1833 data.cols[2] = actCol;
1834 data.efa_act = efa_act;
1837 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 );
1838 if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
1841 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1842 GPU_buffer_unlock( buffer );
1843 GPU_interleaved_setup( buffer, datatype );
1844 glShadeModel(GL_SMOOTH);
1845 varray = GPU_buffer_lock_stream( buffer );
1846 for (i=0,efa= efa_act; efa; i++,efa= efa->next) {
1847 int drawSmooth = (efa->flag & ME_SMOOTH);
1849 if (efa == data.efa_act) {
1852 col = data.cols[(efa->f&SELECT)?1:0];
1853 if (col[3]==0) draw = 0;
1860 if( prevdraw != draw && prevdraw != 0 && numfaces > 0) {
1862 glEnable(GL_POLYGON_STIPPLE);
1863 glPolygonStipple(stipple_quarttone);
1865 GPU_buffer_unlock( buffer );
1866 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
1868 glDisable(GL_POLYGON_STIPPLE);
1870 varray = GPU_buffer_lock_stream( buffer );
1876 /*if (emdm->vertexCos) {
1877 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1878 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1880 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1881 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1883 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1884 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1887 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1888 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1890 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1891 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1893 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1894 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1897 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1898 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1899 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1901 else if( draw == 1 ) {
1902 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1903 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1904 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1907 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1908 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1909 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1914 /*if (emdm->vertexCos) {
1915 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1916 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1918 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1919 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1921 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1922 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1925 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1926 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1928 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1929 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1931 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
1932 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1936 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1937 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1938 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1940 else if( draw == 1 ) {
1941 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1942 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1943 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1946 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1947 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1948 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1955 /*if (emdm->vertexCos) {
1956 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1957 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1959 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1960 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1962 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1963 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1966 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1967 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v1->no);
1969 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1970 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v2->no);
1972 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1973 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v3->no);
1977 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1978 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1979 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1981 else if( draw == 1 ) {
1982 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1983 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1984 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1987 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1988 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1989 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1994 /*if (emdm->vertexCos) {
1995 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1996 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1998 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1999 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
2001 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
2002 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
2005 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
2006 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v3->no);
2008 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
2009 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v4->no);
2011 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
2012 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v1->no);
2016 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
2017 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
2018 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
2020 else if( draw == 1 ) {
2021 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2022 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2023 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2026 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
2027 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
2028 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
2037 GPU_buffer_unlock( buffer );
2038 if( prevdraw != 0 && numfaces > 0) {
2040 glEnable(GL_POLYGON_STIPPLE);
2041 glPolygonStipple(stipple_quarttone);
2043 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2045 glDisable(GL_POLYGON_STIPPLE);
2048 GPU_buffer_unbind();
2050 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
2052 GPU_buffer_free( buffer, 0 );
2055 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2057 EditEdge *eed = EM_get_edge_for_index(index);
2059 if (eed->h==0 && eed->crease!=0.0) {
2060 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
2066 static void draw_dm_creases(DerivedMesh *dm)
2069 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2073 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2075 EditEdge *eed = EM_get_edge_for_index(index);
2077 if (eed->h==0 && eed->bweight!=0.0) {
2078 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2084 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2086 EditVert *eve = EM_get_vert_for_index(index);
2088 if (eve->h==0 && eve->bweight!=0.0) {
2089 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2093 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2095 ToolSettings *ts= scene->toolsettings;
2097 if (ts->selectmode & SCE_SELECT_VERTEX) {
2098 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2099 bglBegin(GL_POINTS);
2100 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2105 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2110 /* Second section of routines: Combine first sets to form fancy
2111 * drawing routines (for example rendering twice to get overlays).
2113 * Also includes routines that are basic drawing but are too
2114 * specialized to be split out (like drawing creases or measurements).
2117 /* EditMesh drawing routines*/
2119 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
2121 ToolSettings *ts= scene->toolsettings;
2124 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2126 for (sel=0; sel<2; sel++) {
2127 char col[4], fcol[4];
2130 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2131 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2133 for (pass=0; pass<2; pass++) {
2134 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2135 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2138 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2139 glDisable(GL_DEPTH_TEST);
2146 size = (size>2.1?size/2.0:size);
2147 fsize = (fsize>2.1?fsize/2.0:fsize);
2148 col[3] = fcol[3] = 100;
2150 col[3] = fcol[3] = 255;
2153 if(ts->selectmode & SCE_SELECT_VERTEX) {
2155 glColor4ubv((GLubyte *)col);
2156 draw_dm_verts(cageDM, sel, eve_act);
2159 if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
2161 glColor4ubv((GLubyte *)fcol);
2162 draw_dm_face_centers(cageDM, sel);
2166 glDisable(GL_BLEND);
2167 glEnable(GL_DEPTH_TEST);
2172 if(v3d->zbuf) glDepthMask(1);
2176 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2178 ToolSettings *ts= scene->toolsettings;
2180 unsigned char wireCol[4], selCol[4], actCol[4];
2182 /* since this function does transparant... */
2183 UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
2184 UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
2185 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
2187 /* when sel only is used, dont render wire, only selected, this is used for
2188 * textured draw mode when the 'edges' option is disabled */
2192 for (pass=0; pass<2; pass++) {
2193 /* show wires in transparant when no zbuf clipping for select */
2195 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2197 glDisable(GL_DEPTH_TEST);
2199 if (!sel_only) wireCol[3] = 85;
2205 if (!sel_only) wireCol[3] = 255;
2208 if(ts->selectmode == SCE_SELECT_FACE) {
2209 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2211 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2212 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2213 glShadeModel(GL_SMOOTH);
2214 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2215 glShadeModel(GL_FLAT);
2217 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2222 glColor4ubv(wireCol);
2223 draw_dm_edges(cageDM);
2228 glDisable(GL_BLEND);
2229 glEnable(GL_DEPTH_TEST);
2234 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2239 float v1[3], v2[3], v3[3], v4[3], x, y, z;
2241 char val[32]; /* Stores the measurement display text here */
2242 char conv_float[5]; /* Use a float conversion matching the grid size */
2243 float area, col[3]; /* area of the face, color of the text to draw */
2244 float grid= unit->system ? unit->scale_length : v3d->grid;
2245 int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2246 if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
2249 /* make the precision of the pronted value proportionate to the gridsize */
2252 strcpy(conv_float, "%.6f");
2253 else if (grid < 0.1f)
2254 strcpy(conv_float, "%.5f");
2255 else if (grid < 1.0f)
2256 strcpy(conv_float, "%.4f");
2257 else if (grid < 10.0f)
2258 strcpy(conv_float, "%.3f");
2260 strcpy(conv_float, "%.2f");
2263 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2264 glDisable(GL_DEPTH_TEST);
2266 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2268 if(me->drawflag & ME_DRAW_EDGELEN) {
2269 UI_GetThemeColor3fv(TH_TEXT, col);
2270 /* make color a bit more red */
2271 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2272 else col[0]= col[0]*0.7f + 0.3f;
2275 for(eed= em->edges.first; eed; eed= eed->next) {
2276 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2277 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2278 VECCOPY(v1, eed->v1->co);
2279 VECCOPY(v2, eed->v2->co);
2281 x= 0.5f*(v1[0]+v2[0]);
2282 y= 0.5f*(v1[1]+v2[1]);
2283 z= 0.5f*(v1[2]+v2[2]);
2285 if(v3d->flag & V3D_GLOBAL_STATS) {
2286 mul_m4_v3(ob->obmat, v1);
2287 mul_m4_v3(ob->obmat, v2);
2290 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2292 sprintf(val, conv_float, len_v3v3(v1, v2));
2294 view3d_cached_text_draw_add(x, y, z, val, 0);
2299 if(me->drawflag & ME_DRAW_FACEAREA) {
2300 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2302 UI_GetThemeColor3fv(TH_TEXT, col);
2303 /* make color a bit more green */
2304 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2305 else col[1]= col[1]*0.7f + 0.3f;
2308 for(efa= em->faces.first; efa; efa= efa->next) {
2309 if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
2310 VECCOPY(v1, efa->v1->co);
2311 VECCOPY(v2, efa->v2->co);
2312 VECCOPY(v3, efa->v3->co);
2314 VECCOPY(v4, efa->v4->co);
2316 if(v3d->flag & V3D_GLOBAL_STATS) {
2317 mul_m4_v3(ob->obmat, v1);
2318 mul_m4_v3(ob->obmat, v2);
2319 mul_m4_v3(ob->obmat, v3);
2320 if (efa->v4) mul_m4_v3(ob->obmat, v4);
2324 area= area_quad_v3(v1, v2, v3, v4);
2326 area = area_tri_v3(v1, v2, v3);
2329 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2331 sprintf(val, conv_float, area);
2333 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2338 if(me->drawflag & ME_DRAW_EDGEANG) {
2339 EditEdge *e1, *e2, *e3, *e4;
2341 UI_GetThemeColor3fv(TH_TEXT, col);
2342 /* make color a bit more blue */
2343 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2344 else col[2]= col[2]*0.7f + 0.3f;
2347 for(efa= em->faces.first; efa; efa= efa->next) {
2348 VECCOPY(v1, efa->v1->co);
2349 VECCOPY(v2, efa->v2->co);
2350 VECCOPY(v3, efa->v3->co);
2352 VECCOPY(v4, efa->v4->co);
2357 if(v3d->flag & V3D_GLOBAL_STATS) {
2358 mul_m4_v3(ob->obmat, v1);
2359 mul_m4_v3(ob->obmat, v2);
2360 mul_m4_v3(ob->obmat, v3);
2361 mul_m4_v3(ob->obmat, v4);
2367 if(efa->e4) e4= efa->e4; else e4= e3;
2369 /* Calculate the angles */
2371 if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2373 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v4, v1, v2)));
2374 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2375 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2377 if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2379 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v1, v2, v3)));
2380 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2381 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2383 if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2386 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v4)));
2388 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v1)));
2389 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2390 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2394 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2395 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v3, v4, v1)));
2396 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2397 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2404 glEnable(GL_DEPTH_TEST);
2405 bglPolygonOffset(rv3d->dist, 0.0f);
2409 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2411 EditFace *efa = EM_get_face_for_index(index);
2414 GPU_enable_material(efa->mat_nr+1, NULL);
2421 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2423 EditFace *efa = EM_get_face_for_index(index);
2428 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2430 Mesh *me = ob->data;
2431 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2432 EditEdge *eed_act = NULL;
2433 EditVert *eve_act = NULL;
2435 if (em->selected.last) {
2436 EditSelection *ese = em->selected.last;
2437 /* face is handeled above */
2438 /*if (ese->type == EDITFACE ) {
2439 efa_act = (EditFace *)ese->data;
2440 } else */ if ( ese->type == EDITEDGE ) {
2441 eed_act = (EditEdge *)ese->data;
2442 } else if ( ese->type == EDITVERT ) {
2443 eve_act = (EditVert *)ese->data;
2447 EM_init_index_arrays(em, 1, 1, 1);
2450 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2451 if(draw_glsl_material(scene, ob, v3d, dt)) {
2452 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2454 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2455 draw_em_fancy__setGLSLFaceOpts, NULL);
2456 GPU_disable_material();
2458 glFrontFace(GL_CCW);
2461 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2465 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2466 GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 );
2469 int i, curmat = 0, draw = 0;
2471 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2473 glEnable(GL_LIGHTING);
2474 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2476 if( finalDM->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
2477 int prevdraw = 0, prevmat = 0;
2479 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END };
2480 GPU_buffer_unlock( buffer );
2481 GPU_interleaved_setup( buffer, datatype );
2482 glShadeModel(GL_SMOOTH);
2483 varray = GPU_buffer_lock_stream( buffer );
2484 for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
2485 int drawSmooth = (efa->flag & ME_SMOOTH);
2487 curmat = efa->mat_nr+1;
2493 if( ((prevdraw != draw) || (curmat != prevmat)) && prevdraw != 0 && numfaces > 0) {
2495 glEnable(GL_POLYGON_STIPPLE);
2496 glPolygonStipple(stipple_quarttone);
2498 GPU_buffer_unlock( buffer );
2499 GPU_enable_material(prevmat, NULL);
2500 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2502 glDisable(GL_POLYGON_STIPPLE);
2504 varray = GPU_buffer_lock_stream( buffer );
2509 VECCOPY(&varray[numfaces*18],efa->v1->co);
2510 VECCOPY(&varray[numfaces*18+3],efa->n);
2512 VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2513 VECCOPY(&varray[numfaces*18+9],efa->n);
2515 VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2516 VECCOPY(&varray[numfaces*18+15],efa->n);
2519 VECCOPY(&varray[numfaces*18],efa->v3->co);
2520 VECCOPY(&varray[numfaces*18+3],efa->n);
2522 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2523 VECCOPY(&varray[numfaces*18+9],efa->n);
2525 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2526 VECCOPY(&varray[numfaces*18+15],efa->n);
2531 VECCOPY(&varray[numfaces*18],efa->v1->co);
2532 VECCOPY(&varray[numfaces*18+3],efa->v1->no);
2534 VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2535 VECCOPY(&varray[numfaces*18+9],efa->v2->no);
2537 VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2538 VECCOPY(&varray[numfaces*18+15],efa->v3->no);
2541 VECCOPY(&varray[numfaces*18],efa->v3->co);
2542 VECCOPY(&varray[numfaces*18+3],efa->v3->no);
2544 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2545 VECCOPY(&varray[numfaces*18+9],efa->v4->no);
2547 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2548 VECCOPY(&varray[numfaces*18+15],efa->v1->no);
2556 GPU_buffer_unlock( buffer );
2557 if( prevdraw != 0 && numfaces > 0) {
2559 glEnable(GL_POLYGON_STIPPLE);
2560 glPolygonStipple(stipple_quarttone);
2562 GPU_enable_material(prevmat, NULL);
2563 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2565 glDisable(GL_POLYGON_STIPPLE);
2568 GPU_buffer_unbind();
2571 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2573 GPU_buffer_free(buffer,0);
2575 glFrontFace(GL_CCW);
2576 glDisable(GL_LIGHTING);
2579 // Setup for drawing wire over, disable zbuffer
2580 // write to show selected edge wires better
2581 UI_ThemeColor(TH_WIRE);
2583 bglPolygonOffset(rv3d->dist, 1.0);
2587 if (cageDM!=finalDM) {
2588 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2589 finalDM->drawEdges(finalDM, 1);
2593 if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2594 unsigned char col1[4], col2[4], col3[4];
2596 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2597 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2598 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2601 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2603 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2604 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2607 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2609 glDisable(GL_BLEND);
2610 glDepthMask(1); // restore write in zbuffer
2611 } else if (efa_act) {
2612 /* even if draw faces is off it would be nice to draw the stipple face
2613 * Make all other faces zero alpha except for the active
2615 unsigned char col1[4], col2[4], col3[4];
2616 col1[3] = col2[3] = 0; /* dont draw */
2617 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2620 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2622 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2624 glDisable(GL_BLEND);
2625 glDepthMask(1); // restore write in zbuffer
2629 /* here starts all fancy draw-extra over */
2630 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2631 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2633 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2634 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2637 if(me->drawflag & ME_DRAWSEAMS) {
2638 UI_ThemeColor(TH_EDGE_SEAM);
2641 draw_dm_edges_seams(cageDM);
2647 if(me->drawflag & ME_DRAWSHARP) {
2648 UI_ThemeColor(TH_EDGE_SHARP);
2651 draw_dm_edges_sharp(cageDM);
2657 if(me->drawflag & ME_DRAWCREASES) {
2658 draw_dm_creases(cageDM);
2660 if(me->drawflag & ME_DRAWBWEIGHTS) {
2661 draw_dm_bweights(scene, cageDM);
2664 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2667 // XXX retopo_matrix_update(v3d);
2669 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2671 if(me->drawflag & ME_DRAWNORMALS) {
2672 UI_ThemeColor(TH_NORMAL);
2673 draw_dm_face_normals(scene, cageDM);
2675 if(me->drawflag & ME_DRAW_VNORMALS) {
2676 UI_ThemeColor(TH_NORMAL);
2677 draw_dm_vert_normals(scene, cageDM);
2680 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2681 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2686 bglPolygonOffset(rv3d->dist, 0.0);
2687 GPU_disable_material();
2690 EM_free_index_arrays();
2693 /* Mesh drawing routines */
2695 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2698 if(v3d->transp==0) { // not when we draw the transparent pass
2702 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2703 drawFacesSolid() doesn't draw the transparent faces */
2704 if(ob->dtx & OB_DRAWTRANSP) {
2705 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2706 dm->drawFacesSolid(dm, GPU_enable_material);
2707 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2708 GPU_disable_material();
2711 dm->drawEdges(dm, 0);
2719 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2725 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2727 Object *ob= base->object;
2728 Mesh *me = ob->data;
2729 Material *ma= give_current_material(ob, 1);
2730 int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2732 int totvert, totedge, totface;
2734 DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2739 if (ob->dtx&OB_DRAWWIRE) {
2740 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2743 totvert = dm->getNumVerts(dm);
2744 totedge = dm->getNumEdges(dm);
2745 totface = dm->getNumFaces(dm);
2747 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2749 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2751 // Unwanted combination.
2752 if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2754 if(dt==OB_BOUNDBOX) {
2755 draw_bounding_volume(scene, ob);
2757 else if(hasHaloMat || (totface==0 && totedge==0)) {
2762 else if(dt==OB_WIRE || totface==0) {
2763 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2765 else if( (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2766 CHECK_OB_DRAWTEXTURE(v3d, dt))
2768 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2770 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2771 draw_mesh_object_outline(v3d, ob, dm);
2774 if(draw_glsl_material(scene, ob, v3d, dt)) {
2775 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2777 dm->drawFacesGLSL(dm, GPU_enable_material);
2778 // if(get_ob_property(ob, "Text"))
2779 // XXX draw_mesh_text(ob, 1);
2780 GPU_disable_material();
2782 glFrontFace(GL_CCW);
2785 draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2789 if(base->flag & SELECT)
2790 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2792 UI_ThemeColor(TH_WIRE);
2794 dm->drawLooseEdges(dm);
2797 else if(dt==OB_SOLID) {
2798 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2799 draw_mesh_object_outline(v3d, ob, dm);
2801 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2803 glEnable(GL_LIGHTING);
2804 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2806 dm->drawFacesSolid(dm, GPU_enable_material);
2807 GPU_disable_material();
2809 glFrontFace(GL_CCW);
2810 glDisable(GL_LIGHTING);
2812 if(base->flag & SELECT) {
2813 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2815 UI_ThemeColor(TH_WIRE);
2817 dm->drawLooseEdges(dm);
2819 else if(dt==OB_SHADED) {
2820 int do_draw= 1; /* to resolve all G.f settings below... */
2824 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2825 /* enforce default material settings */
2826 GPU_enable_material(0, NULL);
2828 /* but set default spec */
2829 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2830 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2831 glColor3ub(120, 120, 120);
2832 glDisable(GL_COLOR_MATERIAL);
2834 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2835 glEnable(GL_LIGHTING);
2836 glEnable(GL_COLOR_MATERIAL);
2838 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2839 glDisable(GL_COLOR_MATERIAL);
2840 glDisable(GL_LIGHTING);
2842 GPU_disable_material();
2844 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2846 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2848 glColor3f(1.0f, 1.0f, 1.0f);
2849 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2855 dl = ob->disp.first;
2856 if (!dl || !dl->col1) {
2857 /* release and reload derivedmesh because it might be freed in
2858 shadeDispList due to a different datamask */
2860 shadeDispList(scene, base);
2861 dl = find_displist(&ob->disp, DL_VERTCOL);
2862 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2865 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2866 draw_mesh_object_outline(v3d, ob, dm);
2869 /* False for dupliframe objects */
2871 unsigned int *obCol1 = dl->col1;
2872 unsigned int *obCol2 = dl->col2;
2874 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2877 if(base->flag & SELECT) {
2878 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2880 UI_ThemeColor(TH_WIRE);
2882 dm->drawLooseEdges(dm);
2886 /* set default draw color back for wire or for draw-extra later on */
2888 if(base->flag & SELECT) {
2889 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2890 UI_ThemeColor(TH_GROUP_ACTIVE);
2891 else if(ob->flag & OB_FROMGROUP)
2892 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2893 else if(flag!=DRAW_CONSTCOLOR)
2894 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2896 glColor3ub(80,80,80);
2898 if (ob->flag & OB_FROMGROUP)
2899 UI_ThemeColor(TH_GROUP);
2901 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2902 glColor3ub(80,80,80);
2904 UI_ThemeColor(TH_WIRE);
2909 /* If drawing wire and drawtype is not OB_WIRE then we are
2910 * overlaying the wires.
2912 * UPDATE bug #10290 - With this wire-only objects can draw
2913 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2915 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2916 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2918 if (dt!=OB_WIRE && draw_wire==2) {
2919 bglPolygonOffset(rv3d->dist, 1.0);
2920 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2923 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2925 if (dt!=OB_WIRE && draw_wire==2) {
2927 bglPolygonOffset(rv3d->dist, 0.0);
2934 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2935 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2937 Object *ob= base->object;
2938 Object *obedit= scene->obedit;
2940 EditMesh *em= me->edit_mesh;
2941 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;