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"
68 #include "BLI_arithb.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_smoke.h"
96 #include "BKE_utildefines.h"
97 #include "smoke_API.h"
100 #include "BIF_glutil.h"
102 #include "GPU_draw.h"
103 #include "GPU_material.h"
104 #include "GPU_extensions.h"
105 #include "gpu_buffers.h"
108 #include "ED_particle.h"
109 #include "ED_screen.h"
110 #include "ED_types.h"
113 #include "UI_resources.h"
114 #include "UI_interface_icons.h"
117 #include "wm_subwindow.h"
120 #include "view3d_intern.h" // own include
123 /* this condition has been made more complex since editmode can draw textures */
124 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
125 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
126 (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
128 #define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
129 ( (sce->toolsettings->selectmode & SCE_SELECT_FACE) && \
130 (vd->drawtype<=OB_SOLID) && \
131 (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
134 static void draw_bounding_volume(Scene *scene, Object *ob);
136 static void drawcube_size(float size);
137 static void drawcircle_size(float size);
138 static void draw_empty_sphere(float size);
139 static void draw_empty_cone(float size);
142 /* ************* only use while object drawing ************** */
143 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
145 RegionView3D *rv3d= ar->regiondata;
146 float fx, fy, vec4[4];
150 /* clipplanes in eye space */
151 if(rv3d->rflag & RV3D_CLIPPING) {
153 Mat4MulVecfl(rv3d->viewmatob, vec4);
154 if(view3d_test_clipping(rv3d, vec4))
161 Mat4MulVec4fl(rv3d->persmatob, vec4);
163 /* clipplanes in window space */
164 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
165 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
167 if( fx>0 && fx<ar->winx) {
169 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
171 if(fy>0.0 && fy< (float)ar->winy) {
172 adr[0]= (short)floor(fx);
173 adr[1]= (short)floor(fy);
179 /* only use while object drawing */
180 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
182 RegionView3D *rv3d= ar->regiondata;
183 float fx, fy, vec4[4];
190 Mat4MulVec4fl(rv3d->persmatob, vec4);
192 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
193 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
195 if( fx>-32700 && fx<32700) {
197 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
199 if(fy>-32700.0 && fy<32700.0) {
200 adr[0]= (short)floor(fx);
201 adr[1]= (short)floor(fy);
207 /* ************************ */
209 /* check for glsl drawing */
211 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
213 if(!GPU_extensions_minimum_support())
217 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
219 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
222 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt >= OB_SHADED);
225 static int check_material_alpha(Base *base, Mesh *me, int glsl)
227 if(base->flag & OB_FROMDUPLI)
236 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
240 static unsigned int colortab[24]=
241 {0x0, 0xFF88FF, 0xFFBBFF,
242 0x403000, 0xFFFF88, 0xFFFFBB,
243 0x104040, 0x66CCCC, 0x77CCCC,
244 0x104010, 0x55BB55, 0x66FF66,
249 static float cube[8][3] = {
260 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
261 /* 32 values of sin function (still same result!) */
262 static float sinval[32] = {
297 /* 32 values of cos function (still same result!) */
298 static float cosval[32] ={
333 /* flag is same as for draw_object */
334 void drawaxes(float size, int flag, char drawtype)
337 float v1[3]= {0.0, 0.0, 0.0};
338 float v2[3]= {0.0, 0.0, 0.0};
339 float v3[3]= {0.0, 0.0, 0.0};
341 if(G.f & G_RENDER_SHADOW)
347 for (axis=0; axis<3; axis++) {
348 float v1[3]= {0.0, 0.0, 0.0};
349 float v2[3]= {0.0, 0.0, 0.0};
361 case OB_SINGLE_ARROW:
364 /* in positive z direction only */
371 glBegin(GL_TRIANGLES);
373 v2[0]= size*0.035; v2[1] = size*0.035;
374 v3[0]= size*-0.035; v3[1] = size*0.035;
375 v2[2]= v3[2]= size*0.75;
377 for (axis=0; axis<4; axis++) {
399 drawcircle_size(size);
402 case OB_EMPTY_SPHERE:
403 draw_empty_sphere(size);
407 draw_empty_cone(size);
412 for (axis=0; axis<3; axis++) {
413 float v1[3]= {0.0, 0.0, 0.0};
414 float v2[3]= {0.0, 0.0, 0.0};
415 int arrow_axis= (axis==0)?1:0;
424 v1[arrow_axis]= -size*0.125;
428 v1[arrow_axis]= size*0.125;
434 v2[axis]+= size*0.125;
436 // patch for 3d cards crashing on glSelect for text drawing (IBM)
437 if((flag & DRAW_PICKING) == 0) {
439 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "x", 0);
441 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "y", 0);
443 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "z", 0);
450 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
452 float vec[3], vx[3], vy[3];
455 VECCOPY(vx, tmat[0]);
456 VECCOPY(vy, tmat[1]);
461 for(a=0; a<tot; a++) {
462 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
463 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
464 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
470 /* circle for object centers, special_color is for library or ob users */
471 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int selstate, int special_color)
475 size= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
476 size*= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
478 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
479 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
483 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
485 else glColor4ub(0x55, 0xCC, 0xCC, 155);
488 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
489 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
490 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
492 drawcircball(GL_POLYGON, vec, size, rv3d->viewinv);
494 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
495 drawcircball(GL_LINE_LOOP, vec, size, rv3d->viewinv);
498 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
501 /* *********** text drawing for object/particles/armature ************* */
503 static ListBase CachedText[3];
504 static int CachedTextLevel= 0;
506 typedef struct ViewCachedString {
507 struct ViewCachedString *next, *prev;
508 float vec[3], col[4];
514 void view3d_cached_text_draw_begin()
516 ListBase *strings= &CachedText[CachedTextLevel];
517 strings->first= strings->last= NULL;
521 void view3d_cached_text_draw_add(float x, float y, float z, char *str, short xoffs)
523 ListBase *strings= &CachedText[CachedTextLevel-1];
524 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString), "ViewCachedString");
526 BLI_addtail(strings, vos);
527 BLI_strncpy(vos->str, str, 128);
531 glGetFloatv(GL_CURRENT_COLOR, vos->col);
535 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
537 RegionView3D *rv3d= ar->regiondata;
538 ListBase *strings= &CachedText[CachedTextLevel-1];
539 ViewCachedString *vos;
542 /* project first and test */
543 for(vos= strings->first; vos; vos= vos->next) {
545 Mat4MulVecfl(mat, vos->vec);
546 view3d_project_short_clip(ar, vos->vec, vos->mval);
547 if(vos->mval[0]!=IS_CLIPPED)
552 if(rv3d->rflag & RV3D_CLIPPING)
554 glDisable(GL_CLIP_PLANE0+a);
557 ED_region_pixelspace(ar);
560 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
564 for(vos= strings->first; vos; vos= vos->next) {
565 if(vos->mval[0]!=IS_CLIPPED) {
566 glColor3fv(vos->col);
567 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], (depth_write)? 0.0f: 2.0f, vos->str);
572 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
578 if(rv3d->rflag & RV3D_CLIPPING)
580 glEnable(GL_CLIP_PLANE0+a);
584 BLI_freelistN(strings);
589 /* ******************** primitive drawing ******************* */
591 static void drawcube(void)
594 glBegin(GL_LINE_STRIP);
595 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
596 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
597 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
600 glBegin(GL_LINE_STRIP);
601 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
604 glBegin(GL_LINE_STRIP);
605 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
608 glBegin(GL_LINE_STRIP);
609 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
613 /* draws a cube on given the scaling of the cube, assuming that
614 * all required matrices have been set (used for drawing empties)
616 static void drawcube_size(float size)
618 glBegin(GL_LINE_STRIP);
619 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
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);
624 glBegin(GL_LINE_STRIP);
625 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
628 glBegin(GL_LINE_STRIP);
629 glVertex3f(-size,size,size); glVertex3f(size,size,size);
632 glBegin(GL_LINE_STRIP);
633 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
637 /* this is an unused (old) cube-drawing function based on a given size */
639 static void drawcube_size(float *size)
643 glScalef(size[0], size[1], size[2]);
646 glBegin(GL_LINE_STRIP);
647 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
648 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
649 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
652 glBegin(GL_LINE_STRIP);
653 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
656 glBegin(GL_LINE_STRIP);
657 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
660 glBegin(GL_LINE_STRIP);
661 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
668 static void drawshadbuflimits(Lamp *la, float mat[][4])
670 float sta[3], end[3], lavec[3];
672 lavec[0]= -mat[2][0];
673 lavec[1]= -mat[2][1];
674 lavec[2]= -mat[2][2];
677 sta[0]= mat[3][0]+ la->clipsta*lavec[0];
678 sta[1]= mat[3][1]+ la->clipsta*lavec[1];
679 sta[2]= mat[3][2]+ la->clipsta*lavec[2];
681 end[0]= mat[3][0]+ la->clipend*lavec[0];
682 end[1]= mat[3][1]+ la->clipend*lavec[1];
683 end[2]= mat[3][2]+ la->clipend*lavec[2];
686 glBegin(GL_LINE_STRIP);
701 static void spotvolume(float *lvec, float *vvec, float inp)
703 /* camera is at 0,0,0 */
704 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
707 Normalize(vvec); /* is this the correct vector ? */
709 Crossf(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
710 Crossf(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
714 /* now we've got two equations: one of a cone and one of a plane, but we have
715 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
717 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
718 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
720 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
727 angle = saacos(plane[2])/2.0;
738 /* rotate lamp vector now over acos(inp) degrees */
746 si = sqrt(1-inp*inp);
752 Mat3MulMat3(mat3,mat2,mat1);
756 Mat3MulMat3(mat4,mat2,mat1);
759 Mat3MulMat3(mat2,mat1,mat3);
760 Mat3MulVecfl(mat2,lvec);
761 Mat3MulMat3(mat2,mat1,mat4);
762 Mat3MulVecfl(mat2,vvec);
767 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
770 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
771 float pixsize, lampsize;
772 float imat[4][4], curcol[4];
775 if(G.f & G_RENDER_SHADOW)
780 /* we first draw only the screen aligned & fixed scale stuff */
782 wmLoadMatrix(rv3d->viewmat);
784 /* lets calculate the scale: */
785 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];
786 pixsize*= rv3d->pixsize;
787 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
789 /* and view aligned matrix: */
790 Mat4CpyMat4(imat, rv3d->viewinv);
795 glGetFloatv(GL_CURRENT_COLOR, curcol);
800 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
801 else glColor4ub(0x77, 0xCC, 0xCC, 155);
805 VECCOPY(vec, ob->obmat[3]);
807 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
809 drawcircball(GL_POLYGON, vec, lampsize, imat);
816 circrad = 3.0f*lampsize;
817 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
821 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
822 if (la->type!=LA_HEMI) {
823 if ((la->mode & LA_SHAD_RAY) ||
824 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
826 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
830 /* draw the pretty sun rays */
831 if(la->type==LA_SUN) {
832 float v1[3], v2[3], mat[3][3];
835 /* setup a 45 degree rotation matrix */
836 VecRotToMat3(imat[2], M_PI/4.0f, mat);
839 VECCOPY(v1, imat[0]);
840 VecMulf(v1, circrad*1.2f);
841 VECCOPY(v2, imat[0]);
842 VecMulf(v2, circrad*2.5f);
845 glTranslatef(vec[0], vec[1], vec[2]);
850 for (axis=0; axis<8; axis++) {
853 Mat3MulVecfl(mat, v1);
854 Mat3MulVecfl(mat, v2);
858 glTranslatef(-vec[0], -vec[1], -vec[2]);
862 if (la->type==LA_LOCAL) {
863 if(la->mode & LA_SPHERE) {
864 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
866 /* yafray: for photonlight also draw lightcone as for spot */
869 glPopMatrix(); /* back in object space */
870 vec[0]= vec[1]= vec[2]= 0.0f;
872 if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
873 lvec[0]=lvec[1]= 0.0;
875 x = rv3d->persmat[0][2];
876 y = rv3d->persmat[1][2];
877 z = rv3d->persmat[2][2];
878 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
879 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
880 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
882 y = cos( M_PI*la->spotsize/360.0 );
883 spotvolume(lvec, vvec, y);
892 /* draw the angled sides of the cone */
893 glBegin(GL_LINE_STRIP);
899 z = x*sqrt(1.0 - y*y);
902 /* draw the circle/square at the end of the cone */
903 glTranslatef(0.0, 0.0 , x);
904 if(la->mode & LA_SQUARE) {
908 glBegin(GL_LINE_LOOP);
918 else circ(0.0, 0.0, fabs(z));
920 /* draw the circle/square representing spotbl */
921 if(la->type==LA_SPOT) {
922 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
923 /* make sure the line is always visible - prevent it from reaching the outer border (or 0)
924 * values are kinda arbitrary - just what seemed to work well */
925 if (spotblcirc == 0) spotblcirc = 0.15;
926 else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
927 circ(0.0, 0.0, spotblcirc);
931 else if ELEM(la->type, LA_HEMI, LA_SUN) {
933 /* draw the line from the circle along the dist */
934 glBegin(GL_LINE_STRIP);
941 if(la->type==LA_HEMI) {
942 /* draw the hemisphere curves */
943 short axis, steps, dir;
944 float outdist, zdist, mul;
945 vec[0]=vec[1]=vec[2]= 0.0;
946 outdist = 0.14; mul = 1.4; dir = 1;
949 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
950 for (axis=0; axis<4; axis++) {
951 float v[3]= {0.0, 0.0, 0.0};
954 glBegin(GL_LINE_STRIP);
956 for (steps=0; steps<6; steps++) {
957 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
958 /* make the arcs start at the edge of the energy circle */
959 if (steps == 0) v[0] = dir*circrad;
960 else v[0] = v[0] + dir*(steps*outdist);
961 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
962 /* make the arcs start at the edge of the energy circle */
963 if (steps == 0) v[1] = dir*circrad;
964 else v[1] = v[1] + dir*(steps*outdist);
967 v[2] = v[2] - steps*zdist;
975 /* flip the direction */
979 } else if(la->type==LA_AREA) {
981 if(la->area_shape==LA_AREA_SQUARE)
982 fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
983 else if(la->area_shape==LA_AREA_RECT)
984 fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
986 glBegin(GL_LINE_STRIP);
987 glVertex3f(0.0,0.0,-circrad);
988 glVertex3f(0.0,0.0,-la->dist);
992 /* and back to viewspace */
993 wmLoadMatrix(rv3d->viewmat);
994 VECCOPY(vec, ob->obmat[3]);
998 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
999 drawshadbuflimits(la, ob->obmat);
1002 UI_GetThemeColor4ubv(TH_LAMP, col);
1003 glColor4ub(col[0], col[1], col[2], col[3]);
1007 if (vec[2]>0) vec[2] -= circrad;
1008 else vec[2] += circrad;
1010 glBegin(GL_LINE_STRIP);
1022 glDisable(GL_BLEND);
1024 /* restore for drawing extra stuff */
1029 static void draw_limit_line(float sta, float end, unsigned int col)
1032 glVertex3f(0.0, 0.0, -sta);
1033 glVertex3f(0.0, 0.0, -end);
1039 glVertex3f(0.0, 0.0, -sta);
1040 glVertex3f(0.0, 0.0, -end);
1046 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1047 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1048 static void draw_focus_cross(float dist, float size)
1051 glVertex3f(-size, 0.f, -dist);
1052 glVertex3f(size, 0.f, -dist);
1053 glVertex3f(0.f, -size, -dist);
1054 glVertex3f(0.f, size, -dist);
1058 /* flag similar to draw_object() */
1059 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1061 /* a standing up pyramid with (0,0,0) as top */
1064 float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1067 if(G.f & G_RENDER_SHADOW)
1072 glDisable(GL_LIGHTING);
1073 glDisable(GL_CULL_FACE);
1075 if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1076 facx= 0.5*cam->ortho_scale*1.28;
1077 facy= 0.5*cam->ortho_scale*1.024;
1078 depth= -cam->clipsta-0.1;
1082 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1084 depth= - fac*cam->lens/16.0;
1089 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
1090 vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1091 vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1092 vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1093 vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1095 glBegin(GL_LINE_LOOP);
1096 glVertex3fv(vec[1]);
1097 glVertex3fv(vec[2]);
1098 glVertex3fv(vec[3]);
1099 glVertex3fv(vec[4]);
1103 if(rv3d->persp>=2 && ob==v3d->camera) return;
1105 glBegin(GL_LINE_STRIP);
1106 glVertex3fv(vec[2]);
1107 glVertex3fv(vec[0]);
1108 glVertex3fv(vec[1]);
1109 glVertex3fv(vec[4]);
1110 glVertex3fv(vec[0]);
1111 glVertex3fv(vec[3]);
1119 /* draw an outline arrow for inactive cameras and filled
1120 * for active cameras. We actually draw both outline+filled
1121 * for active cameras so the wire can be seen side-on */
1123 if (i==0) glBegin(GL_LINE_LOOP);
1124 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1127 vec[0][0]= -0.7*cam->drawsize;
1128 vec[0][1]= 1.1*cam->drawsize;
1129 glVertex3fv(vec[0]);
1132 vec[0][1]= 1.8*cam->drawsize;
1133 glVertex3fv(vec[0]);
1135 vec[0][0]= 0.7*cam->drawsize;
1136 vec[0][1]= 1.1*cam->drawsize;
1137 glVertex3fv(vec[0]);
1143 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1144 wmLoadMatrix(rv3d->viewmat);
1145 Mat4CpyMat4(vec, ob->obmat);
1149 Mat4SwapMat4(rv3d->persmat, tmat);
1150 wmGetSingleMatrix(rv3d->persmat);
1152 if(cam->flag & CAM_SHOWLIMITS) {
1153 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1154 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1155 draw_focus_cross(dof_camera(ob), cam->drawsize);
1159 if(cam->flag & CAM_SHOWMIST)
1160 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1162 Mat4SwapMat4(rv3d->persmat, tmat);
1167 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1169 BPoint *bp = lt->def;
1170 float *co = dl?dl->verts:NULL;
1173 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1174 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1175 bglBegin(GL_POINTS);
1177 for(w=0; w<lt->pntsw; w++) {
1178 int wxt = (w==0 || w==lt->pntsw-1);
1179 for(v=0; v<lt->pntsv; v++) {
1180 int vxt = (v==0 || v==lt->pntsv-1);
1181 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1182 int uxt = (u==0 || u==lt->pntsu-1);
1183 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1185 if((bp->f1 & SELECT)==sel) {
1186 bglVertex3fv(dl?co:bp->vec);
1198 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1200 Object *obedit= vc->obedit;
1201 Lattice *lt= obedit->data;
1202 BPoint *bp = lt->editlatt->def;
1203 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1204 float *co = dl?dl->verts:NULL;
1205 int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1206 short s[2] = {IS_CLIPPED, 0};
1208 for (i=0; i<N; i++, bp++, co+=3) {
1210 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s);
1211 if (s[0] != IS_CLIPPED)
1212 func(userData, bp, s[0], s[1]);
1217 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1219 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1223 MDeformWeight *mdw= ED_vgroup_weight_get (lt->dvert+index, use_wcol-1);
1225 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1231 glVertex3fv(&dl->verts[index*3]);
1233 glVertex3fv(lt->def[index].vec);
1237 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1238 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1240 Lattice *lt= ob->data;
1245 /* now we default make displist, this will modifiers work for non animated case */
1246 if(ob->disp.first==NULL)
1247 lattice_calc_modifiers(scene, ob);
1248 dl= find_displist(&ob->disp, DL_VERTS);
1253 if(ob->defbase.first && lt->dvert) {
1254 use_wcol= ob->actdef;
1255 glShadeModel(GL_SMOOTH);
1259 if(lt->editlatt) lt= lt->editlatt;
1262 for(w=0; w<lt->pntsw; w++) {
1263 int wxt = (w==0 || w==lt->pntsw-1);
1264 for(v=0; v<lt->pntsv; v++) {
1265 int vxt = (v==0 || v==lt->pntsv-1);
1266 for(u=0; u<lt->pntsu; u++) {
1267 int uxt = (u==0 || u==lt->pntsu-1);
1269 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1270 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1271 drawlattice__point(lt, dl, u, v, w, use_wcol);
1273 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1274 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1275 drawlattice__point(lt, dl, u, v, w, use_wcol);
1277 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1278 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1279 drawlattice__point(lt, dl, u, v, w, use_wcol);
1286 /* restoration for weight colors */
1288 glShadeModel(GL_FLAT);
1290 if( ((Lattice *)ob->data)->editlatt ) {
1291 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1293 lattice_draw_verts(lt, dl, 0);
1294 lattice_draw_verts(lt, dl, 1);
1296 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1300 /* ***************** ******************** */
1302 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1304 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1305 EditVert *eve = EM_get_vert_for_index(index);
1308 short s[2]= {IS_CLIPPED, 0};
1310 if (data->clipVerts) {
1311 view3d_project_short_clip(data->vc.ar, co, s);
1313 view3d_project_short_noclip(data->vc.ar, co, s);
1316 if (s[0]!=IS_CLIPPED)
1317 data->func(data->userData, eve, s[0], s[1], index);
1321 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1323 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1324 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1328 data.userData = userData;
1329 data.clipVerts = clipVerts;
1331 EM_init_index_arrays(vc->em, 1, 0, 0);
1332 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1333 EM_free_index_arrays();
1338 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1340 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;
1341 EditEdge *eed = EM_get_edge_for_index(index);
1345 if (data->clipVerts==1) {
1346 view3d_project_short_clip(data->vc.ar, v0co, s[0]);
1347 view3d_project_short_clip(data->vc.ar, v1co, s[1]);
1349 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1350 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1352 if (data->clipVerts==2) {
1353 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1354 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1359 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1363 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)
1365 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1366 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1370 data.userData = userData;
1371 data.clipVerts = clipVerts;
1373 EM_init_index_arrays(vc->em, 0, 1, 0);
1374 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1375 EM_free_index_arrays();
1380 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1382 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1383 EditFace *efa = EM_get_face_for_index(index);
1386 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1387 view3d_project_short_clip(data->vc.ar, cent, s);
1389 data->func(data->userData, efa, s[0], s[1], index);
1393 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1395 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1396 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1400 data.userData = userData;
1402 EM_init_index_arrays(vc->em, 0, 0, 1);
1403 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1404 EM_free_index_arrays();
1409 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1411 Curve *cu= vc->obedit->data;
1412 short s[2] = {IS_CLIPPED, 0};
1416 for (nu= cu->editnurb->first; nu; nu=nu->next) {
1417 if(nu->type == CU_BEZIER) {
1418 for (i=0; i<nu->pntsu; i++) {
1419 BezTriple *bezt = &nu->bezt[i];
1423 if(cu->drawflag & CU_HIDE_HANDLES) {
1424 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1425 if (s[0] != IS_CLIPPED)
1426 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1428 view3d_project_short_clip(vc->ar, bezt->vec[0], s);
1429 if (s[0] != IS_CLIPPED)
1430 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1431 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1432 if (s[0] != IS_CLIPPED)
1433 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1434 view3d_project_short_clip(vc->ar, bezt->vec[2], s);
1435 if (s[0] != IS_CLIPPED)
1436 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1442 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1443 BPoint *bp = &nu->bp[i];
1446 view3d_project_short_clip(vc->ar, bp->vec, s);
1447 if (s[0] != IS_CLIPPED)
1448 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1455 /* ************** DRAW MESH ****************** */
1457 /* First section is all the "simple" draw routines,
1458 * ones that just pass some sort of primitive to GL,
1459 * with perhaps various options to control lighting,
1462 * These routines should not have user interface related
1466 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1468 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1469 EditFace *efa = EM_get_face_for_index(index);
1471 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1473 glVertex3f( cent[0] + no[0]*ts->normalsize,
1474 cent[1] + no[1]*ts->normalsize,
1475 cent[2] + no[2]*ts->normalsize);
1478 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1481 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1485 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1487 EditFace *efa = EM_get_face_for_index(index);
1488 int sel = *((int*) userData);
1490 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1494 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1496 bglBegin(GL_POINTS);
1497 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1501 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1503 Scene *scene= (Scene *)userData;
1504 ToolSettings *ts= scene->toolsettings;
1505 EditVert *eve = EM_get_vert_for_index(index);
1511 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1512 co[1] + no_f[1]*ts->normalsize,
1513 co[2] + no_f[2]*ts->normalsize);
1515 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1516 co[1] + no_s[1]*ts->normalsize/32767.0f,
1517 co[2] + no_s[2]*ts->normalsize/32767.0f);
1521 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1524 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1528 /* Draw verts with color set based on selection */
1529 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1531 struct { int sel; EditVert *eve_act; } * data = userData;
1532 EditVert *eve = EM_get_vert_for_index(index);
1534 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1535 /* draw active larger - need to stop/start point drawing for this :/ */
1536 if (eve==data->eve_act) {
1537 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1538 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1543 bglBegin(GL_POINTS);
1547 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1549 bglBegin(GL_POINTS);
1556 /* disabled because it crashes combined with e.g. subsurf modifier,
1557 * the derivedmesh can't be assumed to be an EditMeshDerivedMesh,
1558 * nor should this struct be copied around, it should be defined in
1559 * a single place only to avoid them getting out of sync */
1561 /* originally defined in DerivedMesh.c */
1566 float (*vertexCos)[3];
1567 float (*vertexNos)[3];
1568 float (*faceNos)[3];
1569 } EditMeshDerivedMesh;
1572 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1574 struct { int sel; EditVert *eve_act; } data;
1575 //GPUBuffer *buffer;
1578 data.eve_act = eve_act;
1581 /* first come the unselected vertices, then the selected */
1582 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 );
1584 if( (varray = GPU_buffer_lock_stream( buffer )) && bglPointHack() == 0 ) {
1585 EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1588 int numverts = 0, numselected = 0;
1589 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END };
1590 GPU_buffer_unlock( buffer );
1591 GPU_interleaved_setup( buffer, datatype );
1592 varray = GPU_buffer_lock_stream( buffer );
1595 for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
1596 if (eve->h==0 && (eve->f&SELECT)==data.sel) {
1597 if (eve==data.eve_act) {
1598 if (emdm->vertexCos) {
1599 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],emdm->vertexCos[i]);
1602 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],eve->co);
1606 if (emdm->vertexCos) {
1607 VECCOPY(&varray[3*numverts],emdm->vertexCos[i]);
1609 VECCOPY(&varray[3*numverts],eve->co);
1616 GPU_buffer_unlock( buffer );
1617 glDrawArrays(GL_POINTS,0,numverts);
1618 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1619 glDrawArrays(GL_POINTS,dm->getNumVerts(dm),numselected);
1620 UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX);
1621 GPU_buffer_unbind();
1625 bglBegin(GL_POINTS);
1626 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1630 GPU_buffer_free( buffer, 0 );
1634 /* Draw edges with color set based on selection */
1635 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1637 EditEdge *eed = EM_get_edge_for_index(index);
1638 //unsigned char **cols = userData, *col;
1639 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1643 if (eed==data->eed_act) {
1644 glColor4ubv(data->actCol);
1646 if (eed->f&SELECT) {
1649 col = data->baseCol;
1651 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1652 if (col[3]==0) return 0;
1661 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1663 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1665 data.baseCol = baseCol;
1666 data.selCol = selCol;
1667 data.actCol = actCol;
1668 data.eed_act = eed_act;
1669 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1673 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1675 return EM_get_edge_for_index(index)->h==0;
1677 static void draw_dm_edges(DerivedMesh *dm)
1679 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1682 /* Draw edges with color interpolated based on selection */
1683 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1685 return EM_get_edge_for_index(index)->h==0;
1687 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1689 EditEdge *eed = EM_get_edge_for_index(index);
1690 unsigned char **cols = userData;
1691 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1692 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1694 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1695 col0[1] + (col1[1]-col0[1])*t,
1696 col0[2] + (col1[2]-col0[2])*t,
1697 col0[3] + (col1[3]-col0[3])*t);
1700 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1702 unsigned char *cols[2] = {baseCol, selCol};
1704 int elemsize = sizeof(float)*3+sizeof(unsigned char)*4;
1705 EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1706 EditMesh *em= emdm->em;
1707 unsigned char *varray;
1711 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 );
1712 if( (varray = GPU_buffer_lock_stream( buffer )) ) {
1715 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1716 GPU_buffer_unlock( buffer );
1717 GPU_interleaved_setup( buffer, datatype );
1718 varray = GPU_buffer_lock_stream( buffer );
1719 for (i=0,eed= em->edges.first; eed; i++,eed= eed->next) {
1721 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1722 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1724 if( emdm->vertexCos ) {
1725 VECCOPY(((float *)&varray[elemsize*numedges*2]),emdm->vertexCos[(int) eed->v1->tmp.l]);
1728 VECCOPY(((float *)&varray[elemsize*numedges*2]),eed->v1->co);
1730 QUATCOPY(&varray[elemsize*numedges*2+sizeof(float)*3],col0);
1731 if( emdm->vertexCos ) {
1732 VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),emdm->vertexCos[(int) eed->v2->tmp.l]);
1735 VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),eed->v2->co);
1737 QUATCOPY(&varray[elemsize*numedges*2+elemsize+sizeof(float)*3],col1);
1741 GPU_buffer_unlock( buffer );
1742 glDrawArrays(GL_LINES,0,numedges*2);
1743 GPU_buffer_unbind();
1747 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1750 GPU_buffer_free( buffer, 0 );
1754 /* Draw only seam edges */
1755 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1757 EditEdge *eed = EM_get_edge_for_index(index);
1759 return (eed->h==0 && eed->seam);
1761 static void draw_dm_edges_seams(DerivedMesh *dm)
1763 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1766 /* Draw only sharp edges */
1767 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1769 EditEdge *eed = EM_get_edge_for_index(index);
1771 return (eed->h==0 && eed->sharp);
1773 static void draw_dm_edges_sharp(DerivedMesh *dm)
1775 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1779 /* Draw faces with color set based on selection
1780 * return 2 for the active face so it renders with stipple enabled */
1781 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1783 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1784 EditFace *efa = EM_get_face_for_index(index);
1788 if (efa == data->efa_act) {
1789 glColor4ubv(data->cols[2]);
1790 return 2; /* stipple */
1792 col = data->cols[(efa->f&SELECT)?1:0];
1793 if (col[3]==0) return 0;
1801 /* also draws the active face */
1802 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
1804 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1805 //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1809 unsigned char *varray;
1810 unsigned char black[] = { 0, 0, 0, 0 };
1812 int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4);
1813 data.cols[0] = baseCol;
1814 data.cols[1] = selCol;
1815 data.cols[2] = actCol;
1816 data.efa_act = efa_act;
1819 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 );
1820 if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
1823 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1824 GPU_buffer_unlock( buffer );
1825 GPU_interleaved_setup( buffer, datatype );
1826 glShadeModel(GL_SMOOTH);
1827 varray = GPU_buffer_lock_stream( buffer );
1828 for (i=0,efa= efa_act; efa; i++,efa= efa->next) {
1829 int drawSmooth = (efa->flag & ME_SMOOTH);
1831 if (efa == data.efa_act) {
1834 col = data.cols[(efa->f&SELECT)?1:0];
1835 if (col[3]==0) draw = 0;
1842 if( prevdraw != draw && prevdraw != 0 && numfaces > 0) {
1844 glEnable(GL_POLYGON_STIPPLE);
1845 glPolygonStipple(stipple_quarttone);
1847 GPU_buffer_unlock( buffer );
1848 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
1850 glDisable(GL_POLYGON_STIPPLE);
1852 varray = GPU_buffer_lock_stream( buffer );
1858 /*if (emdm->vertexCos) {
1859 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1860 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1862 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1863 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1865 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1866 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1869 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1870 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1872 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1873 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1875 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1876 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1879 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1880 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1881 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1883 else if( draw == 1 ) {
1884 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1885 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1886 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1889 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1890 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1891 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1896 /*if (emdm->vertexCos) {
1897 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1898 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1900 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1901 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1903 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1904 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1907 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1908 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1910 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1911 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1913 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
1914 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1918 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1919 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1920 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1922 else if( draw == 1 ) {
1923 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1924 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1925 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1928 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1929 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1930 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1937 /*if (emdm->vertexCos) {
1938 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1939 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1941 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1942 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1944 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1945 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1948 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1949 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v1->no);
1951 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1952 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v2->no);
1954 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1955 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v3->no);
1959 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1960 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1961 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1963 else if( draw == 1 ) {
1964 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1965 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1966 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1969 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1970 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1971 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1976 /*if (emdm->vertexCos) {
1977 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1978 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1980 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1981 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1983 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1984 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1987 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1988 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v3->no);
1990 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1991 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v4->no);
1993 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
1994 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v1->no);
1998 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1999 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
2000 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
2002 else if( draw == 1 ) {
2003 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2004 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2005 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2008 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
2009 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
2010 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
2019 GPU_buffer_unlock( buffer );
2020 if( prevdraw != 0 && numfaces > 0) {
2022 glEnable(GL_POLYGON_STIPPLE);
2023 glPolygonStipple(stipple_quarttone);
2025 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2027 glDisable(GL_POLYGON_STIPPLE);
2030 GPU_buffer_unbind();
2032 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
2034 GPU_buffer_free( buffer, 0 );
2037 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2039 EditEdge *eed = EM_get_edge_for_index(index);
2041 if (eed->h==0 && eed->crease!=0.0) {
2042 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
2048 static void draw_dm_creases(DerivedMesh *dm)
2051 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2055 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2057 EditEdge *eed = EM_get_edge_for_index(index);
2059 if (eed->h==0 && eed->bweight!=0.0) {
2060 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2066 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2068 EditVert *eve = EM_get_vert_for_index(index);
2070 if (eve->h==0 && eve->bweight!=0.0) {
2071 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2075 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2077 ToolSettings *ts= scene->toolsettings;
2079 if (ts->selectmode & SCE_SELECT_VERTEX) {
2080 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2081 bglBegin(GL_POINTS);
2082 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2087 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2092 /* Second section of routines: Combine first sets to form fancy
2093 * drawing routines (for example rendering twice to get overlays).
2095 * Also includes routines that are basic drawing but are too
2096 * specialized to be split out (like drawing creases or measurements).
2099 /* EditMesh drawing routines*/
2101 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
2103 ToolSettings *ts= scene->toolsettings;
2106 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2108 for (sel=0; sel<2; sel++) {
2109 char col[4], fcol[4];
2112 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2113 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2115 for (pass=0; pass<2; pass++) {
2116 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2117 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2120 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2121 glDisable(GL_DEPTH_TEST);
2128 size = (size>2.1?size/2.0:size);
2129 fsize = (fsize>2.1?fsize/2.0:fsize);
2130 col[3] = fcol[3] = 100;
2132 col[3] = fcol[3] = 255;
2135 if(ts->selectmode & SCE_SELECT_VERTEX) {
2137 glColor4ubv((GLubyte *)col);
2138 draw_dm_verts(cageDM, sel, eve_act);
2141 if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
2143 glColor4ubv((GLubyte *)fcol);
2144 draw_dm_face_centers(cageDM, sel);
2148 glDisable(GL_BLEND);
2149 glEnable(GL_DEPTH_TEST);
2154 if(v3d->zbuf) glDepthMask(1);
2158 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2160 ToolSettings *ts= scene->toolsettings;
2162 unsigned char wireCol[4], selCol[4], actCol[4];
2164 /* since this function does transparant... */
2165 UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
2166 UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
2167 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
2169 /* when sel only is used, dont render wire, only selected, this is used for
2170 * textured draw mode when the 'edges' option is disabled */
2174 for (pass=0; pass<2; pass++) {
2175 /* show wires in transparant when no zbuf clipping for select */
2177 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2179 glDisable(GL_DEPTH_TEST);
2181 if (!sel_only) wireCol[3] = 85;
2187 if (!sel_only) wireCol[3] = 255;
2190 if(ts->selectmode == SCE_SELECT_FACE) {
2191 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2193 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2194 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2195 glShadeModel(GL_SMOOTH);
2196 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2197 glShadeModel(GL_FLAT);
2199 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2204 glColor4ubv(wireCol);
2205 draw_dm_edges(cageDM);
2210 glDisable(GL_BLEND);
2211 glEnable(GL_DEPTH_TEST);
2216 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2221 float v1[3], v2[3], v3[3], v4[3], x, y, z;
2223 char val[32]; /* Stores the measurement display text here */
2224 char conv_float[5]; /* Use a float conversion matching the grid size */
2225 float area, col[3]; /* area of the face, color of the text to draw */
2226 float grid= unit->system ? unit->scale_length : v3d->grid;
2227 int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2228 if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
2231 /* make the precission of the pronted value proportionate to the gridsize */
2234 strcpy(conv_float, "%.6f");
2235 else if (grid < 0.1f)
2236 strcpy(conv_float, "%.5f");
2237 else if (grid < 1.0f)
2238 strcpy(conv_float, "%.4f");
2239 else if (grid < 10.0f)
2240 strcpy(conv_float, "%.3f");
2242 strcpy(conv_float, "%.2f");
2245 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2246 glDisable(GL_DEPTH_TEST);
2248 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2250 if(me->drawflag & ME_DRAW_EDGELEN) {
2251 UI_GetThemeColor3fv(TH_TEXT, col);
2252 /* make color a bit more red */
2253 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2254 else col[0]= col[0]*0.7f + 0.3f;
2257 for(eed= em->edges.first; eed; eed= eed->next) {
2258 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2259 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2260 VECCOPY(v1, eed->v1->co);
2261 VECCOPY(v2, eed->v2->co);
2263 x= 0.5f*(v1[0]+v2[0]);
2264 y= 0.5f*(v1[1]+v2[1]);
2265 z= 0.5f*(v1[2]+v2[2]);
2267 if(v3d->flag & V3D_GLOBAL_STATS) {
2268 Mat4MulVecfl(ob->obmat, v1);
2269 Mat4MulVecfl(ob->obmat, v2);
2272 bUnit_AsString(val, sizeof(val), VecLenf(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2274 sprintf(val, conv_float, VecLenf(v1, v2));
2276 view3d_cached_text_draw_add(x, y, z, val, 0);
2281 if(me->drawflag & ME_DRAW_FACEAREA) {
2282 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2284 UI_GetThemeColor3fv(TH_TEXT, col);
2285 /* make color a bit more green */
2286 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2287 else col[1]= col[1]*0.7f + 0.3f;
2290 for(efa= em->faces.first; efa; efa= efa->next) {
2291 if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
2292 VECCOPY(v1, efa->v1->co);
2293 VECCOPY(v2, efa->v2->co);
2294 VECCOPY(v3, efa->v3->co);
2296 VECCOPY(v4, efa->v4->co);
2298 if(v3d->flag & V3D_GLOBAL_STATS) {
2299 Mat4MulVecfl(ob->obmat, v1);
2300 Mat4MulVecfl(ob->obmat, v2);
2301 Mat4MulVecfl(ob->obmat, v3);
2302 if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
2306 area= AreaQ3Dfl(v1, v2, v3, v4);
2308 area = AreaT3Dfl(v1, v2, v3);
2311 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2313 sprintf(val, conv_float, area);
2315 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2320 if(me->drawflag & ME_DRAW_EDGEANG) {
2321 EditEdge *e1, *e2, *e3, *e4;
2323 UI_GetThemeColor3fv(TH_TEXT, col);
2324 /* make color a bit more blue */
2325 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2326 else col[2]= col[2]*0.7f + 0.3f;
2329 for(efa= em->faces.first; efa; efa= efa->next) {
2330 VECCOPY(v1, efa->v1->co);
2331 VECCOPY(v2, efa->v2->co);
2332 VECCOPY(v3, efa->v3->co);
2334 VECCOPY(v4, efa->v4->co);
2339 if(v3d->flag & V3D_GLOBAL_STATS) {
2340 Mat4MulVecfl(ob->obmat, v1);
2341 Mat4MulVecfl(ob->obmat, v2);
2342 Mat4MulVecfl(ob->obmat, v3);
2343 Mat4MulVecfl(ob->obmat, v4);
2349 if(efa->e4) e4= efa->e4; else e4= e3;
2351 /* Calculate the angles */
2353 if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2355 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v4, v1, v2)));
2356 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8f);
2357 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2359 if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2361 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v1, v2, v3)));
2362 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8f);
2363 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2365 if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2368 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v2, v3, v4)));
2370 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v2, v3, v1)));
2371 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8f);
2372 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2376 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2377 sprintf(val,"%.3f", RAD2DEG(VecAngle3(v3, v4, v1)));
2378 VecLerpf(fvec, efa->cent, efa->v4->co, 0.8f);
2379 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2386 glEnable(GL_DEPTH_TEST);
2387 bglPolygonOffset(rv3d->dist, 0.0f);
2391 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2393 EditFace *efa = EM_get_face_for_index(index);
2396 GPU_enable_material(efa->mat_nr+1, NULL);
2403 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2405 EditFace *efa = EM_get_face_for_index(index);
2410 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2412 Mesh *me = ob->data;
2413 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2414 EditEdge *eed_act = NULL;
2415 EditVert *eve_act = NULL;
2417 if (em->selected.last) {
2418 EditSelection *ese = em->selected.last;
2419 /* face is handeled above */
2420 /*if (ese->type == EDITFACE ) {
2421 efa_act = (EditFace *)ese->data;
2422 } else */ if ( ese->type == EDITEDGE ) {
2423 eed_act = (EditEdge *)ese->data;
2424 } else if ( ese->type == EDITVERT ) {
2425 eve_act = (EditVert *)ese->data;
2429 EM_init_index_arrays(em, 1, 1, 1);
2432 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2433 if(draw_glsl_material(scene, ob, v3d, dt)) {
2434 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2436 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2437 draw_em_fancy__setGLSLFaceOpts, NULL);
2438 GPU_disable_material();
2440 glFrontFace(GL_CCW);
2443 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2447 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2448 GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 );
2451 int i, curmat = 0, draw = 0;
2453 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2455 glEnable(GL_LIGHTING);
2456 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2458 if( finalDM->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
2459 int prevdraw = 0, prevmat = 0;
2461 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END };
2462 GPU_buffer_unlock( buffer );
2463 GPU_interleaved_setup( buffer, datatype );
2464 glShadeModel(GL_SMOOTH);
2465 varray = GPU_buffer_lock_stream( buffer );
2466 for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
2467 int drawSmooth = (efa->flag & ME_SMOOTH);
2469 curmat = efa->mat_nr+1;
2475 if( ((prevdraw != draw) || (curmat != prevmat)) && prevdraw != 0 && numfaces > 0) {
2477 glEnable(GL_POLYGON_STIPPLE);
2478 glPolygonStipple(stipple_quarttone);
2480 GPU_buffer_unlock( buffer );
2481 GPU_enable_material(prevmat, NULL);
2482 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2484 glDisable(GL_POLYGON_STIPPLE);
2486 varray = GPU_buffer_lock_stream( buffer );
2491 VECCOPY(&varray[numfaces*18],efa->v1->co);
2492 VECCOPY(&varray[numfaces*18+3],efa->n);
2494 VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2495 VECCOPY(&varray[numfaces*18+9],efa->n);
2497 VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2498 VECCOPY(&varray[numfaces*18+15],efa->n);
2501 VECCOPY(&varray[numfaces*18],efa->v3->co);
2502 VECCOPY(&varray[numfaces*18+3],efa->n);
2504 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2505 VECCOPY(&varray[numfaces*18+9],efa->n);
2507 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2508 VECCOPY(&varray[numfaces*18+15],efa->n);
2513 VECCOPY(&varray[numfaces*18],efa->v1->co);
2514 VECCOPY(&varray[numfaces*18+3],efa->v1->no);
2516 VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2517 VECCOPY(&varray[numfaces*18+9],efa->v2->no);
2519 VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2520 VECCOPY(&varray[numfaces*18+15],efa->v3->no);
2523 VECCOPY(&varray[numfaces*18],efa->v3->co);
2524 VECCOPY(&varray[numfaces*18+3],efa->v3->no);
2526 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2527 VECCOPY(&varray[numfaces*18+9],efa->v4->no);
2529 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2530 VECCOPY(&varray[numfaces*18+15],efa->v1->no);
2538 GPU_buffer_unlock( buffer );
2539 if( prevdraw != 0 && numfaces > 0) {
2541 glEnable(GL_POLYGON_STIPPLE);
2542 glPolygonStipple(stipple_quarttone);
2544 GPU_enable_material(prevmat, NULL);
2545 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2547 glDisable(GL_POLYGON_STIPPLE);
2550 GPU_buffer_unbind();
2553 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2555 GPU_buffer_free(buffer,0);
2557 glFrontFace(GL_CCW);
2558 glDisable(GL_LIGHTING);
2561 // Setup for drawing wire over, disable zbuffer
2562 // write to show selected edge wires better
2563 UI_ThemeColor(TH_WIRE);
2565 bglPolygonOffset(rv3d->dist, 1.0);
2569 if (cageDM!=finalDM) {
2570 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2571 finalDM->drawEdges(finalDM, 1);
2575 if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2576 unsigned char col1[4], col2[4], col3[4];
2578 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2579 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2580 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2583 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2585 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2586 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2589 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2591 glDisable(GL_BLEND);
2592 glDepthMask(1); // restore write in zbuffer
2593 } else if (efa_act) {
2594 /* even if draw faces is off it would be nice to draw the stipple face
2595 * Make all other faces zero alpha except for the active
2597 unsigned char col1[4], col2[4], col3[4];
2598 col1[3] = col2[3] = 0; /* dont draw */
2599 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2602 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2604 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2606 glDisable(GL_BLEND);
2607 glDepthMask(1); // restore write in zbuffer
2611 /* here starts all fancy draw-extra over */
2612 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2613 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2615 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2616 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2619 if(me->drawflag & ME_DRAWSEAMS) {
2620 UI_ThemeColor(TH_EDGE_SEAM);
2623 draw_dm_edges_seams(cageDM);
2629 if(me->drawflag & ME_DRAWSHARP) {
2630 UI_ThemeColor(TH_EDGE_SHARP);
2633 draw_dm_edges_sharp(cageDM);
2639 if(me->drawflag & ME_DRAWCREASES) {
2640 draw_dm_creases(cageDM);
2642 if(me->drawflag & ME_DRAWBWEIGHTS) {
2643 draw_dm_bweights(scene, cageDM);
2646 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2649 // XXX retopo_matrix_update(v3d);
2651 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2653 if(me->drawflag & ME_DRAWNORMALS) {
2654 UI_ThemeColor(TH_NORMAL);
2655 draw_dm_face_normals(scene, cageDM);
2657 if(me->drawflag & ME_DRAW_VNORMALS) {
2658 UI_ThemeColor(TH_NORMAL);
2659 draw_dm_vert_normals(scene, cageDM);
2662 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2663 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2668 bglPolygonOffset(rv3d->dist, 0.0);
2669 GPU_disable_material();
2672 EM_free_index_arrays();
2675 /* Mesh drawing routines */
2677 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2680 if(v3d->transp==0) { // not when we draw the transparent pass
2684 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2685 drawFacesSolid() doesn't draw the transparent faces */
2686 if(ob->dtx & OB_DRAWTRANSP) {
2687 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2688 dm->drawFacesSolid(dm, GPU_enable_material);
2689 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2690 GPU_disable_material();
2693 dm->drawEdges(dm, 0);
2701 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2707 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2709 Object *ob= base->object;
2710 Mesh *me = ob->data;
2711 Material *ma= give_current_material(ob, 1);
2712 int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2714 int totvert, totedge, totface;
2716 DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2721 if (ob->dtx&OB_DRAWWIRE) {
2722 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2725 totvert = dm->getNumVerts(dm);
2726 totedge = dm->getNumEdges(dm);
2727 totface = dm->getNumFaces(dm);
2729 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2731 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2733 // Unwanted combination.
2734 if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2736 if(dt==OB_BOUNDBOX) {
2737 draw_bounding_volume(scene, ob);
2739 else if(hasHaloMat || (totface==0 && totedge==0)) {
2744 else if(dt==OB_WIRE || totface==0) {
2745 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2747 else if( (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2748 CHECK_OB_DRAWTEXTURE(v3d, dt))
2750 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2752 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2753 draw_mesh_object_outline(v3d, ob, dm);
2756 if(draw_glsl_material(scene, ob, v3d, dt)) {
2757 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2759 dm->drawFacesGLSL(dm, GPU_enable_material);
2760 // if(get_ob_property(ob, "Text"))
2761 // XXX draw_mesh_text(ob, 1);
2762 GPU_disable_material();
2764 glFrontFace(GL_CCW);
2767 draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2771 if(base->flag & SELECT)
2772 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2774 UI_ThemeColor(TH_WIRE);
2776 dm->drawLooseEdges(dm);
2779 else if(dt==OB_SOLID) {
2780 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2781 draw_mesh_object_outline(v3d, ob, dm);
2783 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2785 glEnable(GL_LIGHTING);
2786 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2788 dm->drawFacesSolid(dm, GPU_enable_material);
2789 GPU_disable_material();
2791 glFrontFace(GL_CCW);
2792 glDisable(GL_LIGHTING);
2794 if(base->flag & SELECT) {
2795 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2797 UI_ThemeColor(TH_WIRE);
2799 dm->drawLooseEdges(dm);
2801 else if(dt==OB_SHADED) {
2802 int do_draw= 1; /* to resolve all G.f settings below... */
2806 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2807 /* enforce default material settings */
2808 GPU_enable_material(0, NULL);
2810 /* but set default spec */
2811 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2812 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2813 glColor3ub(120, 120, 120);
2814 glDisable(GL_COLOR_MATERIAL);
2816 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2817 glEnable(GL_LIGHTING);
2818 glEnable(GL_COLOR_MATERIAL);
2820 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2821 glDisable(GL_COLOR_MATERIAL);
2822 glDisable(GL_LIGHTING);
2824 GPU_disable_material();
2826 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2828 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2830 glColor3f(1.0f, 1.0f, 1.0f);
2831 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2837 dl = ob->disp.first;
2838 if (!dl || !dl->col1) {
2839 /* release and reload derivedmesh because it might be freed in
2840 shadeDispList due to a different datamask */
2842 shadeDispList(scene, base);
2843 dl = find_displist(&ob->disp, DL_VERTCOL);
2844 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2847 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2848 draw_mesh_object_outline(v3d, ob, dm);
2851 /* False for dupliframe objects */
2853 unsigned int *obCol1 = dl->col1;
2854 unsigned int *obCol2 = dl->col2;
2856 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2859 if(base->flag & SELECT) {
2860 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2862 UI_ThemeColor(TH_WIRE);
2864 dm->drawLooseEdges(dm);
2868 /* set default draw color back for wire or for draw-extra later on */
2870 if(base->flag & SELECT) {
2871 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2872 UI_ThemeColor(TH_GROUP_ACTIVE);
2873 else if(ob->flag & OB_FROMGROUP)
2874 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2875 else if(flag!=DRAW_CONSTCOLOR)
2876 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2878 glColor3ub(80,80,80);
2880 if (ob->flag & OB_FROMGROUP)
2881 UI_ThemeColor(TH_GROUP);
2883 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2884 glColor3ub(80,80,80);
2886 UI_ThemeColor(TH_WIRE);
2891 /* If drawing wire and drawtype is not OB_WIRE then we are
2892 * overlaying the wires.
2894 * UPDATE bug #10290 - With this wire-only objects can draw
2895 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2897 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2898 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2900 if (dt!=OB_WIRE && draw_wire==2) {
2901 bglPolygonOffset(rv3d->dist, 1.0);
2902 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2905 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2907 if (dt!=OB_WIRE && draw_wire==2) {
2909 bglPolygonOffset(rv3d->dist, 0.0);
2916 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2917 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2919 Object *ob= base->object;
2920 Object *obedit= scene->obedit;
2922 EditMesh *em= me->edit_mesh;
2923 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2925 if(obedit && ob!=obedit && ob->data==obedit->data) {
2930 if(ob==obedit || drawlinked) {
2931 DerivedMesh *finalDM, *cageDM;
2934 finalDM = cageDM = editmesh_get_derived_base(ob, em);
2936 cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2937 v3d->customdata_mask);
2940 // no transp in editmode, the fancy draw over goes bad then
<