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_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 * or after running ED_view3d_init_mats_rv3d
145 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
147 RegionView3D *rv3d= ar->regiondata;
148 float fx, fy, vec4[4];
152 /* clipplanes in eye space */
153 if(rv3d->rflag & RV3D_CLIPPING) {
155 mul_m4_v3(rv3d->viewmatob, vec4);
156 if(view3d_test_clipping(rv3d, vec4))
163 mul_m4_v4(rv3d->persmatob, vec4);
165 /* clipplanes in window space */
166 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
167 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
169 if( fx>0 && fx<ar->winx) {
171 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
173 if(fy>0.0 && fy< (float)ar->winy) {
174 adr[0]= (short)floor(fx);
175 adr[1]= (short)floor(fy);
181 /* only use while object drawing */
182 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
184 RegionView3D *rv3d= ar->regiondata;
185 float fx, fy, vec4[4];
192 mul_m4_v4(rv3d->persmatob, vec4);
194 if( vec4[3]>BL_NEAR_CLIP ) { /* is the NEAR clipping cutoff for picking */
195 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
197 if( fx>-32700 && fx<32700) {
199 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
201 if(fy>-32700.0 && fy<32700.0) {
202 adr[0]= (short)floor(fx);
203 adr[1]= (short)floor(fy);
209 /* ************************ */
211 /* check for glsl drawing */
213 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
215 if(!GPU_glsl_support())
219 if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
221 if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
224 return (scene->gm.matmode == GAME_MAT_GLSL) && (dt >= OB_SHADED);
227 static int check_material_alpha(Base *base, Mesh *me, int glsl)
229 if(base->flag & OB_FROMDUPLI)
238 return (glsl || (base->object->dtx & OB_DRAWTRANSP));
242 static unsigned int colortab[24]=
243 {0x0, 0xFF88FF, 0xFFBBFF,
244 0x403000, 0xFFFF88, 0xFFFFBB,
245 0x104040, 0x66CCCC, 0x77CCCC,
246 0x104010, 0x55BB55, 0x66FF66,
251 static float cube[8][3] = {
262 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
263 /* 32 values of sin function (still same result!) */
264 static float sinval[32] = {
299 /* 32 values of cos function (still same result!) */
300 static float cosval[32] ={
335 /* flag is same as for draw_object */
336 void drawaxes(float size, int flag, char drawtype)
339 float v1[3]= {0.0, 0.0, 0.0};
340 float v2[3]= {0.0, 0.0, 0.0};
341 float v3[3]= {0.0, 0.0, 0.0};
343 if(G.f & G_RENDER_SHADOW)
349 for (axis=0; axis<3; axis++) {
350 float v1[3]= {0.0, 0.0, 0.0};
351 float v2[3]= {0.0, 0.0, 0.0};
363 case OB_SINGLE_ARROW:
366 /* in positive z direction only */
373 glBegin(GL_TRIANGLES);
375 v2[0]= size*0.035; v2[1] = size*0.035;
376 v3[0]= size*-0.035; v3[1] = size*0.035;
377 v2[2]= v3[2]= size*0.75;
379 for (axis=0; axis<4; axis++) {
401 drawcircle_size(size);
404 case OB_EMPTY_SPHERE:
405 draw_empty_sphere(size);
409 draw_empty_cone(size);
414 for (axis=0; axis<3; axis++) {
415 float v1[3]= {0.0, 0.0, 0.0};
416 float v2[3]= {0.0, 0.0, 0.0};
417 int arrow_axis= (axis==0)?1:0;
426 v1[arrow_axis]= -size*0.125;
430 v1[arrow_axis]= size*0.125;
436 v2[axis]+= size*0.125;
438 // patch for 3d cards crashing on glSelect for text drawing (IBM)
439 if((flag & DRAW_PICKING) == 0) {
441 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "x", 0);
443 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "y", 0);
445 view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "z", 0);
452 void drawcircball(int mode, float *cent, float rad, float tmat[][4])
454 float vec[3], vx[3], vy[3];
457 VECCOPY(vx, tmat[0]);
458 VECCOPY(vy, tmat[1]);
463 for(a=0; a<tot; a++) {
464 vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
465 vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
466 vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
472 /* circle for object centers, special_color is for library or ob users */
473 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int selstate, int special_color)
477 size= rv3d->persmat[0][3]*vec[0]+ rv3d->persmat[1][3]*vec[1]+ rv3d->persmat[2][3]*vec[2]+ rv3d->persmat[3][3];
478 size*= rv3d->pixsize*((float)U.obcenter_dia*0.5f);
480 /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
481 if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
485 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
487 else glColor4ub(0x55, 0xCC, 0xCC, 155);
490 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
491 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
492 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
494 drawcircball(GL_POLYGON, vec, size, rv3d->viewinv);
496 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
497 drawcircball(GL_LINE_LOOP, vec, size, rv3d->viewinv);
500 if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
503 /* *********** text drawing for object/particles/armature ************* */
505 static ListBase CachedText[3];
506 static int CachedTextLevel= 0;
508 typedef struct ViewCachedString {
509 struct ViewCachedString *next, *prev;
510 float vec[3], col[4];
516 void view3d_cached_text_draw_begin()
518 ListBase *strings= &CachedText[CachedTextLevel];
519 strings->first= strings->last= NULL;
523 void view3d_cached_text_draw_add(float x, float y, float z, char *str, short xoffs)
525 ListBase *strings= &CachedText[CachedTextLevel-1];
526 ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString), "ViewCachedString");
528 BLI_addtail(strings, vos);
529 BLI_strncpy(vos->str, str, 128);
533 glGetFloatv(GL_CURRENT_COLOR, vos->col);
537 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
539 RegionView3D *rv3d= ar->regiondata;
540 ListBase *strings= &CachedText[CachedTextLevel-1];
541 ViewCachedString *vos;
544 /* project first and test */
545 for(vos= strings->first; vos; vos= vos->next) {
547 mul_m4_v3(mat, vos->vec);
548 view3d_project_short_clip(ar, vos->vec, vos->mval);
549 if(vos->mval[0]!=IS_CLIPPED)
554 if(rv3d->rflag & RV3D_CLIPPING)
556 glDisable(GL_CLIP_PLANE0+a);
559 ED_region_pixelspace(ar);
562 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
566 for(vos= strings->first; vos; vos= vos->next) {
567 if(vos->mval[0]!=IS_CLIPPED) {
568 glColor3fv(vos->col);
569 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], (depth_write)? 0.0f: 2.0f, vos->str);
574 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
580 if(rv3d->rflag & RV3D_CLIPPING)
582 glEnable(GL_CLIP_PLANE0+a);
586 BLI_freelistN(strings);
591 /* ******************** primitive drawing ******************* */
593 static void drawcube(void)
596 glBegin(GL_LINE_STRIP);
597 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
598 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
599 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
602 glBegin(GL_LINE_STRIP);
603 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
606 glBegin(GL_LINE_STRIP);
607 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
610 glBegin(GL_LINE_STRIP);
611 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
615 /* draws a cube on given the scaling of the cube, assuming that
616 * all required matrices have been set (used for drawing empties)
618 static void drawcube_size(float size)
620 glBegin(GL_LINE_STRIP);
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);glVertex3f(size,-size,size); glVertex3f(size,size,size);
623 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
626 glBegin(GL_LINE_STRIP);
627 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
630 glBegin(GL_LINE_STRIP);
631 glVertex3f(-size,size,size); glVertex3f(size,size,size);
634 glBegin(GL_LINE_STRIP);
635 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
639 /* this is an unused (old) cube-drawing function based on a given size */
641 static void drawcube_size(float *size)
645 glScalef(size[0], size[1], size[2]);
648 glBegin(GL_LINE_STRIP);
649 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
650 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
651 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
654 glBegin(GL_LINE_STRIP);
655 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
658 glBegin(GL_LINE_STRIP);
659 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
662 glBegin(GL_LINE_STRIP);
663 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
670 static void drawshadbuflimits(Lamp *la, float mat[][4])
672 float sta[3], end[3], lavec[3];
674 lavec[0]= -mat[2][0];
675 lavec[1]= -mat[2][1];
676 lavec[2]= -mat[2][2];
679 sta[0]= mat[3][0]+ la->clipsta*lavec[0];
680 sta[1]= mat[3][1]+ la->clipsta*lavec[1];
681 sta[2]= mat[3][2]+ la->clipsta*lavec[2];
683 end[0]= mat[3][0]+ la->clipend*lavec[0];
684 end[1]= mat[3][1]+ la->clipend*lavec[1];
685 end[2]= mat[3][2]+ la->clipend*lavec[2];
688 glBegin(GL_LINE_STRIP);
703 static void spotvolume(float *lvec, float *vvec, float inp)
705 /* camera is at 0,0,0 */
706 float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
709 normalize_v3(vvec); /* is this the correct vector ? */
711 cross_v3_v3v3(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
712 cross_v3_v3v3(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
716 /* now we've got two equations: one of a cone and one of a plane, but we have
717 three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
719 /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
720 /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
722 /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
729 angle = saacos(plane[2])/2.0;
738 quat_to_mat3(mat1,q);
740 /* rotate lamp vector now over acos(inp) degrees */
748 si = sqrt(1-inp*inp);
754 mul_m3_m3m3(mat3,mat2,mat1);
758 mul_m3_m3m3(mat4,mat2,mat1);
761 mul_m3_m3m3(mat2,mat1,mat3);
762 mul_m3_v3(mat2,lvec);
763 mul_m3_m3m3(mat2,mat1,mat4);
764 mul_m3_v3(mat2,vvec);
769 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
772 float vec[3], lvec[3], vvec[3], circrad, x,y,z;
773 float pixsize, lampsize;
774 float imat[4][4], curcol[4];
777 if(G.f & G_RENDER_SHADOW)
782 /* we first draw only the screen aligned & fixed scale stuff */
784 wmLoadMatrix(rv3d->viewmat);
786 /* lets calculate the scale: */
787 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];
788 pixsize*= rv3d->pixsize;
789 lampsize= pixsize*((float)U.obcenter_dia*0.5f);
791 /* and view aligned matrix: */
792 copy_m4_m4(imat, rv3d->viewinv);
793 normalize_v3(imat[0]);
794 normalize_v3(imat[1]);
797 glGetFloatv(GL_CURRENT_COLOR, curcol);
802 if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
803 else glColor4ub(0x77, 0xCC, 0xCC, 155);
807 VECCOPY(vec, ob->obmat[3]);
809 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
811 drawcircball(GL_POLYGON, vec, lampsize, imat);
818 circrad = 3.0f*lampsize;
819 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
823 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
824 if (la->type!=LA_HEMI) {
825 if ((la->mode & LA_SHAD_RAY) ||
826 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
828 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
832 /* draw the pretty sun rays */
833 if(la->type==LA_SUN) {
834 float v1[3], v2[3], mat[3][3];
837 /* setup a 45 degree rotation matrix */
838 vec_rot_to_mat3( mat,imat[2], M_PI/4.0f);
841 VECCOPY(v1, imat[0]);
842 mul_v3_fl(v1, circrad*1.2f);
843 VECCOPY(v2, imat[0]);
844 mul_v3_fl(v2, circrad*2.5f);
847 glTranslatef(vec[0], vec[1], vec[2]);
852 for (axis=0; axis<8; axis++) {
860 glTranslatef(-vec[0], -vec[1], -vec[2]);
864 if (la->type==LA_LOCAL) {
865 if(la->mode & LA_SPHERE) {
866 drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
868 /* yafray: for photonlight also draw lightcone as for spot */
871 glPopMatrix(); /* back in object space */
872 vec[0]= vec[1]= vec[2]= 0.0f;
874 if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
875 lvec[0]=lvec[1]= 0.0;
877 x = rv3d->persmat[0][2];
878 y = rv3d->persmat[1][2];
879 z = rv3d->persmat[2][2];
880 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
881 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
882 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
884 y = cos( M_PI*la->spotsize/360.0 );
885 spotvolume(lvec, vvec, y);
894 /* draw the angled sides of the cone */
895 glBegin(GL_LINE_STRIP);
901 z = x*sqrt(1.0 - y*y);
904 /* draw the circle/square at the end of the cone */
905 glTranslatef(0.0, 0.0 , x);
906 if(la->mode & LA_SQUARE) {
910 glBegin(GL_LINE_LOOP);
920 else circ(0.0, 0.0, fabs(z));
922 /* draw the circle/square representing spotbl */
923 if(la->type==LA_SPOT) {
924 float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
925 /* hide line if it is zero size or overlaps with outer border,
926 previously it adjusted to always to show it but that seems
927 confusing because it doesn't show the actual blend size */
928 if (spotblcirc != 0 && spotblcirc != fabs(z))
929 circ(0.0, 0.0, spotblcirc);
933 else if ELEM(la->type, LA_HEMI, LA_SUN) {
935 /* draw the line from the circle along the dist */
936 glBegin(GL_LINE_STRIP);
943 if(la->type==LA_HEMI) {
944 /* draw the hemisphere curves */
945 short axis, steps, dir;
946 float outdist, zdist, mul;
947 vec[0]=vec[1]=vec[2]= 0.0;
948 outdist = 0.14; mul = 1.4; dir = 1;
951 /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
952 for (axis=0; axis<4; axis++) {
953 float v[3]= {0.0, 0.0, 0.0};
956 glBegin(GL_LINE_STRIP);
958 for (steps=0; steps<6; steps++) {
959 if (axis == 0 || axis == 1) { /* x axis up, x axis down */
960 /* make the arcs start at the edge of the energy circle */
961 if (steps == 0) v[0] = dir*circrad;
962 else v[0] = v[0] + dir*(steps*outdist);
963 } else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
964 /* make the arcs start at the edge of the energy circle */
965 if (steps == 0) v[1] = dir*circrad;
966 else v[1] = v[1] + dir*(steps*outdist);
969 v[2] = v[2] - steps*zdist;
977 /* flip the direction */
981 } else if(la->type==LA_AREA) {
983 if(la->area_shape==LA_AREA_SQUARE)
984 fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
985 else if(la->area_shape==LA_AREA_RECT)
986 fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
988 glBegin(GL_LINE_STRIP);
989 glVertex3f(0.0,0.0,-circrad);
990 glVertex3f(0.0,0.0,-la->dist);
994 /* and back to viewspace */
995 wmLoadMatrix(rv3d->viewmat);
996 VECCOPY(vec, ob->obmat[3]);
1000 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1001 drawshadbuflimits(la, ob->obmat);
1004 UI_GetThemeColor4ubv(TH_LAMP, col);
1005 glColor4ub(col[0], col[1], col[2], col[3]);
1009 if (vec[2]>0) vec[2] -= circrad;
1010 else vec[2] += circrad;
1012 glBegin(GL_LINE_STRIP);
1024 glDisable(GL_BLEND);
1026 /* restore for drawing extra stuff */
1031 static void draw_limit_line(float sta, float end, unsigned int col)
1034 glVertex3f(0.0, 0.0, -sta);
1035 glVertex3f(0.0, 0.0, -end);
1041 glVertex3f(0.0, 0.0, -sta);
1042 glVertex3f(0.0, 0.0, -end);
1048 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1049 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1050 static void draw_focus_cross(float dist, float size)
1053 glVertex3f(-size, 0.f, -dist);
1054 glVertex3f(size, 0.f, -dist);
1055 glVertex3f(0.f, -size, -dist);
1056 glVertex3f(0.f, size, -dist);
1060 /* flag similar to draw_object() */
1061 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1063 /* a standing up pyramid with (0,0,0) as top */
1066 float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1069 if(G.f & G_RENDER_SHADOW)
1074 glDisable(GL_LIGHTING);
1075 glDisable(GL_CULL_FACE);
1077 if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1078 facx= 0.5*cam->ortho_scale*1.28;
1079 facy= 0.5*cam->ortho_scale*1.024;
1080 depth= -cam->clipsta-0.1;
1084 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1086 depth= - fac*cam->lens/16.0;
1091 vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
1092 vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1093 vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1094 vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1095 vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1097 glBegin(GL_LINE_LOOP);
1098 glVertex3fv(vec[1]);
1099 glVertex3fv(vec[2]);
1100 glVertex3fv(vec[3]);
1101 glVertex3fv(vec[4]);
1105 if(rv3d->persp>=2 && ob==v3d->camera) return;
1107 glBegin(GL_LINE_STRIP);
1108 glVertex3fv(vec[2]);
1109 glVertex3fv(vec[0]);
1110 glVertex3fv(vec[1]);
1111 glVertex3fv(vec[4]);
1112 glVertex3fv(vec[0]);
1113 glVertex3fv(vec[3]);
1121 /* draw an outline arrow for inactive cameras and filled
1122 * for active cameras. We actually draw both outline+filled
1123 * for active cameras so the wire can be seen side-on */
1125 if (i==0) glBegin(GL_LINE_LOOP);
1126 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1129 vec[0][0]= -0.7*cam->drawsize;
1130 vec[0][1]= 1.1*cam->drawsize;
1131 glVertex3fv(vec[0]);
1134 vec[0][1]= 1.8*cam->drawsize;
1135 glVertex3fv(vec[0]);
1137 vec[0][0]= 0.7*cam->drawsize;
1138 vec[0][1]= 1.1*cam->drawsize;
1139 glVertex3fv(vec[0]);
1145 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1146 wmLoadMatrix(rv3d->viewmat);
1147 copy_m4_m4(vec, ob->obmat);
1151 swap_m4m4(rv3d->persmat, tmat);
1152 wmGetSingleMatrix(rv3d->persmat);
1154 if(cam->flag & CAM_SHOWLIMITS) {
1155 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1156 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1157 draw_focus_cross(dof_camera(ob), cam->drawsize);
1161 if(cam->flag & CAM_SHOWMIST)
1162 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1164 swap_m4m4(rv3d->persmat, tmat);
1169 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1171 BPoint *bp = lt->def;
1172 float *co = dl?dl->verts:NULL;
1175 UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1176 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1177 bglBegin(GL_POINTS);
1179 for(w=0; w<lt->pntsw; w++) {
1180 int wxt = (w==0 || w==lt->pntsw-1);
1181 for(v=0; v<lt->pntsv; v++) {
1182 int vxt = (v==0 || v==lt->pntsv-1);
1183 for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1184 int uxt = (u==0 || u==lt->pntsu-1);
1185 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1187 if((bp->f1 & SELECT)==sel) {
1188 bglVertex3fv(dl?co:bp->vec);
1200 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1202 Object *obedit= vc->obedit;
1203 Lattice *lt= obedit->data;
1204 BPoint *bp = lt->editlatt->def;
1205 DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1206 float *co = dl?dl->verts:NULL;
1207 int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1208 short s[2] = {IS_CLIPPED, 0};
1210 for (i=0; i<N; i++, bp++, co+=3) {
1212 view3d_project_short_clip(vc->ar, dl?co:bp->vec, s);
1213 if (s[0] != IS_CLIPPED)
1214 func(userData, bp, s[0], s[1]);
1219 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1221 int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1225 MDeformWeight *mdw= ED_vgroup_weight_get (lt->dvert+index, use_wcol-1);
1227 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1233 glVertex3fv(&dl->verts[index*3]);
1235 glVertex3fv(lt->def[index].vec);
1239 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1240 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1242 Lattice *lt= ob->data;
1247 /* now we default make displist, this will modifiers work for non animated case */
1248 if(ob->disp.first==NULL)
1249 lattice_calc_modifiers(scene, ob);
1250 dl= find_displist(&ob->disp, DL_VERTS);
1255 if(ob->defbase.first && lt->dvert) {
1256 use_wcol= ob->actdef;
1257 glShadeModel(GL_SMOOTH);
1261 if(lt->editlatt) lt= lt->editlatt;
1264 for(w=0; w<lt->pntsw; w++) {
1265 int wxt = (w==0 || w==lt->pntsw-1);
1266 for(v=0; v<lt->pntsv; v++) {
1267 int vxt = (v==0 || v==lt->pntsv-1);
1268 for(u=0; u<lt->pntsu; u++) {
1269 int uxt = (u==0 || u==lt->pntsu-1);
1271 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1272 drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1273 drawlattice__point(lt, dl, u, v, w, use_wcol);
1275 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1276 drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1277 drawlattice__point(lt, dl, u, v, w, use_wcol);
1279 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1280 drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1281 drawlattice__point(lt, dl, u, v, w, use_wcol);
1288 /* restoration for weight colors */
1290 glShadeModel(GL_FLAT);
1292 if( ((Lattice *)ob->data)->editlatt ) {
1293 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1295 lattice_draw_verts(lt, dl, 0);
1296 lattice_draw_verts(lt, dl, 1);
1298 if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1302 /* ***************** ******************** */
1304 /* Note! - foreach funcs should be called while drawing or directly after
1305 * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1306 * but would not give correct results with dupli's for eg. which dont
1307 * use the object matrix in the useual way */
1308 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1310 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1311 EditVert *eve = EM_get_vert_for_index(index);
1314 short s[2]= {IS_CLIPPED, 0};
1316 if (data->clipVerts) {
1317 view3d_project_short_clip(data->vc.ar, co, s);
1319 view3d_project_short_noclip(data->vc.ar, co, s);
1322 if (s[0]!=IS_CLIPPED)
1323 data->func(data->userData, eve, s[0], s[1], index);
1327 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1329 struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1330 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1334 data.userData = userData;
1335 data.clipVerts = clipVerts;
1337 EM_init_index_arrays(vc->em, 1, 0, 0);
1338 dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1339 EM_free_index_arrays();
1344 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1346 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;
1347 EditEdge *eed = EM_get_edge_for_index(index);
1351 if (data->clipVerts==1) {
1352 view3d_project_short_clip(data->vc.ar, v0co, s[0]);
1353 view3d_project_short_clip(data->vc.ar, v1co, s[1]);
1355 view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1356 view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1358 if (data->clipVerts==2) {
1359 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1360 if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy))
1365 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1369 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)
1371 struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1372 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1376 data.userData = userData;
1377 data.clipVerts = clipVerts;
1379 EM_init_index_arrays(vc->em, 0, 1, 0);
1380 dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1381 EM_free_index_arrays();
1386 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1388 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1389 EditFace *efa = EM_get_face_for_index(index);
1392 if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1393 view3d_project_short_clip(data->vc.ar, cent, s);
1395 data->func(data->userData, efa, s[0], s[1], index);
1399 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1401 struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1402 DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1406 data.userData = userData;
1408 EM_init_index_arrays(vc->em, 0, 0, 1);
1409 dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1410 EM_free_index_arrays();
1415 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1417 Curve *cu= vc->obedit->data;
1418 short s[2] = {IS_CLIPPED, 0};
1422 for (nu= cu->editnurb->first; nu; nu=nu->next) {
1423 if(nu->type == CU_BEZIER) {
1424 for (i=0; i<nu->pntsu; i++) {
1425 BezTriple *bezt = &nu->bezt[i];
1429 if(cu->drawflag & CU_HIDE_HANDLES) {
1430 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1431 if (s[0] != IS_CLIPPED)
1432 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1434 view3d_project_short_clip(vc->ar, bezt->vec[0], s);
1435 if (s[0] != IS_CLIPPED)
1436 func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1437 view3d_project_short_clip(vc->ar, bezt->vec[1], s);
1438 if (s[0] != IS_CLIPPED)
1439 func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1440 view3d_project_short_clip(vc->ar, bezt->vec[2], s);
1441 if (s[0] != IS_CLIPPED)
1442 func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1448 for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1449 BPoint *bp = &nu->bp[i];
1452 view3d_project_short_clip(vc->ar, bp->vec, s);
1453 if (s[0] != IS_CLIPPED)
1454 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1461 /* ************** DRAW MESH ****************** */
1463 /* First section is all the "simple" draw routines,
1464 * ones that just pass some sort of primitive to GL,
1465 * with perhaps various options to control lighting,
1468 * These routines should not have user interface related
1472 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1474 ToolSettings *ts= ((Scene *)userData)->toolsettings;
1475 EditFace *efa = EM_get_face_for_index(index);
1477 if (efa->h==0 && efa->fgonf!=EM_FGON) {
1479 glVertex3f( cent[0] + no[0]*ts->normalsize,
1480 cent[1] + no[1]*ts->normalsize,
1481 cent[2] + no[2]*ts->normalsize);
1484 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
1487 dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1491 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1493 EditFace *efa = EM_get_face_for_index(index);
1494 int sel = *((int*) userData);
1496 if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1500 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1502 bglBegin(GL_POINTS);
1503 dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1507 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1509 Scene *scene= (Scene *)userData;
1510 ToolSettings *ts= scene->toolsettings;
1511 EditVert *eve = EM_get_vert_for_index(index);
1517 glVertex3f( co[0] + no_f[0]*ts->normalsize,
1518 co[1] + no_f[1]*ts->normalsize,
1519 co[2] + no_f[2]*ts->normalsize);
1521 glVertex3f( co[0] + no_s[0]*ts->normalsize/32767.0f,
1522 co[1] + no_s[1]*ts->normalsize/32767.0f,
1523 co[2] + no_s[2]*ts->normalsize/32767.0f);
1527 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
1530 dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1534 /* Draw verts with color set based on selection */
1535 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1537 struct { int sel; EditVert *eve_act; } * data = userData;
1538 EditVert *eve = EM_get_vert_for_index(index);
1540 if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1541 /* draw active larger - need to stop/start point drawing for this :/ */
1542 if (eve==data->eve_act) {
1543 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1544 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1549 bglBegin(GL_POINTS);
1553 UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1555 bglBegin(GL_POINTS);
1562 /* disabled because it crashes combined with e.g. subsurf modifier,
1563 * the derivedmesh can't be assumed to be an EditMeshDerivedMesh,
1564 * nor should this struct be copied around, it should be defined in
1565 * a single place only to avoid them getting out of sync */
1567 /* originally defined in DerivedMesh.c */
1572 float (*vertexCos)[3];
1573 float (*vertexNos)[3];
1574 float (*faceNos)[3];
1575 } EditMeshDerivedMesh;
1578 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1580 struct { int sel; EditVert *eve_act; } data;
1581 //GPUBuffer *buffer;
1584 data.eve_act = eve_act;
1587 /* first come the unselected vertices, then the selected */
1588 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 );
1590 if( (varray = GPU_buffer_lock_stream( buffer )) && bglPointHack() == 0 ) {
1591 EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
1594 int numverts = 0, numselected = 0;
1595 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_END };
1596 GPU_buffer_unlock( buffer );
1597 GPU_interleaved_setup( buffer, datatype );
1598 varray = GPU_buffer_lock_stream( buffer );
1601 for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
1602 if (eve->h==0 && (eve->f&SELECT)==data.sel) {
1603 if (eve==data.eve_act) {
1604 if (emdm->vertexCos) {
1605 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],emdm->vertexCos[i]);
1608 VECCOPY(&varray[3*(dm->getNumVerts(dm)+numselected)],eve->co);
1612 if (emdm->vertexCos) {
1613 VECCOPY(&varray[3*numverts],emdm->vertexCos[i]);
1615 VECCOPY(&varray[3*numverts],eve->co);
1622 GPU_buffer_unlock( buffer );
1623 glDrawArrays(GL_POINTS,0,numverts);
1624 UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1625 glDrawArrays(GL_POINTS,dm->getNumVerts(dm),numselected);
1626 UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX);
1627 GPU_buffer_unbind();
1631 bglBegin(GL_POINTS);
1632 dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1636 GPU_buffer_free( buffer, 0 );
1640 /* Draw edges with color set based on selection */
1641 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1643 EditEdge *eed = EM_get_edge_for_index(index);
1644 //unsigned char **cols = userData, *col;
1645 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1649 if (eed==data->eed_act) {
1650 glColor4ubv(data->actCol);
1652 if (eed->f&SELECT) {
1655 col = data->baseCol;
1657 /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
1658 if (col[3]==0) return 0;
1667 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
1669 struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1671 data.baseCol = baseCol;
1672 data.selCol = selCol;
1673 data.actCol = actCol;
1674 data.eed_act = eed_act;
1675 dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1679 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1681 return EM_get_edge_for_index(index)->h==0;
1683 static void draw_dm_edges(DerivedMesh *dm)
1685 dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1688 /* Draw edges with color interpolated based on selection */
1689 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1691 return EM_get_edge_for_index(index)->h==0;
1693 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1695 EditEdge *eed = EM_get_edge_for_index(index);
1696 unsigned char **cols = userData;
1697 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1698 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1700 glColor4ub( col0[0] + (col1[0]-col0[0])*t,
1701 col0[1] + (col1[1]-col0[1])*t,
1702 col0[2] + (col1[2]-col0[2])*t,
1703 col0[3] + (col1[3]-col0[3])*t);
1706 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1708 unsigned char *cols[2] = {baseCol, selCol};
1710 int elemsize = sizeof(float)*3+sizeof(unsigned char)*4;
1711 EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1712 EditMesh *em= emdm->em;
1713 unsigned char *varray;
1717 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 );
1718 if( (varray = GPU_buffer_lock_stream( buffer )) ) {
1721 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1722 GPU_buffer_unlock( buffer );
1723 GPU_interleaved_setup( buffer, datatype );
1724 varray = GPU_buffer_lock_stream( buffer );
1725 for (i=0,eed= em->edges.first; eed; i++,eed= eed->next) {
1727 unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1728 unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1730 if( emdm->vertexCos ) {
1731 VECCOPY(((float *)&varray[elemsize*numedges*2]),emdm->vertexCos[(int) eed->v1->tmp.l]);
1734 VECCOPY(((float *)&varray[elemsize*numedges*2]),eed->v1->co);
1736 QUATCOPY(&varray[elemsize*numedges*2+sizeof(float)*3],col0);
1737 if( emdm->vertexCos ) {
1738 VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),emdm->vertexCos[(int) eed->v2->tmp.l]);
1741 VECCOPY(((float *)&varray[elemsize*numedges*2+elemsize]),eed->v2->co);
1743 QUATCOPY(&varray[elemsize*numedges*2+elemsize+sizeof(float)*3],col1);
1747 GPU_buffer_unlock( buffer );
1748 glDrawArrays(GL_LINES,0,numedges*2);
1749 GPU_buffer_unbind();
1753 dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1756 GPU_buffer_free( buffer, 0 );
1760 /* Draw only seam edges */
1761 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1763 EditEdge *eed = EM_get_edge_for_index(index);
1765 return (eed->h==0 && eed->seam);
1767 static void draw_dm_edges_seams(DerivedMesh *dm)
1769 dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1772 /* Draw only sharp edges */
1773 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1775 EditEdge *eed = EM_get_edge_for_index(index);
1777 return (eed->h==0 && eed->sharp);
1779 static void draw_dm_edges_sharp(DerivedMesh *dm)
1781 dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1785 /* Draw faces with color set based on selection
1786 * return 2 for the active face so it renders with stipple enabled */
1787 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1789 struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1790 EditFace *efa = EM_get_face_for_index(index);
1794 if (efa == data->efa_act) {
1795 glColor4ubv(data->cols[2]);
1796 return 2; /* stipple */
1798 col = data->cols[(efa->f&SELECT)?1:0];
1799 if (col[3]==0) return 0;
1807 /* also draws the active face */
1808 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
1810 struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1811 //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm;
1815 unsigned char *varray;
1816 unsigned char black[] = { 0, 0, 0, 0 };
1818 int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4);
1819 data.cols[0] = baseCol;
1820 data.cols[1] = selCol;
1821 data.cols[2] = actCol;
1822 data.efa_act = efa_act;
1825 buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*dm->getNumFaces(dm)*3*2, 0 );
1826 if( dm->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
1829 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_C4UB, GPU_BUFFER_INTER_END };
1830 GPU_buffer_unlock( buffer );
1831 GPU_interleaved_setup( buffer, datatype );
1832 glShadeModel(GL_SMOOTH);
1833 varray = GPU_buffer_lock_stream( buffer );
1834 for (i=0,efa= efa_act; efa; i++,efa= efa->next) {
1835 int drawSmooth = (efa->flag & ME_SMOOTH);
1837 if (efa == data.efa_act) {
1840 col = data.cols[(efa->f&SELECT)?1:0];
1841 if (col[3]==0) draw = 0;
1848 if( prevdraw != draw && prevdraw != 0 && numfaces > 0) {
1850 glEnable(GL_POLYGON_STIPPLE);
1851 glPolygonStipple(stipple_quarttone);
1853 GPU_buffer_unlock( buffer );
1854 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
1856 glDisable(GL_POLYGON_STIPPLE);
1858 varray = GPU_buffer_lock_stream( buffer );
1864 /*if (emdm->vertexCos) {
1865 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1866 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1868 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1869 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1871 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1872 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1875 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1876 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1878 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1879 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1881 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1882 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1885 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1886 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1887 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1889 else if( draw == 1 ) {
1890 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1891 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1892 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1895 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1896 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1897 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1902 /*if (emdm->vertexCos) {
1903 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1904 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->faceNos[i]);
1906 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1907 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->faceNos[i]);
1909 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1910 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->faceNos[i]);
1913 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1914 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->n);
1916 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1917 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->n);
1919 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
1920 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->n);
1924 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1925 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1926 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1928 else if( draw == 1 ) {
1929 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1930 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1931 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1934 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1935 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1936 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1943 /*if (emdm->vertexCos) {
1944 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v1->tmp.l]);
1945 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1947 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v2->tmp.l]);
1948 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1950 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v3->tmp.l]);
1951 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1954 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v1->co);
1955 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v1->no);
1957 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v2->co);
1958 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v2->no);
1960 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v3->co);
1961 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v3->no);
1965 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
1966 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
1967 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
1969 else if( draw == 1 ) {
1970 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1971 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1972 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
1975 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
1976 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
1977 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
1982 /*if (emdm->vertexCos) {
1983 VECCOPY((float *)&varray[elemsize*3*numfaces],emdm->vertexCos[(int) efa->v3->tmp.l]);
1984 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],emdm->vertexNos[(int) efa->v1->tmp.l]);
1986 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],emdm->vertexCos[(int) efa->v4->tmp.l]);
1987 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],emdm->vertexNos[(int) efa->v2->tmp.l]);
1989 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],emdm->vertexCos[(int) efa->v1->tmp.l]);
1990 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],emdm->vertexNos[(int) efa->v3->tmp.l]);
1993 VECCOPY((float *)&varray[elemsize*3*numfaces],efa->v3->co);
1994 VECCOPY((float *)&varray[elemsize*3*numfaces+sizeof(float)*3],efa->v3->no);
1996 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize],efa->v4->co);
1997 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize+sizeof(float)*3],efa->v4->no);
1999 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2],efa->v1->co);
2000 VECCOPY((float *)&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*3],efa->v1->no);
2004 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[2]);
2005 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[2]);
2006 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[2]);
2008 else if( draw == 1 ) {
2009 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2010 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2011 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],data.cols[(efa->f&SELECT)?1:0]);
2014 QUATCOPY(&varray[elemsize*3*numfaces+sizeof(float)*6],black);
2015 QUATCOPY(&varray[elemsize*3*numfaces+elemsize+sizeof(float)*6],black);
2016 QUATCOPY(&varray[elemsize*3*numfaces+elemsize*2+sizeof(float)*6],black);
2025 GPU_buffer_unlock( buffer );
2026 if( prevdraw != 0 && numfaces > 0) {
2028 glEnable(GL_POLYGON_STIPPLE);
2029 glPolygonStipple(stipple_quarttone);
2031 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2033 glDisable(GL_POLYGON_STIPPLE);
2036 GPU_buffer_unbind();
2038 dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
2040 GPU_buffer_free( buffer, 0 );
2043 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2045 EditEdge *eed = EM_get_edge_for_index(index);
2047 if (eed->h==0 && eed->crease!=0.0) {
2048 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
2054 static void draw_dm_creases(DerivedMesh *dm)
2057 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2061 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2063 EditEdge *eed = EM_get_edge_for_index(index);
2065 if (eed->h==0 && eed->bweight!=0.0) {
2066 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2072 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2074 EditVert *eve = EM_get_vert_for_index(index);
2076 if (eve->h==0 && eve->bweight!=0.0) {
2077 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2081 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2083 ToolSettings *ts= scene->toolsettings;
2085 if (ts->selectmode & SCE_SELECT_VERTEX) {
2086 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2087 bglBegin(GL_POINTS);
2088 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2093 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2098 /* Second section of routines: Combine first sets to form fancy
2099 * drawing routines (for example rendering twice to get overlays).
2101 * Also includes routines that are basic drawing but are too
2102 * specialized to be split out (like drawing creases or measurements).
2105 /* EditMesh drawing routines*/
2107 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
2109 ToolSettings *ts= scene->toolsettings;
2112 if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
2114 for (sel=0; sel<2; sel++) {
2115 char col[4], fcol[4];
2118 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2119 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2121 for (pass=0; pass<2; pass++) {
2122 float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2123 float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2126 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2127 glDisable(GL_DEPTH_TEST);
2134 size = (size>2.1?size/2.0:size);
2135 fsize = (fsize>2.1?fsize/2.0:fsize);
2136 col[3] = fcol[3] = 100;
2138 col[3] = fcol[3] = 255;
2141 if(ts->selectmode & SCE_SELECT_VERTEX) {
2143 glColor4ubv((GLubyte *)col);
2144 draw_dm_verts(cageDM, sel, eve_act);
2147 if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
2149 glColor4ubv((GLubyte *)fcol);
2150 draw_dm_face_centers(cageDM, sel);
2154 glDisable(GL_BLEND);
2155 glEnable(GL_DEPTH_TEST);
2160 if(v3d->zbuf) glDepthMask(1);
2164 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2166 ToolSettings *ts= scene->toolsettings;
2168 unsigned char wireCol[4], selCol[4], actCol[4];
2170 /* since this function does transparant... */
2171 UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
2172 UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
2173 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
2175 /* when sel only is used, dont render wire, only selected, this is used for
2176 * textured draw mode when the 'edges' option is disabled */
2180 for (pass=0; pass<2; pass++) {
2181 /* show wires in transparant when no zbuf clipping for select */
2183 if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2185 glDisable(GL_DEPTH_TEST);
2187 if (!sel_only) wireCol[3] = 85;
2193 if (!sel_only) wireCol[3] = 255;
2196 if(ts->selectmode == SCE_SELECT_FACE) {
2197 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2199 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
2200 if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2201 glShadeModel(GL_SMOOTH);
2202 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2203 glShadeModel(GL_FLAT);
2205 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2210 glColor4ubv(wireCol);
2211 draw_dm_edges(cageDM);
2216 glDisable(GL_BLEND);
2217 glEnable(GL_DEPTH_TEST);
2222 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2227 float v1[3], v2[3], v3[3], v4[3], x, y, z;
2229 char val[32]; /* Stores the measurement display text here */
2230 char conv_float[5]; /* Use a float conversion matching the grid size */
2231 float area, col[3]; /* area of the face, color of the text to draw */
2232 float grid= unit->system ? unit->scale_length : v3d->grid;
2233 int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2234 if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
2237 /* make the precision of the pronted value proportionate to the gridsize */
2240 strcpy(conv_float, "%.6f");
2241 else if (grid < 0.1f)
2242 strcpy(conv_float, "%.5f");
2243 else if (grid < 1.0f)
2244 strcpy(conv_float, "%.4f");
2245 else if (grid < 10.0f)
2246 strcpy(conv_float, "%.3f");
2248 strcpy(conv_float, "%.2f");
2251 if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2252 glDisable(GL_DEPTH_TEST);
2254 if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2256 if(me->drawflag & ME_DRAW_EDGELEN) {
2257 UI_GetThemeColor3fv(TH_TEXT, col);
2258 /* make color a bit more red */
2259 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2260 else col[0]= col[0]*0.7f + 0.3f;
2263 for(eed= em->edges.first; eed; eed= eed->next) {
2264 /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2265 if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2266 VECCOPY(v1, eed->v1->co);
2267 VECCOPY(v2, eed->v2->co);
2269 x= 0.5f*(v1[0]+v2[0]);
2270 y= 0.5f*(v1[1]+v2[1]);
2271 z= 0.5f*(v1[2]+v2[2]);
2273 if(v3d->flag & V3D_GLOBAL_STATS) {
2274 mul_m4_v3(ob->obmat, v1);
2275 mul_m4_v3(ob->obmat, v2);
2278 bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2280 sprintf(val, conv_float, len_v3v3(v1, v2));
2282 view3d_cached_text_draw_add(x, y, z, val, 0);
2287 if(me->drawflag & ME_DRAW_FACEAREA) {
2288 // XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2290 UI_GetThemeColor3fv(TH_TEXT, col);
2291 /* make color a bit more green */
2292 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2293 else col[1]= col[1]*0.7f + 0.3f;
2296 for(efa= em->faces.first; efa; efa= efa->next) {
2297 if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
2298 VECCOPY(v1, efa->v1->co);
2299 VECCOPY(v2, efa->v2->co);
2300 VECCOPY(v3, efa->v3->co);
2302 VECCOPY(v4, efa->v4->co);
2304 if(v3d->flag & V3D_GLOBAL_STATS) {
2305 mul_m4_v3(ob->obmat, v1);
2306 mul_m4_v3(ob->obmat, v2);
2307 mul_m4_v3(ob->obmat, v3);
2308 if (efa->v4) mul_m4_v3(ob->obmat, v4);
2312 area= area_quad_v3(v1, v2, v3, v4);
2314 area = area_tri_v3(v1, v2, v3);
2317 bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2319 sprintf(val, conv_float, area);
2321 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2326 if(me->drawflag & ME_DRAW_EDGEANG) {
2327 EditEdge *e1, *e2, *e3, *e4;
2329 UI_GetThemeColor3fv(TH_TEXT, col);
2330 /* make color a bit more blue */
2331 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2332 else col[2]= col[2]*0.7f + 0.3f;
2335 for(efa= em->faces.first; efa; efa= efa->next) {
2336 VECCOPY(v1, efa->v1->co);
2337 VECCOPY(v2, efa->v2->co);
2338 VECCOPY(v3, efa->v3->co);
2340 VECCOPY(v4, efa->v4->co);
2345 if(v3d->flag & V3D_GLOBAL_STATS) {
2346 mul_m4_v3(ob->obmat, v1);
2347 mul_m4_v3(ob->obmat, v2);
2348 mul_m4_v3(ob->obmat, v3);
2349 mul_m4_v3(ob->obmat, v4);
2355 if(efa->e4) e4= efa->e4; else e4= e3;
2357 /* Calculate the angles */
2359 if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2361 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v4, v1, v2)));
2362 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2363 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2365 if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2367 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v1, v2, v3)));
2368 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2369 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2371 if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2374 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v4)));
2376 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v1)));
2377 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2378 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2382 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2383 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v3, v4, v1)));
2384 interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2385 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2392 glEnable(GL_DEPTH_TEST);
2393 bglPolygonOffset(rv3d->dist, 0.0f);
2397 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2399 EditFace *efa = EM_get_face_for_index(index);
2402 GPU_enable_material(efa->mat_nr+1, NULL);
2409 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2411 EditFace *efa = EM_get_face_for_index(index);
2416 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2418 Mesh *me = ob->data;
2419 EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2420 EditEdge *eed_act = NULL;
2421 EditVert *eve_act = NULL;
2423 if (em->selected.last) {
2424 EditSelection *ese = em->selected.last;
2425 /* face is handeled above */
2426 /*if (ese->type == EDITFACE ) {
2427 efa_act = (EditFace *)ese->data;
2428 } else */ if ( ese->type == EDITEDGE ) {
2429 eed_act = (EditEdge *)ese->data;
2430 } else if ( ese->type == EDITVERT ) {
2431 eve_act = (EditVert *)ese->data;
2435 EM_init_index_arrays(em, 1, 1, 1);
2438 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2439 if(draw_glsl_material(scene, ob, v3d, dt)) {
2440 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2442 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2443 draw_em_fancy__setGLSLFaceOpts, NULL);
2444 GPU_disable_material();
2446 glFrontFace(GL_CCW);
2449 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2453 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2454 GPUBuffer *buffer = GPU_buffer_legacy(em->derivedFinal)?0:GPU_buffer_alloc( sizeof(float)*6*em->totface*3*2, 0 );
2457 int i, curmat = 0, draw = 0;
2459 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2461 glEnable(GL_LIGHTING);
2462 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2464 if( finalDM->getVertCos == 0 && (varray = GPU_buffer_lock_stream( buffer )) ) {
2465 int prevdraw = 0, prevmat = 0;
2467 int datatype[] = { GPU_BUFFER_INTER_V3F, GPU_BUFFER_INTER_N3F, GPU_BUFFER_INTER_END };
2468 GPU_buffer_unlock( buffer );
2469 GPU_interleaved_setup( buffer, datatype );
2470 glShadeModel(GL_SMOOTH);
2471 varray = GPU_buffer_lock_stream( buffer );
2472 for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
2473 int drawSmooth = (efa->flag & ME_SMOOTH);
2475 curmat = efa->mat_nr+1;
2481 if( ((prevdraw != draw) || (curmat != prevmat)) && prevdraw != 0 && numfaces > 0) {
2483 glEnable(GL_POLYGON_STIPPLE);
2484 glPolygonStipple(stipple_quarttone);
2486 GPU_buffer_unlock( buffer );
2487 GPU_enable_material(prevmat, NULL);
2488 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2490 glDisable(GL_POLYGON_STIPPLE);
2492 varray = GPU_buffer_lock_stream( buffer );
2497 VECCOPY(&varray[numfaces*18],efa->v1->co);
2498 VECCOPY(&varray[numfaces*18+3],efa->n);
2500 VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2501 VECCOPY(&varray[numfaces*18+9],efa->n);
2503 VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2504 VECCOPY(&varray[numfaces*18+15],efa->n);
2507 VECCOPY(&varray[numfaces*18],efa->v3->co);
2508 VECCOPY(&varray[numfaces*18+3],efa->n);
2510 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2511 VECCOPY(&varray[numfaces*18+9],efa->n);
2513 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2514 VECCOPY(&varray[numfaces*18+15],efa->n);
2519 VECCOPY(&varray[numfaces*18],efa->v1->co);
2520 VECCOPY(&varray[numfaces*18+3],efa->v1->no);
2522 VECCOPY(&varray[numfaces*18+6],efa->v2->co);
2523 VECCOPY(&varray[numfaces*18+9],efa->v2->no);
2525 VECCOPY(&varray[numfaces*18+12],efa->v3->co);
2526 VECCOPY(&varray[numfaces*18+15],efa->v3->no);
2529 VECCOPY(&varray[numfaces*18],efa->v3->co);
2530 VECCOPY(&varray[numfaces*18+3],efa->v3->no);
2532 VECCOPY(&varray[numfaces*18+6],efa->v4->co);
2533 VECCOPY(&varray[numfaces*18+9],efa->v4->no);
2535 VECCOPY(&varray[numfaces*18+12],efa->v1->co);
2536 VECCOPY(&varray[numfaces*18+15],efa->v1->no);
2544 GPU_buffer_unlock( buffer );
2545 if( prevdraw != 0 && numfaces > 0) {
2547 glEnable(GL_POLYGON_STIPPLE);
2548 glPolygonStipple(stipple_quarttone);
2550 GPU_enable_material(prevmat, NULL);
2551 glDrawArrays(GL_TRIANGLES,0,numfaces*3);
2553 glDisable(GL_POLYGON_STIPPLE);
2556 GPU_buffer_unbind();
2559 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2561 GPU_buffer_free(buffer,0);
2563 glFrontFace(GL_CCW);
2564 glDisable(GL_LIGHTING);
2567 // Setup for drawing wire over, disable zbuffer
2568 // write to show selected edge wires better
2569 UI_ThemeColor(TH_WIRE);
2571 bglPolygonOffset(rv3d->dist, 1.0);
2575 if (cageDM!=finalDM) {
2576 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2577 finalDM->drawEdges(finalDM, 1);
2581 if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2582 unsigned char col1[4], col2[4], col3[4];
2584 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2585 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2586 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2589 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2591 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2592 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2595 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2597 glDisable(GL_BLEND);
2598 glDepthMask(1); // restore write in zbuffer
2599 } else if (efa_act) {
2600 /* even if draw faces is off it would be nice to draw the stipple face
2601 * Make all other faces zero alpha except for the active
2603 unsigned char col1[4], col2[4], col3[4];
2604 col1[3] = col2[3] = 0; /* dont draw */
2605 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2608 glDepthMask(0); // disable write in zbuffer, needed for nice transp
2610 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2612 glDisable(GL_BLEND);
2613 glDepthMask(1); // restore write in zbuffer
2617 /* here starts all fancy draw-extra over */
2618 if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2619 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2621 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2622 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2625 if(me->drawflag & ME_DRAWSEAMS) {
2626 UI_ThemeColor(TH_EDGE_SEAM);
2629 draw_dm_edges_seams(cageDM);
2635 if(me->drawflag & ME_DRAWSHARP) {
2636 UI_ThemeColor(TH_EDGE_SHARP);
2639 draw_dm_edges_sharp(cageDM);
2645 if(me->drawflag & ME_DRAWCREASES) {
2646 draw_dm_creases(cageDM);
2648 if(me->drawflag & ME_DRAWBWEIGHTS) {
2649 draw_dm_bweights(scene, cageDM);
2652 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2655 // XXX retopo_matrix_update(v3d);
2657 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2659 if(me->drawflag & ME_DRAWNORMALS) {
2660 UI_ThemeColor(TH_NORMAL);
2661 draw_dm_face_normals(scene, cageDM);
2663 if(me->drawflag & ME_DRAW_VNORMALS) {
2664 UI_ThemeColor(TH_NORMAL);
2665 draw_dm_vert_normals(scene, cageDM);
2668 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2669 draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2674 bglPolygonOffset(rv3d->dist, 0.0);
2675 GPU_disable_material();
2678 EM_free_index_arrays();
2681 /* Mesh drawing routines */
2683 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2686 if(v3d->transp==0) { // not when we draw the transparent pass
2690 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2691 drawFacesSolid() doesn't draw the transparent faces */
2692 if(ob->dtx & OB_DRAWTRANSP) {
2693 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2694 dm->drawFacesSolid(dm, GPU_enable_material);
2695 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2696 GPU_disable_material();
2699 dm->drawEdges(dm, 0);
2707 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2713 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2715 Object *ob= base->object;
2716 Mesh *me = ob->data;
2717 Material *ma= give_current_material(ob, 1);
2718 int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2720 int totvert, totedge, totface;
2722 DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2727 if (ob->dtx&OB_DRAWWIRE) {
2728 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2731 totvert = dm->getNumVerts(dm);
2732 totedge = dm->getNumEdges(dm);
2733 totface = dm->getNumFaces(dm);
2735 /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2737 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2739 // Unwanted combination.
2740 if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2742 if(dt==OB_BOUNDBOX) {
2743 draw_bounding_volume(scene, ob);
2745 else if(hasHaloMat || (totface==0 && totedge==0)) {
2750 else if(dt==OB_WIRE || totface==0) {
2751 draw_wire = 1; /* draw wire only, no depth buffer stuff */
2753 else if( (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2754 CHECK_OB_DRAWTEXTURE(v3d, dt))
2756 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2758 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2759 draw_mesh_object_outline(v3d, ob, dm);
2762 if(draw_glsl_material(scene, ob, v3d, dt)) {
2763 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2765 dm->drawFacesGLSL(dm, GPU_enable_material);
2766 // if(get_ob_property(ob, "Text"))
2767 // XXX draw_mesh_text(ob, 1);
2768 GPU_disable_material();
2770 glFrontFace(GL_CCW);
2773 draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2777 if(base->flag & SELECT)
2778 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2780 UI_ThemeColor(TH_WIRE);
2782 dm->drawLooseEdges(dm);
2785 else if(dt==OB_SOLID) {
2786 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2787 draw_mesh_object_outline(v3d, ob, dm);
2789 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2791 glEnable(GL_LIGHTING);
2792 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2794 dm->drawFacesSolid(dm, GPU_enable_material);
2795 GPU_disable_material();
2797 glFrontFace(GL_CCW);
2798 glDisable(GL_LIGHTING);
2800 if(base->flag & SELECT) {
2801 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2803 UI_ThemeColor(TH_WIRE);
2805 dm->drawLooseEdges(dm);
2807 else if(dt==OB_SHADED) {
2808 int do_draw= 1; /* to resolve all G.f settings below... */
2812 if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2813 /* enforce default material settings */
2814 GPU_enable_material(0, NULL);
2816 /* but set default spec */
2817 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2818 glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
2819 glColor3ub(120, 120, 120);
2820 glDisable(GL_COLOR_MATERIAL);
2822 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2823 glEnable(GL_LIGHTING);
2824 glEnable(GL_COLOR_MATERIAL);
2826 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2827 glDisable(GL_COLOR_MATERIAL);
2828 glDisable(GL_LIGHTING);
2830 GPU_disable_material();
2832 else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2834 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2836 glColor3f(1.0f, 1.0f, 1.0f);
2837 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2843 dl = ob->disp.first;
2844 if (!dl || !dl->col1) {
2845 /* release and reload derivedmesh because it might be freed in
2846 shadeDispList due to a different datamask */
2848 shadeDispList(scene, base);
2849 dl = find_displist(&ob->disp, DL_VERTCOL);
2850 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2853 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2854 draw_mesh_object_outline(v3d, ob, dm);
2857 /* False for dupliframe objects */
2859 unsigned int *obCol1 = dl->col1;
2860 unsigned int *obCol2 = dl->col2;
2862 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2865 if(base->flag & SELECT) {
2866 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2868 UI_ThemeColor(TH_WIRE);
2870 dm->drawLooseEdges(dm);
2874 /* set default draw color back for wire or for draw-extra later on */
2876 if(base->flag & SELECT) {
2877 if(ob==OBACT && ob->flag & OB_FROMGROUP)
2878 UI_ThemeColor(TH_GROUP_ACTIVE);
2879 else if(ob->flag & OB_FROMGROUP)
2880 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2881 else if(flag!=DRAW_CONSTCOLOR)
2882 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2884 glColor3ub(80,80,80);
2886 if (ob->flag & OB_FROMGROUP)
2887 UI_ThemeColor(TH_GROUP);
2889 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2890 glColor3ub(80,80,80);
2892 UI_ThemeColor(TH_WIRE);
2897 /* If drawing wire and drawtype is not OB_WIRE then we are
2898 * overlaying the wires.
2900 * UPDATE bug #10290 - With this wire-only objects can draw
2901 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2903 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2904 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2906 if (dt!=OB_WIRE && draw_wire==2) {
2907 bglPolygonOffset(rv3d->dist, 1.0);
2908 glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2911 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2913 if (dt!=OB_WIRE && draw_wire==2) {
2915 bglPolygonOffset(rv3d->dist, 0.0);
2922 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2923 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2925 Object *ob= base->object;
2926 Object *obedit= scene->obedit;
2928 EditMesh *em= me->edit_mesh;
2929 int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2931 if(obedit && ob!=obedit && ob->data==obedit->data) {
2936 if(ob==obedit || drawlinked) {
2937 DerivedMesh *finalDM, *cageDM;
2940 finalDM = cageDM = editmesh_get_derived_base(ob, em);