Merged changes in the trunk up to revision 44039.
[blender-staging.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30
31 #include <string.h>
32 #include <math.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_camera_types.h"
37 #include "DNA_curve_types.h"
38 #include "DNA_constraint_types.h" // for drawing constraint
39 #include "DNA_lamp_types.h"
40 #include "DNA_lattice_types.h"
41 #include "DNA_material_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_meta_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_smoke_types.h"
46 #include "DNA_speaker_types.h"
47 #include "DNA_world_types.h"
48 #include "DNA_armature_types.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_math.h"
52 #include "BLI_editVert.h"
53 #include "BLI_edgehash.h"
54 #include "BLI_rand.h"
55 #include "BLI_utildefines.h"
56
57 #include "BKE_anim.h"                   //for the where_on_path function
58 #include "BKE_camera.h"
59 #include "BKE_constraint.h" // for the get_constraint_target function
60 #include "BKE_curve.h"
61 #include "BKE_DerivedMesh.h"
62 #include "BKE_deform.h"
63 #include "BKE_displist.h"
64 #include "BKE_font.h"
65 #include "BKE_global.h"
66 #include "BKE_image.h"
67 #include "BKE_key.h"
68 #include "BKE_lattice.h"
69 #include "BKE_mesh.h"
70 #include "BKE_material.h"
71 #include "BKE_mball.h"
72 #include "BKE_modifier.h"
73 #include "BKE_object.h"
74 #include "BKE_paint.h"
75 #include "BKE_particle.h"
76 #include "BKE_pointcache.h"
77 #include "BKE_scene.h"
78 #include "BKE_unit.h"
79 #include "BKE_movieclip.h"
80 #include "BKE_tracking.h"
81
82 #include "smoke_API.h"
83
84 #include "IMB_imbuf.h"
85 #include "IMB_imbuf_types.h"
86
87 #include "BIF_gl.h"
88 #include "BIF_glutil.h"
89
90 #include "GPU_draw.h"
91 #include "GPU_extensions.h"
92
93 #include "ED_mesh.h"
94 #include "ED_particle.h"
95 #include "ED_screen.h"
96 #include "ED_sculpt.h"
97 #include "ED_types.h"
98 #include "ED_curve.h" /* for curve_editnurbs */
99
100 #include "UI_resources.h"
101
102 #include "WM_api.h"
103 #include "wm_subwindow.h"
104 #include "BLF_api.h"
105
106 #include "view3d_intern.h"      // own include
107
108
109 /* this condition has been made more complex since editmode can draw textures */
110 #define CHECK_OB_DRAWTEXTURE(vd, dt)                                          \
111         ((ELEM(vd->drawtype, OB_TEXTURE, OB_MATERIAL) && dt>OB_SOLID) ||          \
112         (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
113
114 typedef enum eWireDrawMode {
115         OBDRAW_WIRE_OFF= 0,
116         OBDRAW_WIRE_ON= 1,
117         OBDRAW_WIRE_ON_DEPTH= 2
118 } eWireDrawMode;
119
120 /* user data structures for derived mesh callbacks */
121 typedef struct foreachScreenVert_userData {
122         void (*func)(void *userData, EditVert *eve, int x, int y, int index);
123         void *userData;
124         ViewContext vc;
125         eV3DClipTest clipVerts;
126 } foreachScreenVert_userData;
127
128 typedef struct foreachScreenEdge_userData {
129         void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
130         void *userData;
131         ViewContext vc;
132         eV3DClipTest clipVerts;
133 } foreachScreenEdge_userData;
134
135 typedef struct foreachScreenFace_userData {
136         void (*func)(void *userData, EditFace *efa, int x, int y, int index);
137         void *userData;
138         ViewContext vc;
139 } foreachScreenFace_userData;
140
141 typedef struct drawDMVerts_userData {
142         int sel;
143         EditVert *eve_act;
144 } drawDMVerts_userData;
145
146 typedef struct drawDMEdgesSel_userData {
147         unsigned char *baseCol, *selCol, *actCol;
148         EditEdge *eed_act;
149 } drawDMEdgesSel_userData;
150
151 typedef struct drawDMFacesSel_userData {
152         unsigned char *cols[4];
153         EditFace *efa_act;
154         int *orig_index;
155 } drawDMFacesSel_userData;
156
157 typedef struct drawDMNormal_userData {
158         float normalsize;
159 } drawDMNormal_userData;
160
161 typedef struct bbsObmodeMeshVerts_userData {
162         void *offset;
163         MVert *mvert;
164 } bbsObmodeMeshVerts_userData;
165
166 static void draw_bounding_volume(Scene *scene, Object *ob, char type);
167
168 static void drawcube_size(float size);
169 static void drawcircle_size(float size);
170 static void draw_empty_sphere(float size);
171 static void draw_empty_cone(float size);
172
173 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
174 {
175         if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
176                 return 0;
177
178         if(G.f & G_BACKBUFSEL)
179                 return 0;
180
181         if((vd->flag & V3D_ZBUF_SELECT) == 0)
182                 return 1;
183
184         /* if its drawing textures with zbuf sel, then dont draw dots */
185         if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
186                 return 0;
187
188         if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
189                 return 0;
190
191         return 1;
192 }
193
194 /* ************* only use while object drawing **************
195  * or after running ED_view3d_init_mats_rv3d
196  * */
197 static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int local)
198 {
199         RegionView3D *rv3d= ar->regiondata;
200         float fx, fy, vec4[4];
201         
202         adr[0]= IS_CLIPPED;
203         
204         /* clipplanes in eye space */
205         if(rv3d->rflag & RV3D_CLIPPING) {
206                 if(ED_view3d_test_clipping(rv3d, vec, local))
207                         return;
208         }
209         
210         copy_v3_v3(vec4, vec);
211         vec4[3]= 1.0;
212         
213         mul_m4_v4(rv3d->persmatob, vec4);
214         
215         /* clipplanes in window space */
216         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
217                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
218                 
219                 if( fx>0 && fx<ar->winx) {
220                         
221                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
222                         
223                         if(fy > 0.0f && fy < (float)ar->winy) {
224                                 adr[0]= (short)floorf(fx);
225                                 adr[1]= (short)floorf(fy);
226                         }
227                 }
228         }
229 }
230
231 /* only use while object drawing */
232 static void view3d_project_short_noclip(ARegion *ar, const float vec[3], short adr[2])
233 {
234         RegionView3D *rv3d= ar->regiondata;
235         float fx, fy, vec4[4];
236         
237         adr[0]= IS_CLIPPED;
238         
239         copy_v3_v3(vec4, vec);
240         vec4[3]= 1.0;
241         
242         mul_m4_v4(rv3d->persmatob, vec4);
243         
244         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
245                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
246                 
247                 if( fx>-32700 && fx<32700) {
248                         
249                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
250                         
251                         if(fy > -32700.0f && fy < 32700.0f) {
252                                 adr[0]= (short)floorf(fx);
253                                 adr[1]= (short)floorf(fy);
254                         }
255                 }
256         }
257 }
258
259 /* same as view3d_project_short_clip but use persmat instead of persmatob for projection */
260 static void view3d_project_short_clip_persmat(ARegion *ar, float *vec, short adr[2], int local)
261 {
262         RegionView3D *rv3d= ar->regiondata;
263         float fx, fy, vec4[4];
264
265         adr[0]= IS_CLIPPED;
266
267         /* clipplanes in eye space */
268         if(rv3d->rflag & RV3D_CLIPPING) {
269                 if(ED_view3d_test_clipping(rv3d, vec, local))
270                         return;
271         }
272
273         copy_v3_v3(vec4, vec);
274         vec4[3]= 1.0;
275
276         mul_m4_v4(rv3d->persmat, vec4);
277
278         /* clipplanes in window space */
279         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
280                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
281
282                 if( fx>0 && fx<ar->winx) {
283
284                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
285
286                         if(fy > 0.0f && fy < (float)ar->winy) {
287                                 adr[0]= (short)floorf(fx);
288                                 adr[1]= (short)floorf(fy);
289                         }
290                 }
291         }
292 }
293 /* ************************ */
294
295 /* check for glsl drawing */
296
297 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
298 {
299         if(!GPU_glsl_support())
300                 return 0;
301         if(G.f & G_PICKSEL)
302                 return 0;
303         if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
304                 return 0;
305         if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
306                 return 0;
307         if(scene_use_new_shading_nodes(scene))
308                 return 0;
309         
310         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
311 }
312
313 static int check_alpha_pass(Base *base)
314 {
315         if(base->flag & OB_FROMDUPLI)
316                 return 0;
317
318         if(G.f & G_PICKSEL)
319                 return 0;
320         
321         return (base->object->dtx & OB_DRAWTRANSP);
322 }
323
324         /***/
325 static unsigned int colortab[24]=
326         {0x0,           0xFF88FF, 0xFFBBFF, 
327          0x403000,      0xFFFF88, 0xFFFFBB, 
328          0x104040,      0x66CCCC, 0x77CCCC, 
329          0x104010,      0x55BB55, 0x66FF66, 
330          0xFFFFFF
331 };
332
333
334 static float cube[8][3] = {
335         {-1.0, -1.0, -1.0},
336         {-1.0, -1.0,  1.0},
337         {-1.0,  1.0,  1.0},
338         {-1.0,  1.0, -1.0},
339         { 1.0, -1.0, -1.0},
340         { 1.0, -1.0,  1.0},
341         { 1.0,  1.0,  1.0},
342         { 1.0,  1.0, -1.0},
343 };
344
345 /* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
346 /* 32 values of sin function (still same result!) */
347 #define CIRCLE_RESOL 32
348
349 static const float sinval[CIRCLE_RESOL] = {
350         0.00000000,
351         0.20129852,
352         0.39435585,
353         0.57126821,
354         0.72479278,
355         0.84864425,
356         0.93775213,
357         0.98846832,
358         0.99871650,
359         0.96807711,
360         0.89780453,
361         0.79077573,
362         0.65137248,
363         0.48530196,
364         0.29936312,
365         0.10116832,
366         -0.10116832,
367         -0.29936312,
368         -0.48530196,
369         -0.65137248,
370         -0.79077573,
371         -0.89780453,
372         -0.96807711,
373         -0.99871650,
374         -0.98846832,
375         -0.93775213,
376         -0.84864425,
377         -0.72479278,
378         -0.57126821,
379         -0.39435585,
380         -0.20129852,
381         0.00000000
382 };
383
384 /* 32 values of cos function (still same result!) */
385 static const float cosval[CIRCLE_RESOL] = {
386         1.00000000,
387         0.97952994,
388         0.91895781,
389         0.82076344,
390         0.68896691,
391         0.52896401,
392         0.34730525,
393         0.15142777,
394         -0.05064916,
395         -0.25065253,
396         -0.44039415,
397         -0.61210598,
398         -0.75875812,
399         -0.87434661,
400         -0.95413925,
401         -0.99486932,
402         -0.99486932,
403         -0.95413925,
404         -0.87434661,
405         -0.75875812,
406         -0.61210598,
407         -0.44039415,
408         -0.25065253,
409         -0.05064916,
410         0.15142777,
411         0.34730525,
412         0.52896401,
413         0.68896691,
414         0.82076344,
415         0.91895781,
416         0.97952994,
417         1.00000000
418 };
419
420 static void draw_xyz_wire(const float c[3], float size, int axis)
421 {
422         float v1[3]= {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
423         float dim = size * 0.1f;
424         float dx[3], dy[3], dz[3];
425
426         dx[0]=dim; dx[1]=0.f; dx[2]=0.f;
427         dy[0]=0.f; dy[1]=dim; dy[2]=0.f;
428         dz[0]=0.f; dz[1]=0.f; dz[2]=dim;
429
430         switch(axis) {
431                 case 0:         /* x axis */
432                         glBegin(GL_LINES);
433                         
434                         /* bottom left to top right */
435                         sub_v3_v3v3(v1, c, dx);
436                         sub_v3_v3(v1, dy);
437                         add_v3_v3v3(v2, c, dx);
438                         add_v3_v3(v2, dy);
439                         
440                         glVertex3fv(v1);
441                         glVertex3fv(v2);
442                         
443                         /* top left to bottom right */
444                         mul_v3_fl(dy, 2.f);
445                         add_v3_v3(v1, dy);
446                         sub_v3_v3(v2, dy);
447                         
448                         glVertex3fv(v1);
449                         glVertex3fv(v2);
450                         
451                         glEnd();
452                         break;
453                 case 1:         /* y axis */
454                         glBegin(GL_LINES);
455                         
456                         /* bottom left to top right */
457                         mul_v3_fl(dx, 0.75f);
458                         sub_v3_v3v3(v1, c, dx);
459                         sub_v3_v3(v1, dy);
460                         add_v3_v3v3(v2, c, dx);
461                         add_v3_v3(v2, dy);
462                         
463                         glVertex3fv(v1);
464                         glVertex3fv(v2);
465                         
466                         /* top left to center */
467                         mul_v3_fl(dy, 2.f);
468                         add_v3_v3(v1, dy);
469                         copy_v3_v3(v2, c);
470                         
471                         glVertex3fv(v1);
472                         glVertex3fv(v2);
473                         
474                         glEnd();
475                         break;
476                 case 2:         /* z axis */
477                         glBegin(GL_LINE_STRIP);
478                         
479                         /* start at top left */
480                         sub_v3_v3v3(v1, c, dx);
481                         add_v3_v3v3(v1, c, dz);
482                         
483                         glVertex3fv(v1);
484                         
485                         mul_v3_fl(dx, 2.f);
486                         add_v3_v3(v1, dx);
487
488                         glVertex3fv(v1);
489                         
490                         mul_v3_fl(dz, 2.f);
491                         sub_v3_v3(v1, dx);
492                         sub_v3_v3(v1, dz);
493                         
494                         glVertex3fv(v1);
495                         
496                         add_v3_v3(v1, dx);
497                 
498                         glVertex3fv(v1);
499                         
500                         glEnd();
501                         break;
502         }
503         
504 }
505
506 void drawaxes(float size, char drawtype)
507 {
508         int axis;
509         float v1[3]= {0.0, 0.0, 0.0};
510         float v2[3]= {0.0, 0.0, 0.0};
511         float v3[3]= {0.0, 0.0, 0.0};
512         
513         switch(drawtype) {
514         
515         case OB_PLAINAXES:
516                 for (axis=0; axis<3; axis++) {
517                         glBegin(GL_LINES);
518                         
519                         v1[axis]= size;
520                         v2[axis]= -size;
521                         glVertex3fv(v1);
522                         glVertex3fv(v2);
523
524                         /* reset v1 & v2 to zero */
525                         v1[axis]= v2[axis]= 0.0f;
526
527                         glEnd();
528                 }
529                 break;
530         case OB_SINGLE_ARROW:
531         
532                 glBegin(GL_LINES);
533                 /* in positive z direction only */
534                 v1[2]= size;
535                 glVertex3fv(v1);
536                 glVertex3fv(v2);
537                 glEnd();
538                 
539                 /* square pyramid */
540                 glBegin(GL_TRIANGLES);
541                 
542                 v2[0]= size * 0.035f; v2[1] = size * 0.035f;
543                 v3[0]= size * -0.035f; v3[1] = size * 0.035f;
544                 v2[2]= v3[2]= size * 0.75f;
545                 
546                 for (axis=0; axis<4; axis++) {
547                         if (axis % 2 == 1) {
548                                 v2[0] = -v2[0];
549                                 v3[1] = -v3[1];
550                         } else {
551                                 v2[1] = -v2[1];
552                                 v3[0] = -v3[0];
553                         }
554                         
555                         glVertex3fv(v1);
556                         glVertex3fv(v2);
557                         glVertex3fv(v3);
558                         
559                 }
560                 glEnd();
561                 
562                 break;
563         case OB_CUBE:
564                 drawcube_size(size);
565                 break;
566                 
567         case OB_CIRCLE:
568                 drawcircle_size(size);
569                 break;
570         
571         case OB_EMPTY_SPHERE:
572                 draw_empty_sphere(size);
573                 break;
574
575         case OB_EMPTY_CONE:
576                 draw_empty_cone(size);
577                 break;
578
579         case OB_ARROWS:
580         default:
581                 for (axis=0; axis<3; axis++) {
582                         const int arrow_axis= (axis==0) ? 1:0;
583
584                         glBegin(GL_LINES);
585                         
586                         v2[axis]= size;
587                         glVertex3fv(v1);
588                         glVertex3fv(v2);
589                                 
590                         v1[axis]= size*0.85f;
591                         v1[arrow_axis]= -size*0.08f;
592                         glVertex3fv(v1);
593                         glVertex3fv(v2);
594                                 
595                         v1[arrow_axis]= size*0.08f;
596                         glVertex3fv(v1);
597                         glVertex3fv(v2);
598                         
599                         glEnd();
600                                 
601                         v2[axis]+= size*0.125f;
602                         
603                         draw_xyz_wire(v2, size, axis);
604                         
605                         
606                         /* reset v1 & v2 to zero */
607                         v1[arrow_axis]= v1[axis]= v2[axis]= 0.0f;
608                 }
609                 break;
610         }
611 }
612
613
614 /* Function to draw an Image on a empty Object */
615 static void draw_empty_image(Object *ob)
616 {
617         Image *ima = (Image*)ob->data;
618         ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
619
620         float scale, ofs_x, ofs_y, sca_x, sca_y;
621         int ima_x, ima_y;
622
623         if(ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
624                 IMB_rect_from_float(ibuf);
625         }
626
627         /* Get the buffer dimensions so we can fallback to fake ones */
628         if(ibuf && ibuf->rect) {
629                 ima_x= ibuf->x;
630                 ima_y= ibuf->y;
631         }
632         else {
633                 ima_x= 1;
634                 ima_y= 1;
635         }
636
637         /* Get the image aspect even if the buffer is invalid */
638         if(ima) {
639                 if(ima->aspx > ima->aspy) {
640                         sca_x= 1.0f;
641                         sca_y= ima->aspy / ima->aspx;
642                 }
643                 else if(ima->aspx < ima->aspy) {
644                         sca_x= ima->aspx / ima->aspy;
645                         sca_y= 1.0f;
646                 }
647                 else {
648                         sca_x= 1.0f;
649                         sca_y= 1.0f;
650                 }
651         }
652         else {
653                 sca_x= 1.0f;
654                 sca_y= 1.0f;
655         }
656
657         /* Calculate the scale center based on objects origin */
658         ofs_x= ob->ima_ofs[0] * ima_x;
659         ofs_y= ob->ima_ofs[1] * ima_y;
660
661         glMatrixMode(GL_MODELVIEW);
662         glPushMatrix();
663
664         /* Make sure we are drawing at the origin */
665         glTranslatef(0.0f,  0.0f,  0.0f);
666
667         /* Calculate Image scale */
668         scale= (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
669
670         /* Set the object scale */
671         glScalef(scale * sca_x, scale * sca_y, 1.0f);
672
673         if(ibuf && ibuf->rect) {
674                 /* Setup GL params */
675                 glEnable(GL_BLEND);
676                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
677
678                 /* Use the object color and alpha */
679                 glColor4fv(ob->col);
680
681                 /* Draw the Image on the screen */
682                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
683                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
684
685                 glDisable(GL_BLEND);
686         }
687
688         UI_ThemeColor((ob->flag & SELECT) ? TH_SELECT : TH_WIRE);
689
690         /* Calculate the outline vertex positions */
691         glBegin(GL_LINE_LOOP);
692         glVertex2f(ofs_x, ofs_y);
693         glVertex2f(ofs_x + ima_x, ofs_y);
694         glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
695         glVertex2f(ofs_x, ofs_y + ima_y);
696         glEnd();
697
698         /* Reset GL settings */
699         glMatrixMode(GL_MODELVIEW);
700         glPopMatrix();
701 }
702
703 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
704 {
705         float vx[3], vy[3];
706         float *viter= (float *)verts;
707         unsigned int a;
708
709         mul_v3_v3fl(vx, tmat[0], rad);
710         mul_v3_v3fl(vy, tmat[1], rad);
711
712         for (a=0; a < CIRCLE_RESOL; a++, viter += 3) {
713                 viter[0]= cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
714                 viter[1]= cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
715                 viter[2]= cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
716         }
717 }
718
719 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
720 {
721         float verts[CIRCLE_RESOL][3];
722
723         circball_array_fill(verts, cent, rad, tmat);
724
725         glEnableClientState(GL_VERTEX_ARRAY);
726         glVertexPointer(3, GL_FLOAT, 0, verts);
727         glDrawArrays(mode, 0, CIRCLE_RESOL);
728         glDisableClientState(GL_VERTEX_ARRAY);
729 }
730
731 /* circle for object centers, special_color is for library or ob users */
732 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
733 {
734         const float size= ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
735         float verts[CIRCLE_RESOL][3];
736
737         /* using gldepthfunc guarantees that it does write z values,
738          * but not checks for it, so centers remain visible independt order of drawing */
739         if(v3d->zbuf)  glDepthFunc(GL_ALWAYS);
740         glEnable(GL_BLEND);
741         
742         if(special_color) {
743                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
744
745                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
746         }
747         else {
748                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
749                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
750                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
751         }
752
753         circball_array_fill(verts, co, size, rv3d->viewinv);
754
755         /* enable vertex array */
756         glEnableClientState(GL_VERTEX_ARRAY);
757         glVertexPointer(3, GL_FLOAT, 0, verts);
758
759         /* 1. draw filled, blended polygon */
760         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
761
762         /* 2. draw outline */
763         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
764         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
765
766         /* finishe up */
767         glDisableClientState(GL_VERTEX_ARRAY);
768
769         glDisable(GL_BLEND);
770
771         if(v3d->zbuf)  glDepthFunc(GL_LEQUAL);
772 }
773
774 /* *********** text drawing for object/particles/armature ************* */
775 static ListBase CachedText[3];
776 static int CachedTextLevel= 0;
777
778 typedef struct ViewCachedString {
779         struct ViewCachedString *next, *prev;
780         float vec[3];
781         union {
782                 unsigned char ub[4];
783                 int pack;
784         } col;
785         short sco[2];
786         short xoffs;
787         short flag;
788         int str_len, pad;
789         /* str is allocated past the end */
790 } ViewCachedString;
791
792 void view3d_cached_text_draw_begin(void)
793 {
794         ListBase *strings= &CachedText[CachedTextLevel];
795         strings->first= strings->last= NULL;
796         CachedTextLevel++;
797 }
798
799 void view3d_cached_text_draw_add(const float co[3],
800                                  const char *str,
801                                  short xoffs, short flag,
802                                  const unsigned char col[4])
803 {
804         int alloc_len= strlen(str) + 1;
805         ListBase *strings= &CachedText[CachedTextLevel-1];
806         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
807         ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
808
809         BLI_addtail(strings, vos);
810         copy_v3_v3(vos->vec, co);
811         vos->col.pack= *((int *)col);
812         vos->xoffs= xoffs;
813         vos->flag= flag;
814         vos->str_len= alloc_len-1;
815
816         /* allocate past the end */
817         memcpy(++vos, str, alloc_len);
818 }
819
820 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
821 {
822         RegionView3D *rv3d= ar->regiondata;
823         ListBase *strings= &CachedText[CachedTextLevel-1];
824         ViewCachedString *vos;
825         int a, tot= 0;
826         
827         /* project first and test */
828         for(vos= strings->first; vos; vos= vos->next) {
829                 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
830                         mul_m4_v3(mat, vos->vec);
831
832                 if(vos->flag&V3D_CACHE_TEXT_GLOBALSPACE)
833                         view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, 0);
834                 else
835                         view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
836
837                 if(vos->sco[0]!=IS_CLIPPED)
838                         tot++;
839         }
840
841         if(tot) {
842                 int col_pack_prev= 0;
843
844 #if 0
845                 bglMats mats; /* ZBuffer depth vars */
846                 double ux, uy, uz;
847                 float depth;
848
849                 if(v3d->zbuf)
850                         bgl_get_mats(&mats);
851 #endif
852                 if(rv3d->rflag & RV3D_CLIPPING)
853                         for(a=0; a<6; a++)
854                                 glDisable(GL_CLIP_PLANE0+a);
855                 
856                 glMatrixMode(GL_PROJECTION);
857                 glPushMatrix();
858                 glMatrixMode(GL_MODELVIEW);
859                 glPushMatrix();
860                 ED_region_pixelspace(ar);
861                 
862                 if(depth_write) {
863                         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
864                 }
865                 else glDepthMask(0);
866                 
867                 for(vos= strings->first; vos; vos= vos->next) {
868                         /* too slow, reading opengl info while drawing is very bad,
869                          * better to see if we can use the zbuffer while in pixel space - campbell */
870 #if 0
871                         if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
872                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
873                                 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
874
875                                 if(uz > depth)
876                                         continue;
877                         }
878 #endif
879                         if(vos->sco[0]!=IS_CLIPPED) {
880                                 const char *str= (char *)(vos+1);
881
882                                 if(col_pack_prev != vos->col.pack) {
883                                         glColor3ubv(vos->col.ub);
884                                         col_pack_prev= vos->col.pack;
885                                 }
886                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
887                                             BLF_draw_default_ascii :
888                                             BLF_draw_default
889                                             ) ( (float)vos->sco[0] + vos->xoffs,
890                                                 (float)vos->sco[1],
891                                                 (depth_write) ? 0.0f: 2.0f,
892                                                 str,
893                                                 vos->str_len);
894                         }
895                 }
896                 
897                 if(depth_write) {
898                         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
899                 }
900                 else glDepthMask(1);
901                 
902                 glMatrixMode(GL_PROJECTION);
903                 glPopMatrix();
904                 glMatrixMode(GL_MODELVIEW);
905                 glPopMatrix();
906
907                 if(rv3d->rflag & RV3D_CLIPPING)
908                         for(a=0; a<6; a++)
909                                 glEnable(GL_CLIP_PLANE0+a);
910         }
911         
912         if(strings->first) 
913                 BLI_freelistN(strings);
914         
915         CachedTextLevel--;
916 }
917
918 /* ******************** primitive drawing ******************* */
919
920 static void drawcube(void)
921 {
922
923         glBegin(GL_LINE_STRIP);
924                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
925                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
926                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
927         glEnd();
928
929         glBegin(GL_LINE_STRIP);
930                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
931         glEnd();
932
933         glBegin(GL_LINE_STRIP);
934                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
935         glEnd();
936
937         glBegin(GL_LINE_STRIP);
938                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
939         glEnd();
940 }
941
942 /* draws a cube on given the scaling of the cube, assuming that 
943  * all required matrices have been set (used for drawing empties)
944  */
945 static void drawcube_size(float size)
946 {
947         glBegin(GL_LINE_STRIP);
948                 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);
949                 glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
950
951                 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);
952                 glVertex3f(size,-size,size); glVertex3f(size,size,size);
953
954                 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
955         glEnd();
956
957         glBegin(GL_LINE_STRIP);
958                 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
959         glEnd();
960
961         glBegin(GL_LINE_STRIP);
962                 glVertex3f(-size,size,size); glVertex3f(size,size,size);
963         glEnd();
964
965         glBegin(GL_LINE_STRIP);
966                 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
967         glEnd();
968 }
969
970 /* this is an unused (old) cube-drawing function based on a given size */
971 #if 0
972 static void drawcube_size(const float size[3])
973 {
974
975         glPushMatrix();
976         glScalef(size[0],  size[1],  size[2]);
977         
978
979         glBegin(GL_LINE_STRIP);
980                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
981                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
982                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
983         glEnd();
984
985         glBegin(GL_LINE_STRIP);
986                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
987         glEnd();
988
989         glBegin(GL_LINE_STRIP);
990                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
991         glEnd();
992
993         glBegin(GL_LINE_STRIP);
994                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
995         glEnd();
996         
997         glPopMatrix();
998 }
999 #endif
1000
1001 static void drawshadbuflimits(Lamp *la, float mat[][4])
1002 {
1003         float sta[3], end[3], lavec[3];
1004
1005         negate_v3_v3(lavec, mat[2]);
1006         normalize_v3(lavec);
1007
1008         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
1009         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
1010
1011         glBegin(GL_LINE_STRIP);
1012                 glVertex3fv(sta);
1013                 glVertex3fv(end);
1014         glEnd();
1015
1016         glPointSize(3.0);
1017         bglBegin(GL_POINTS);
1018         bglVertex3fv(sta);
1019         bglVertex3fv(end);
1020         bglEnd();
1021         glPointSize(1.0);
1022 }
1023
1024
1025
1026 static void spotvolume(float lvec[3], float vvec[3], const float inp)
1027 {
1028         /* camera is at 0,0,0 */
1029         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
1030
1031         normalize_v3(lvec);
1032         normalize_v3(vvec);                             /* is this the correct vector ? */
1033
1034         cross_v3_v3v3(temp,vvec,lvec);          /* equation for a plane through vvec en lvec */
1035         cross_v3_v3v3(plane,lvec,temp);         /* a plane perpendicular to this, parrallel with lvec */
1036
1037         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1038         if(normalize_v3(plane) == 0.0f)
1039                 plane[1]= 1.0f;
1040
1041         /* now we've got two equations: one of a cone and one of a plane, but we have
1042         three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
1043
1044         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1045         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1046
1047         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1048         
1049         q[1] = plane[1] ; 
1050         q[2] = -plane[0] ; 
1051         q[3] = 0 ;
1052         normalize_v3(&q[1]);
1053
1054         angle = saacos(plane[2])/2.0f;
1055         co = cosf(angle);
1056         si = sqrtf(1-co*co);
1057
1058         q[0] =  co;
1059         q[1] *= si;
1060         q[2] *= si;
1061         q[3] =  0;
1062
1063         quat_to_mat3(mat1,q);
1064
1065         /* rotate lamp vector now over acos(inp) degrees */
1066         copy_v3_v3(vvec, lvec);
1067
1068         unit_m3(mat2);
1069         co = inp;
1070         si = sqrtf(1.0f-inp*inp);
1071
1072         mat2[0][0] =  co;
1073         mat2[1][0] = -si;
1074         mat2[0][1] =  si;
1075         mat2[1][1] =  co;
1076         mul_m3_m3m3(mat3,mat2,mat1);
1077
1078         mat2[1][0] =  si;
1079         mat2[0][1] = -si;
1080         mul_m3_m3m3(mat4,mat2,mat1);
1081         transpose_m3(mat1);
1082
1083         mul_m3_m3m3(mat2,mat1,mat3);
1084         mul_m3_v3(mat2,lvec);
1085         mul_m3_m3m3(mat2,mat1,mat4);
1086         mul_m3_v3(mat2,vvec);
1087
1088         return;
1089 }
1090
1091 static void draw_spot_cone(Lamp *la, float x, float z)
1092 {
1093         z= fabs(z);
1094
1095         glBegin(GL_TRIANGLE_FAN);
1096         glVertex3f(0.0f, 0.0f, -x);
1097
1098         if(la->mode & LA_SQUARE) {
1099                 glVertex3f(z, z, 0);
1100                 glVertex3f(-z, z, 0);
1101                 glVertex3f(-z, -z, 0);
1102                 glVertex3f(z, -z, 0);
1103                 glVertex3f(z, z, 0);
1104         }
1105         else {
1106                 float angle;
1107                 int a;
1108
1109                 for(a=0; a<33; a++) {
1110                         angle= a*M_PI*2/(33-1);
1111                         glVertex3f(z*cosf(angle), z*sinf(angle), 0);
1112                 }
1113         }
1114
1115         glEnd();
1116 }
1117
1118 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1119 {
1120         glEnable(GL_CULL_FACE);
1121         glEnable(GL_BLEND);
1122         glDepthMask(0);
1123
1124         /* draw backside darkening */
1125         glCullFace(GL_FRONT);
1126
1127         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1128         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1129
1130         draw_spot_cone(la, x, z);
1131
1132         /* draw front side lighting */
1133         glCullFace(GL_BACK);
1134
1135         glBlendFunc(GL_ONE,  GL_ONE); 
1136         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1137
1138         draw_spot_cone(la, x, z);
1139
1140         /* restore state */
1141         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1142         glDisable(GL_BLEND);
1143         glDepthMask(1);
1144         glDisable(GL_CULL_FACE);
1145         glCullFace(GL_BACK);
1146 }
1147
1148 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1149 {
1150         Object *ob= base->object;
1151         const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1152         Lamp *la= ob->data;
1153         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1154         float lampsize;
1155         float imat[4][4], curcol[4];
1156         unsigned char col[4];
1157         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1158         /* the moment of view3d_draw_transp() call */
1159         const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1160         const short drawcone= ((dt > OB_WIRE) &&
1161                                !(G.f & G_PICKSEL) &&
1162                                (la->type == LA_SPOT) &&
1163                                (la->mode & LA_SHOW_CONE) &&
1164                                !(base->flag & OB_FROMDUPLI) &&
1165                                !is_view);
1166
1167         if(drawcone && !v3d->transp) {
1168                 /* in this case we need to draw delayed */
1169                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1170                 return;
1171         }
1172         
1173         /* we first draw only the screen aligned & fixed scale stuff */
1174         glPushMatrix();
1175         glLoadMatrixf(rv3d->viewmat);
1176
1177         /* lets calculate the scale: */
1178         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1179
1180         /* and view aligned matrix: */
1181         copy_m4_m4(imat, rv3d->viewinv);
1182         normalize_v3(imat[0]);
1183         normalize_v3(imat[1]);
1184
1185         /* lamp center */
1186         copy_v3_v3(vec, ob->obmat[3]);
1187         
1188         /* for AA effects */
1189         glGetFloatv(GL_CURRENT_COLOR, curcol);
1190         curcol[3]= 0.6;
1191         glColor4fv(curcol);
1192         
1193         if(lampsize > 0.0f) {
1194
1195                 if(ob->id.us>1) {
1196                         if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1197                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
1198                 }
1199                 
1200                 /* Inner Circle */
1201                 glEnable(GL_BLEND);
1202                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1203                 glDisable(GL_BLEND);
1204                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1205                 
1206                 /* restore */
1207                 if(ob->id.us>1)
1208                         glColor4fv(curcol);
1209                         
1210                 /* Outer circle */
1211                 circrad = 3.0f*lampsize;
1212                 setlinestyle(3);
1213
1214                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1215
1216                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1217                 if(la->type!=LA_HEMI) {
1218                         if(     (la->mode & LA_SHAD_RAY) ||
1219                                 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1220                         ) {
1221                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1222                         }
1223                 }
1224         }
1225         else {
1226                 setlinestyle(3);
1227                 circrad = 0.0f;
1228         }
1229         
1230         /* draw the pretty sun rays */
1231         if(la->type==LA_SUN) {
1232                 float v1[3], v2[3], mat[3][3];
1233                 short axis;
1234                 
1235                 /* setup a 45 degree rotation matrix */
1236                 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1237                 
1238                 /* vectors */
1239                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1240                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1241                 
1242                 /* center */
1243                 glTranslatef(vec[0], vec[1], vec[2]);
1244                 
1245                 setlinestyle(3);
1246                 
1247                 glBegin(GL_LINES);
1248                 for (axis=0; axis<8; axis++) {
1249                         glVertex3fv(v1);
1250                         glVertex3fv(v2);
1251                         mul_m3_v3(mat, v1);
1252                         mul_m3_v3(mat, v2);
1253                 }
1254                 glEnd();
1255                 
1256                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1257
1258         }               
1259         
1260         if (la->type==LA_LOCAL) {
1261                 if(la->mode & LA_SPHERE) {
1262                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1263                 }
1264                 /* yafray: for photonlight also draw lightcone as for spot */
1265         }
1266         
1267         glPopMatrix();  /* back in object space */
1268         zero_v3(vec);
1269         
1270         if(is_view) {
1271                 /* skip drawing extra info */
1272         }
1273         else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1274                 lvec[0]=lvec[1]= 0.0; 
1275                 lvec[2] = 1.0;
1276                 x = rv3d->persmat[0][2];
1277                 y = rv3d->persmat[1][2];
1278                 z = rv3d->persmat[2][2];
1279                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1280                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1281                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1282
1283                 y = cosf(la->spotsize*(float)(M_PI/360.0));
1284                 spotvolume(lvec, vvec, y);
1285                 x = -la->dist;
1286                 mul_v3_fl(lvec, x);
1287                 mul_v3_fl(vvec, x);
1288
1289                 /* draw the angled sides of the cone */
1290                 glBegin(GL_LINE_STRIP);
1291                         glVertex3fv(vvec);
1292                         glVertex3fv(vec);
1293                         glVertex3fv(lvec);
1294                 glEnd();
1295                 
1296                 z = x*sqrtf(1.0f - y*y);
1297                 x *= y;
1298
1299                 /* draw the circle/square at the end of the cone */
1300                 glTranslatef(0.0, 0.0 ,  x);
1301                 if(la->mode & LA_SQUARE) {
1302                         float tvec[3];
1303                         float z_abs= fabs(z);
1304
1305                         tvec[0]= tvec[1]= z_abs;
1306                         tvec[2]= 0.0;
1307
1308                         glBegin(GL_LINE_LOOP);
1309                                 glVertex3fv(tvec);
1310                                 tvec[1]= -z_abs; /* neg */
1311                                 glVertex3fv(tvec);
1312                                 tvec[0]= -z_abs; /* neg */
1313                                 glVertex3fv(tvec);
1314                                 tvec[1]= z_abs; /* pos */
1315                                 glVertex3fv(tvec);
1316                         glEnd();
1317                 }
1318                 else circ(0.0, 0.0, fabsf(z));
1319                 
1320                 /* draw the circle/square representing spotbl */
1321                 if(la->type==LA_SPOT) {
1322                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1323                         /* hide line if it is zero size or overlaps with outer border,
1324                            previously it adjusted to always to show it but that seems
1325                            confusing because it doesn't show the actual blend size */
1326                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1327                                 circ(0.0, 0.0, spotblcirc);
1328                 }
1329
1330                 if(drawcone)
1331                         draw_transp_spot_volume(la, x, z);
1332
1333                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1334                 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1335                 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1336                         float lvec_clip[3];
1337                         float vvec_clip[3];
1338                         float clipsta_fac= la->clipsta / -x;
1339
1340                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1341                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1342
1343                         glBegin(GL_LINE_STRIP);
1344                                 glVertex3fv(lvec_clip);
1345                                 glVertex3fv(vvec_clip);
1346                         glEnd();
1347                 }
1348         }
1349         else if ELEM(la->type, LA_HEMI, LA_SUN) {
1350                 
1351                 /* draw the line from the circle along the dist */
1352                 glBegin(GL_LINE_STRIP);
1353                         vec[2] = -circrad;
1354                         glVertex3fv(vec); 
1355                         vec[2]= -la->dist; 
1356                         glVertex3fv(vec);
1357                 glEnd();
1358                 
1359                 if(la->type==LA_HEMI) {
1360                         /* draw the hemisphere curves */
1361                         short axis, steps, dir;
1362                         float outdist, zdist, mul;
1363                         zero_v3(vec);
1364                         outdist = 0.14; mul = 1.4; dir = 1;
1365                         
1366                         setlinestyle(4);
1367                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1368                         for (axis=0; axis<4; axis++) {
1369                                 float v[3]= {0.0, 0.0, 0.0};
1370                                 zdist = 0.02;
1371                                 
1372                                 glBegin(GL_LINE_STRIP);
1373                                 
1374                                 for (steps=0; steps<6; steps++) {
1375                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
1376                                                 /* make the arcs start at the edge of the energy circle */
1377                                                 if (steps == 0) v[0] = dir*circrad;
1378                                                 else v[0] = v[0] + dir*(steps*outdist);
1379                                         } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
1380                                                 /* make the arcs start at the edge of the energy circle */
1381                                                 if (steps == 0) v[1] = dir*circrad;
1382                                                 else v[1] = v[1] + dir*(steps*outdist); 
1383                                         }
1384                 
1385                                         v[2] = v[2] - steps*zdist;
1386                                         
1387                                         glVertex3fv(v);
1388                                         
1389                                         zdist = zdist * mul;
1390                                 }
1391                                 
1392                                 glEnd();
1393                                 /* flip the direction */
1394                                 dir = -dir;
1395                         }
1396                 }
1397         } else if(la->type==LA_AREA) {
1398                 setlinestyle(3);
1399                 if(la->area_shape==LA_AREA_SQUARE) 
1400                         fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1401                 else if(la->area_shape==LA_AREA_RECT) 
1402                         fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1403
1404                 glBegin(GL_LINE_STRIP); 
1405                 glVertex3f(0.0,0.0,-circrad);
1406                 glVertex3f(0.0,0.0,-la->dist);
1407                 glEnd();
1408         }
1409         
1410         /* and back to viewspace */
1411         glLoadMatrixf(rv3d->viewmat);
1412         copy_v3_v3(vec, ob->obmat[3]);
1413
1414         setlinestyle(0);
1415         
1416         if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1417                 drawshadbuflimits(la, ob->obmat);
1418         }
1419         
1420         UI_GetThemeColor4ubv(TH_LAMP, col);
1421         glColor4ubv(col);
1422          
1423         glEnable(GL_BLEND);
1424         
1425         if (vec[2]>0) vec[2] -= circrad;
1426         else vec[2] += circrad;
1427         
1428         glBegin(GL_LINE_STRIP);
1429                 glVertex3fv(vec); 
1430                 vec[2]= 0; 
1431                 glVertex3fv(vec);
1432         glEnd();
1433         
1434         glPointSize(2.0);
1435         glBegin(GL_POINTS);
1436                 glVertex3fv(vec);
1437         glEnd();
1438         glPointSize(1.0);
1439         
1440         glDisable(GL_BLEND);
1441         
1442         /* restore for drawing extra stuff */
1443         glColor3fv(curcol);
1444
1445 }
1446
1447 static void draw_limit_line(float sta, float end, unsigned int col)
1448 {
1449         glBegin(GL_LINES);
1450         glVertex3f(0.0, 0.0, -sta);
1451         glVertex3f(0.0, 0.0, -end);
1452         glEnd();
1453
1454         glPointSize(3.0);
1455         glBegin(GL_POINTS);
1456         cpack(col);
1457         glVertex3f(0.0, 0.0, -sta);
1458         glVertex3f(0.0, 0.0, -end);
1459         glEnd();
1460         glPointSize(1.0);
1461 }               
1462
1463
1464 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1465 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1466 static void draw_focus_cross(float dist, float size)
1467 {
1468         glBegin(GL_LINES);
1469         glVertex3f(-size, 0.f, -dist);
1470         glVertex3f(size, 0.f, -dist);
1471         glVertex3f(0.f, -size, -dist);
1472         glVertex3f(0.f, size, -dist);
1473         glEnd();
1474 }
1475
1476 #ifdef VIEW3D_CAMERA_BORDER_HACK
1477 float view3d_camera_border_hack_col[4];
1478 short view3d_camera_border_hack_test= FALSE;
1479 #endif
1480
1481 /* ****************** draw clip data *************** */
1482
1483 static void draw_bundle_sphere(void)
1484 {
1485         static GLuint displist= 0;
1486
1487         if (displist == 0) {
1488                 GLUquadricObj *qobj;
1489
1490                 displist= glGenLists(1);
1491                 glNewList(displist, GL_COMPILE);
1492
1493                 qobj= gluNewQuadric();
1494                 gluQuadricDrawStyle(qobj, GLU_FILL);
1495                 glShadeModel(GL_SMOOTH);
1496                 gluSphere(qobj, 0.05, 8, 8);
1497                 glShadeModel(GL_FLAT);
1498                 gluDeleteQuadric(qobj);
1499
1500                 glEndList();
1501         }
1502
1503         glCallList(displist);
1504 }
1505
1506 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1507                         MovieClip *clip, MovieTrackingObject *tracking_object, int flag, int *global_track_index)
1508 {
1509         MovieTracking *tracking= &clip->tracking;
1510         MovieTrackingTrack *track;
1511         float mat[4][4], imat[4][4];
1512         unsigned char col[4], scol[4];
1513         int tracknr= *global_track_index;
1514         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
1515
1516         UI_GetThemeColor4ubv(TH_TEXT, col);
1517         UI_GetThemeColor4ubv(TH_SELECT, scol);
1518
1519         BKE_get_tracking_mat(scene, base->object, mat);
1520
1521         glPushMatrix();
1522
1523         if(tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1524                 /* current ogl matrix is translated in camera space, bundles should
1525                    be rendered in world space, so camera matrix should be "removed"
1526                    from current ogl matrix */
1527                 invert_m4_m4(imat, base->object->obmat);
1528
1529                 glMultMatrixf(imat);
1530                 glMultMatrixf(mat);
1531         }
1532         else {
1533                 float obmat[4][4];
1534
1535                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1536
1537                 invert_m4_m4(imat, obmat);
1538                 glMultMatrixf(imat);
1539         }
1540
1541         for (track= tracksbase->first; track; track= track->next) {
1542                 int selected= TRACK_SELECTED(track);
1543
1544                 if((track->flag&TRACK_HAS_BUNDLE)==0)
1545                         continue;
1546
1547                 if(flag&DRAW_PICKING)
1548                         glLoadName(base->selcol + (tracknr<<16));
1549
1550                 glPushMatrix();
1551                         glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1552                         glScalef(v3d->bundle_size/0.05f, v3d->bundle_size/0.05f, v3d->bundle_size/0.05f);
1553
1554                         if(v3d->drawtype==OB_WIRE) {
1555                                 glDisable(GL_LIGHTING);
1556
1557                                 if(selected) {
1558                                         if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1559                                         else UI_ThemeColor(TH_SELECT);
1560                                 } else {
1561                                         if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1562                                         else UI_ThemeColor(TH_WIRE);
1563                                 }
1564
1565                                 drawaxes(0.05f, v3d->bundle_drawtype);
1566
1567                                 glEnable(GL_LIGHTING);
1568                         } else if(v3d->drawtype>OB_WIRE) {
1569                                 if(v3d->bundle_drawtype==OB_EMPTY_SPHERE) {
1570                                         /* selection outline */
1571                                         if(selected) {
1572                                                 if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1573                                                 else UI_ThemeColor(TH_SELECT);
1574
1575                                                 glLineWidth(2.f);
1576                                                 glDisable(GL_LIGHTING);
1577                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1578
1579                                                 draw_bundle_sphere();
1580
1581                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1582                                                 glEnable(GL_LIGHTING);
1583                                                 glLineWidth(1.f);
1584                                         }
1585
1586                                         if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1587                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1588
1589                                         draw_bundle_sphere();
1590                                 } else {
1591                                         glDisable(GL_LIGHTING);
1592
1593                                         if(selected) {
1594                                                 if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1595                                                 else UI_ThemeColor(TH_SELECT);
1596                                         } else {
1597                                                 if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1598                                                 else UI_ThemeColor(TH_WIRE);
1599                                         }
1600
1601                                         drawaxes(0.05f, v3d->bundle_drawtype);
1602
1603                                         glEnable(GL_LIGHTING);
1604                                 }
1605                         }
1606
1607                 glPopMatrix();
1608
1609                 if((flag & DRAW_PICKING)==0 && (v3d->flag2&V3D_SHOW_BUNDLENAME)) {
1610                         float pos[3];
1611                         unsigned char tcol[4];
1612
1613                         if(selected) memcpy(tcol, scol, sizeof(tcol));
1614                         else memcpy(tcol, col, sizeof(tcol));
1615
1616                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1617                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1618                 }
1619
1620                 tracknr++;
1621         }
1622
1623         if((flag & DRAW_PICKING)==0) {
1624                 if((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) {
1625                         MovieTrackingReconstruction *reconstruction;
1626                         reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object);
1627
1628                         if(reconstruction->camnr) {
1629                                 MovieReconstructedCamera *camera= reconstruction->cameras;
1630                                 int a= 0;
1631
1632                                 glDisable(GL_LIGHTING);
1633                                 UI_ThemeColor(TH_CAMERA_PATH);
1634                                 glLineWidth(2.0f);
1635
1636                                 glBegin(GL_LINE_STRIP);
1637                                         for(a= 0; a<reconstruction->camnr; a++, camera++) {
1638                                                 glVertex3fv(camera->mat[3]);
1639                                         }
1640                                         glEnd();
1641
1642                                         glLineWidth(1.0f);
1643                                         glEnable(GL_LIGHTING);
1644                         }
1645                 }
1646         }
1647
1648         glPopMatrix();
1649
1650         *global_track_index= tracknr;
1651 }
1652
1653 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag)
1654 {
1655         MovieTracking *tracking= &clip->tracking;
1656         MovieTrackingObject *tracking_object;
1657         float curcol[4];
1658         int global_track_index= 1;
1659
1660         if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
1661                 return;
1662
1663         if(v3d->flag2&V3D_RENDER_OVERRIDE)
1664                 return;
1665
1666         glGetFloatv(GL_CURRENT_COLOR, curcol);
1667
1668         glEnable(GL_LIGHTING);
1669         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1670         glEnable(GL_COLOR_MATERIAL);
1671         glShadeModel(GL_SMOOTH);
1672
1673         tracking_object= tracking->objects.first;
1674         while(tracking_object) {
1675                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1676                                         flag, &global_track_index);
1677
1678                 tracking_object= tracking_object->next;
1679         }
1680
1681         /* restore */
1682         glShadeModel(GL_FLAT);
1683         glDisable(GL_COLOR_MATERIAL);
1684         glDisable(GL_LIGHTING);
1685
1686         glColor4fv(curcol);
1687
1688         if(flag&DRAW_PICKING)
1689                 glLoadName(base->selcol);
1690 }
1691
1692 /* flag similar to draw_object() */
1693 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag)
1694 {
1695         /* a standing up pyramid with (0,0,0) as top */
1696         Camera *cam;
1697         Object *ob= base->object;
1698         float tvec[3];
1699         float vec[4][3], asp[2], shift[2], scale[3];
1700         int i;
1701         float drawsize;
1702         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1703         MovieClip *clip= object_get_movieclip(scene, base->object, 0);
1704
1705         /* draw data for movie clip set as active for scene */
1706         if(clip)
1707                 draw_viewport_reconstruction(scene, base, v3d, clip, flag);
1708
1709 #ifdef VIEW3D_CAMERA_BORDER_HACK
1710         if(is_view && !(G.f & G_PICKSEL)) {
1711                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1712                 view3d_camera_border_hack_test= TRUE;
1713                 return;
1714         }
1715 #endif
1716
1717         cam= ob->data;
1718
1719         scale[0]= 1.0f / len_v3(ob->obmat[0]);
1720         scale[1]= 1.0f / len_v3(ob->obmat[1]);
1721         scale[2]= 1.0f / len_v3(ob->obmat[2]);
1722
1723         camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1724                              asp, shift, &drawsize, vec);
1725
1726         glDisable(GL_LIGHTING);
1727         glDisable(GL_CULL_FACE);
1728
1729         /* camera frame */
1730         glBegin(GL_LINE_LOOP);
1731         glVertex3fv(vec[0]);
1732         glVertex3fv(vec[1]);
1733         glVertex3fv(vec[2]);
1734         glVertex3fv(vec[3]);
1735         glEnd();
1736
1737         if(is_view)
1738                 return;
1739
1740         zero_v3(tvec);
1741
1742         /* center point to camera frame */
1743         glBegin(GL_LINE_STRIP);
1744         glVertex3fv(vec[1]);
1745         glVertex3fv(tvec);
1746         glVertex3fv(vec[0]);
1747         glVertex3fv(vec[3]);
1748         glVertex3fv(tvec);
1749         glVertex3fv(vec[2]);
1750         glEnd();
1751
1752
1753         /* arrow on top */
1754         tvec[2]= vec[1][2]; /* copy the depth */
1755
1756
1757         /* draw an outline arrow for inactive cameras and filled
1758          * for active cameras. We actually draw both outline+filled
1759          * for active cameras so the wire can be seen side-on */        
1760         for (i=0;i<2;i++) {
1761                 if (i==0) glBegin(GL_LINE_LOOP);
1762                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1763                 else break;
1764
1765                 tvec[0]= shift[0] + ((-0.7f * drawsize) * scale[0]);
1766                 tvec[1]= shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1767                 glVertex3fv(tvec); /* left */
1768                 
1769                 tvec[0]= shift[0] + ((0.7f * drawsize) * scale[0]);
1770                 glVertex3fv(tvec); /* right */
1771                 
1772                 tvec[0]= shift[0];
1773                 tvec[1]= shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1774                 glVertex3fv(tvec); /* top */
1775         
1776                 glEnd();
1777         }
1778
1779         if(flag==0) {
1780                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1781                         float nobmat[4][4];
1782                         World *wrld;
1783         
1784                         /* draw in normalized object matrix space */
1785                         copy_m4_m4(nobmat, ob->obmat);
1786                         normalize_m4(nobmat);
1787
1788                         glPushMatrix();
1789                         glLoadMatrixf(rv3d->viewmat);
1790                         glMultMatrixf(nobmat);
1791
1792                         if(cam->flag & CAM_SHOWLIMITS) {
1793                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1794                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1795                                 draw_focus_cross(object_camera_dof_distance(ob), cam->drawsize);
1796                         }
1797
1798                         wrld= scene->world;
1799                         if(cam->flag & CAM_SHOWMIST) 
1800                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1801                                 
1802                         glPopMatrix();
1803                 }
1804         }
1805 }
1806
1807 /* flag similar to draw_object() */
1808 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1809                         Object *UNUSED(ob), int UNUSED(flag))
1810 {
1811         //Speaker *spk = ob->data;
1812
1813         float vec[3];
1814         int i, j;
1815
1816         glEnable(GL_BLEND);
1817
1818         for(j = 0; j < 3; j++) {
1819                 vec[2] = 0.25f * j -0.125f;
1820
1821                 glBegin(GL_LINE_LOOP);
1822                 for(i = 0; i < 16; i++) {
1823                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1824                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1825                         glVertex3fv(vec);
1826                 }
1827                 glEnd();
1828         }
1829
1830         for(j = 0; j < 4; j++) {
1831                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1832                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1833                 glBegin(GL_LINE_STRIP);
1834                 for(i = 0; i < 3; i++) {
1835                         if(i == 1) {
1836                                 vec[0] *= 0.5f;
1837                                 vec[1] *= 0.5f;
1838                         }
1839
1840                         vec[2] = 0.25f * i -0.125f;
1841                         glVertex3fv(vec);
1842                 }
1843                 glEnd();
1844         }
1845
1846         glDisable(GL_BLEND);
1847 }
1848
1849 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1850 {
1851         BPoint *bp = lt->def;
1852         float *co = dl?dl->verts:NULL;
1853         int u, v, w;
1854
1855         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1856         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1857         bglBegin(GL_POINTS);
1858
1859         for(w=0; w<lt->pntsw; w++) {
1860                 int wxt = (w==0 || w==lt->pntsw-1);
1861                 for(v=0; v<lt->pntsv; v++) {
1862                         int vxt = (v==0 || v==lt->pntsv-1);
1863                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1864                                 int uxt = (u==0 || u==lt->pntsu-1);
1865                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1866                                         if(bp->hide==0) {
1867                                                 if((bp->f1 & SELECT)==sel) {
1868                                                         bglVertex3fv(dl?co:bp->vec);
1869                                                 }
1870                                         }
1871                                 }
1872                         }
1873                 }
1874         }
1875         
1876         glPointSize(1.0);
1877         bglEnd();       
1878 }
1879
1880 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1881 {
1882         Object *obedit= vc->obedit;
1883         Lattice *lt= obedit->data;
1884         BPoint *bp = lt->editlatt->latt->def;
1885         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1886         float *co = dl?dl->verts:NULL;
1887         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1888         short s[2] = {IS_CLIPPED, 0};
1889
1890         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1891
1892         for (i=0; i<N; i++, bp++, co+=3) {
1893                 if (bp->hide==0) {
1894                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1895                         if (s[0] != IS_CLIPPED)
1896                                 func(userData, bp, s[0], s[1]);
1897                 }
1898         }
1899 }
1900
1901 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1902 {
1903         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1904
1905         if(use_wcol) {
1906                 float col[3];
1907                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1908                 
1909                 weight_to_rgb(col, mdw?mdw->weight:0.0f);
1910                 glColor3fv(col);
1911
1912         }
1913         
1914         if (dl) {
1915                 glVertex3fv(&dl->verts[index*3]);
1916         } else {
1917                 glVertex3fv(lt->def[index].vec);
1918         }
1919 }
1920
1921 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1922 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1923 {
1924         Lattice *lt= ob->data;
1925         DispList *dl;
1926         int u, v, w;
1927         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1928
1929         /* now we default make displist, this will modifiers work for non animated case */
1930         if(ob->disp.first==NULL)
1931                 lattice_calc_modifiers(scene, ob);
1932         dl= find_displist(&ob->disp, DL_VERTS);
1933         
1934         if(is_edit) {
1935                 lt= lt->editlatt->latt;
1936
1937                 cpack(0x004000);
1938                 
1939                 if(ob->defbase.first && lt->dvert) {
1940                         use_wcol= ob->actdef;
1941                         glShadeModel(GL_SMOOTH);
1942                 }
1943         }
1944         
1945         glBegin(GL_LINES);
1946         for(w=0; w<lt->pntsw; w++) {
1947                 int wxt = (w==0 || w==lt->pntsw-1);
1948                 for(v=0; v<lt->pntsv; v++) {
1949                         int vxt = (v==0 || v==lt->pntsv-1);
1950                         for(u=0; u<lt->pntsu; u++) {
1951                                 int uxt = (u==0 || u==lt->pntsu-1);
1952
1953                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1954                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1955                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1956                                 }
1957                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1958                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1959                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1960                                 }
1961                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1962                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1963                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1964                                 }
1965                         }
1966                 }
1967         }               
1968         glEnd();
1969         
1970         /* restoration for weight colors */
1971         if(use_wcol)
1972                 glShadeModel(GL_FLAT);
1973
1974         if(is_edit) {
1975                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1976                 
1977                 lattice_draw_verts(lt, dl, 0);
1978                 lattice_draw_verts(lt, dl, 1);
1979                 
1980                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1981         }
1982 }
1983
1984 /* ***************** ******************** */
1985
1986 /* Note! - foreach funcs should be called while drawing or directly after
1987  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1988  * but would not give correct results with dupli's for eg. which dont
1989  * use the object matrix in the useual way */
1990 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1991 {
1992         foreachScreenVert_userData *data = userData;
1993         EditVert *eve = EM_get_vert_for_index(index);
1994
1995         if (eve->h==0) {
1996                 short s[2]= {IS_CLIPPED, 0};
1997
1998                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
1999                         view3d_project_short_clip(data->vc.ar, co, s, 1);
2000                 } else {
2001                         view3d_project_short_noclip(data->vc.ar, co, s);
2002                 }
2003
2004                 if (s[0]!=IS_CLIPPED)
2005                         data->func(data->userData, eve, s[0], s[1], index);
2006         }
2007 }
2008
2009 void mesh_foreachScreenVert(
2010         ViewContext *vc,
2011         void (*func)(void *userData, EditVert *eve, int x, int y, int index),
2012         void *userData, eV3DClipTest clipVerts)
2013 {
2014         foreachScreenVert_userData data;
2015         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2016         
2017         data.vc= *vc;
2018         data.func = func;
2019         data.userData = userData;
2020         data.clipVerts = clipVerts;
2021
2022         if(clipVerts != V3D_CLIP_TEST_OFF)
2023                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2024
2025         EM_init_index_arrays(vc->em, 1, 0, 0);
2026         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
2027         EM_free_index_arrays();
2028
2029         dm->release(dm);
2030 }
2031
2032 /*  draw callback */
2033 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2034 {
2035         MVert *mv = &((MVert *)userData)[index];
2036
2037         if(!(mv->flag & ME_HIDE)) {
2038                 const char sel= mv->flag & SELECT;
2039
2040                 // TODO define selected color
2041                 if(sel) {
2042                         glColor3f(1.0f, 1.0f, 0.0f);
2043                 }
2044                 else {
2045                         glColor3f(0.0f, 0.0f, 0.0f);
2046                 }
2047
2048                 glVertex3fv(co);
2049         }
2050 }
2051
2052 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2053 {
2054         glBegin(GL_POINTS);
2055         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2056         glEnd();
2057 }
2058 static int is_co_in_region(ARegion *ar, const short co[2])
2059 {
2060         return ( (co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
2061                  (co[0] >= 0)          &&
2062                  (co[0] <  ar->winx)   &&
2063                  (co[1] >= 0)          &&
2064                  (co[1] <  ar->winy));
2065 }
2066 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
2067 {
2068         foreachScreenEdge_userData *data = userData;
2069         EditEdge *eed = EM_get_edge_for_index(index);
2070         short s[2][2];
2071
2072         if (eed->h==0) {
2073                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2074                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
2075                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
2076                 }
2077                 else {
2078                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
2079                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
2080
2081                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2082                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
2083                                      !is_co_in_region(data->vc.ar, s[1]))
2084                                 {
2085                                         return;
2086                                 }
2087                         }
2088                 }
2089
2090                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2091         }
2092 }
2093
2094 void mesh_foreachScreenEdge(
2095         ViewContext *vc,
2096         void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index),
2097         void *userData, eV3DClipTest clipVerts)
2098 {
2099         foreachScreenEdge_userData data;
2100         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2101
2102         data.vc= *vc;
2103         data.func = func;
2104         data.userData = userData;
2105         data.clipVerts = clipVerts;
2106
2107         if(clipVerts != V3D_CLIP_TEST_OFF)
2108                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2109
2110         EM_init_index_arrays(vc->em, 0, 1, 0);
2111         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2112         EM_free_index_arrays();
2113
2114         dm->release(dm);
2115 }
2116
2117 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2118 {
2119         foreachScreenFace_userData *data = userData;
2120         EditFace *efa = EM_get_face_for_index(index);
2121         short s[2];
2122
2123         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
2124                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
2125
2126                 if (s[0] != IS_CLIPPED) {
2127                         data->func(data->userData, efa, s[0], s[1], index);
2128                 }
2129         }
2130 }
2131
2132 void mesh_foreachScreenFace(
2133         ViewContext *vc,
2134         void (*func)(void *userData, EditFace *efa, int x, int y, int index),
2135         void *userData)
2136 {
2137         foreachScreenFace_userData data;
2138         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2139
2140         data.vc= *vc;
2141         data.func = func;
2142         data.userData = userData;
2143
2144         //if(clipVerts)
2145         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2146
2147         EM_init_index_arrays(vc->em, 0, 0, 1);
2148         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2149         EM_free_index_arrays();
2150
2151         dm->release(dm);
2152 }
2153
2154 void nurbs_foreachScreenVert(
2155         ViewContext *vc,
2156         void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2157         void *userData)
2158 {
2159         Curve *cu= vc->obedit->data;
2160         short s[2] = {IS_CLIPPED, 0};
2161         Nurb *nu;
2162         int i;
2163         ListBase *nurbs= curve_editnurbs(cu);
2164
2165         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2166
2167         for (nu= nurbs->first; nu; nu=nu->next) {
2168                 if(nu->type == CU_BEZIER) {
2169                         for (i=0; i<nu->pntsu; i++) {
2170                                 BezTriple *bezt = &nu->bezt[i];
2171
2172                                 if(bezt->hide==0) {
2173                                         
2174                                         if(cu->drawflag & CU_HIDE_HANDLES) {
2175                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2176                                                 if (s[0] != IS_CLIPPED)
2177                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2178                                         } else {
2179                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
2180                                                 if (s[0] != IS_CLIPPED)
2181                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2182                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2183                                                 if (s[0] != IS_CLIPPED)
2184                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2185                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
2186                                                 if (s[0] != IS_CLIPPED)
2187                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2188                                         }
2189                                 }
2190                         }
2191                 }
2192                 else {
2193                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2194                                 BPoint *bp = &nu->bp[i];
2195
2196                                 if(bp->hide==0) {
2197                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
2198                                         if (s[0] != IS_CLIPPED)
2199                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2200                                 }
2201                         }
2202                 }
2203         }
2204 }
2205
2206 /* ************** DRAW MESH ****************** */
2207
2208 /* First section is all the "simple" draw routines, 
2209  * ones that just pass some sort of primitive to GL,
2210  * with perhaps various options to control lighting,
2211  * color, etc.
2212  *
2213  * These routines should not have user interface related
2214  * logic!!!
2215  */
2216
2217 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2218 {
2219         drawDMNormal_userData *data = userData;
2220         EditFace *efa = EM_get_face_for_index(index);
2221
2222         if (efa->h==0 && efa->fgonf!=EM_FGON) {
2223                 glVertex3fv(cent);
2224                 glVertex3f(cent[0] + no[0] * data->normalsize,
2225                            cent[1] + no[1] * data->normalsize,
2226                            cent[2] + no[2] * data->normalsize);
2227         }
2228 }
2229 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
2230 {
2231         drawDMNormal_userData data;
2232
2233         data.normalsize = scene->toolsettings->normalsize;
2234
2235         glBegin(GL_LINES);
2236         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2237         glEnd();
2238 }
2239
2240 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2241 {
2242         EditFace *efa = EM_get_face_for_index(index);
2243         int sel = *((int*) userData);
2244
2245         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
2246                 bglVertex3fv(cent);
2247         }
2248 }
2249 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
2250 {
2251         bglBegin(GL_POINTS);
2252         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
2253         bglEnd();
2254 }
2255
2256 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2257 {
2258         drawDMNormal_userData *data = userData;
2259         EditVert *eve = EM_get_vert_for_index(index);
2260
2261         if (eve->h==0) {
2262                 glVertex3fv(co);
2263
2264                 if (no_f) {
2265                         glVertex3f(co[0] + no_f[0] * data->normalsize,
2266                                    co[1] + no_f[1] * data->normalsize,
2267                                    co[2] + no_f[2] * data->normalsize);
2268                 }
2269                 else {
2270                         glVertex3f(co[0] + no_s[0] * (data->normalsize / 32767.0f),
2271                                    co[1] + no_s[1] * (data->normalsize / 32767.0f),
2272                                    co[2] + no_s[2] * (data->normalsize / 32767.0f));
2273                 }
2274         }
2275 }
2276 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
2277 {
2278         drawDMNormal_userData data;
2279
2280         data.normalsize = scene->toolsettings->normalsize;
2281
2282         glBegin(GL_LINES);
2283         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2284         glEnd();
2285 }
2286
2287         /* Draw verts with color set based on selection */
2288 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2289 {
2290         drawDMVerts_userData * data = userData;
2291         EditVert *eve = EM_get_vert_for_index(index);
2292
2293         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
2294                 /* draw active larger - need to stop/start point drawing for this :/ */
2295                 if (eve==data->eve_act) {
2296                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2297                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2298                         
2299                         bglEnd();
2300                         
2301                         glPointSize(size);
2302                         bglBegin(GL_POINTS);
2303                         bglVertex3fv(co);
2304                         bglEnd();
2305                         
2306                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2307                         glPointSize(size);
2308                         bglBegin(GL_POINTS);
2309                 } else {
2310                         bglVertex3fv(co);
2311                 }
2312         }
2313 }
2314
2315 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
2316 {
2317         drawDMVerts_userData data;
2318         data.sel = sel;
2319         data.eve_act = eve_act;
2320
2321         bglBegin(GL_POINTS);
2322         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2323         bglEnd();
2324 }
2325
2326         /* Draw edges with color set based on selection */
2327 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2328 {
2329         EditEdge *eed = EM_get_edge_for_index(index);
2330         //unsigned char **cols = userData, *col;
2331         drawDMEdgesSel_userData * data = userData;
2332         unsigned char *col;
2333
2334         if (eed->h==0) {
2335                 if (eed==data->eed_act) {
2336                         glColor4ubv(data->actCol);
2337                 } else {
2338                         if (eed->f&SELECT) {
2339                                 col = data->selCol;
2340                         } else {
2341                                 col = data->baseCol;
2342                         }
2343                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2344                         if (col[3]==0) return 0;
2345                         
2346                         glColor4ubv(col);
2347                 }
2348                 return 1;
2349         } else {
2350                 return 0;
2351         }
2352 }
2353 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
2354 {
2355         drawDMEdgesSel_userData data;
2356         
2357         data.baseCol = baseCol;
2358         data.selCol = selCol;
2359         data.actCol = actCol;
2360         data.eed_act = eed_act;
2361         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2362 }
2363
2364         /* Draw edges */
2365 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2366 {
2367         return EM_get_edge_for_index(index)->h==0;
2368 }
2369 static void draw_dm_edges(DerivedMesh *dm) 
2370 {
2371         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2372 }
2373
2374         /* Draw edges with color interpolated based on selection */
2375 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2376 {
2377         return EM_get_edge_for_index(index)->h==0;
2378 }
2379 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2380 {
2381         EditEdge *eed = EM_get_edge_for_index(index);
2382         unsigned char **cols = userData;
2383         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2384         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2385
2386         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2387                                 col0[1] + (col1[1]-col0[1])*t,
2388                                 col0[2] + (col1[2]-col0[2])*t,
2389                                 col0[3] + (col1[3]-col0[3])*t);
2390 }
2391
2392 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2393 {
2394         unsigned char *cols[2];
2395         cols[0]= baseCol;
2396         cols[1]= selCol;
2397         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2398 }
2399
2400         /* Draw only seam edges */
2401 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2402 {
2403         EditEdge *eed = EM_get_edge_for_index(index);
2404
2405         return (eed->h==0 && eed->seam);
2406 }
2407 static void draw_dm_edges_seams(DerivedMesh *dm)
2408 {
2409         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2410 }
2411
2412         /* Draw only sharp edges */
2413 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2414 {
2415         EditEdge *eed = EM_get_edge_for_index(index);
2416
2417         return (eed->h==0 && eed->sharp);
2418 }
2419 static void draw_dm_edges_sharp(DerivedMesh *dm)
2420 {
2421         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2422 }
2423
2424         /* Draw only Freestyle feature edges */
2425 static int draw_dm_edges_freestyle__setDrawOptions(void *UNUSED(userData), int index)
2426 {
2427         EditEdge *eed = EM_get_edge_for_index(index);
2428
2429         return (eed->h==0 && eed->freestyle);
2430 }
2431 static void draw_dm_edges_freestyle(DerivedMesh *dm)
2432 {
2433         dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, NULL);
2434 }
2435
2436         /* Draw faces with color set based on selection
2437          * return 2 for the active face so it renders with stipple enabled */
2438 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2439 {
2440         drawDMFacesSel_userData * data = userData;
2441         EditFace *efa = EM_get_face_for_index(index);
2442         unsigned char *col;
2443         
2444         if (efa->h==0) {
2445                 if (efa == data->efa_act) {
2446                         glColor4ubv(data->cols[3]);
2447                         return 2; /* stipple */
2448                 } else {
2449                         col = data->cols[(efa->f & SELECT) ? 1 : (efa->flag & ME_FREESTYLE_FACE) ? 2 : 0];
2450                         if (col[3]==0) return 0;
2451                         glColor4ubv(col);
2452                         return 1;
2453                 }
2454         }
2455         return 0;
2456 }
2457
2458 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2459 {
2460         drawDMFacesSel_userData *data = userData;
2461         EditFace *efa;
2462         EditFace *next_efa;
2463         unsigned char *col, *next_col;
2464
2465         if(!data->orig_index)
2466                 return 0;
2467
2468         efa= EM_get_face_for_index(data->orig_index[index]);
2469         next_efa= EM_get_face_for_index(data->orig_index[next_index]);
2470
2471         if(efa == next_efa)
2472                 return 1;
2473
2474         if(efa == data->efa_act || next_efa == data->efa_act)
2475                 return 0;
2476
2477         col = data->cols[(efa->f & SELECT) ? 1 : (efa->flag & ME_FREESTYLE_FACE) ? 2 : 0];
2478         next_col = data->cols[(next_efa->f & SELECT) ? 1 : (next_efa->flag & ME_FREESTYLE_FACE) ? 2 : 0];
2479
2480         if(col[3]==0 || next_col[3]==0)
2481                 return 0;
2482
2483         return col == next_col;
2484 }
2485
2486 /* also draws the active face */
2487 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *markCol, unsigned char *actCol, EditFace *efa_act) 
2488 {
2489         drawDMFacesSel_userData data;
2490         data.cols[0] = baseCol;
2491         data.cols[1] = selCol;
2492         data.cols[2] = markCol;
2493         data.cols[3] = actCol;
2494         data.efa_act = efa_act;
2495         data.orig_index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
2496
2497         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2498 }
2499
2500 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2501 {
2502         EditEdge *eed = EM_get_edge_for_index(index);
2503
2504         if (eed->h==0 && eed->crease != 0.0f) {
2505                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2506                 return 1;
2507         } else {
2508                 return 0;
2509         }
2510 }
2511 static void draw_dm_creases(DerivedMesh *dm)
2512 {
2513         glLineWidth(3.0);
2514         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2515         glLineWidth(1.0);
2516 }
2517
2518 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2519 {
2520         EditEdge *eed = EM_get_edge_for_index(index);
2521
2522         if (eed->h==0 && eed->bweight != 0.0f) {
2523                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2524                 return 1;
2525         } else {
2526                 return 0;
2527         }
2528 }
2529 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2530 {
2531         EditVert *eve = EM_get_vert_for_index(index);
2532
2533         if (eve->h==0 && eve->bweight != 0.0f) {
2534                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2535                 bglVertex3fv(co);
2536         }
2537 }
2538 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2539 {
2540         ToolSettings *ts= scene->toolsettings;
2541
2542         if (ts->selectmode & SCE_SELECT_VERTEX) {
2543                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2544                 bglBegin(GL_POINTS);
2545                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2546                 bglEnd();
2547         }
2548         else {
2549                 glLineWidth(3.0);
2550                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2551                 glLineWidth(1.0);
2552         }
2553 }
2554
2555 /* Second section of routines: Combine first sets to form fancy
2556  * drawing routines (for example rendering twice to get overlays).
2557  *
2558  * Also includes routines that are basic drawing but are too
2559  * specialized to be split out (like drawing creases or measurements).
2560  */
2561
2562 /* EditMesh drawing routines*/
2563
2564 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2565                                 DerivedMesh *cageDM, EditVert *eve_act)
2566 {
2567         ToolSettings *ts= scene->toolsettings;
2568         int sel;
2569
2570         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2571
2572         for (sel=0; sel<2; sel++) {
2573                 unsigned char col[4], fcol[4];
2574                 int pass;
2575
2576                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2577                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2578
2579                 for (pass=0; pass<2; pass++) {
2580                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2581                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2582
2583                         if (pass==0) {
2584                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2585                                         glDisable(GL_DEPTH_TEST);
2586                                                 
2587                                         glEnable(GL_BLEND);
2588                                 } else {
2589                                         continue;
2590                                 }
2591
2592                                 size = (size > 2.1f ? size/2.0f:size);
2593                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2594                                 col[3] = fcol[3] = 100;
2595                         } else {
2596                                 col[3] = fcol[3] = 255;
2597                         }
2598                                 
2599                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2600                                 glPointSize(size);
2601                                 glColor4ubv(col);
2602                                 draw_dm_verts(cageDM, sel, eve_act);
2603                         }
2604                         
2605                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2606                                 glPointSize(fsize);
2607                                 glColor4ubv(fcol);
2608                                 draw_dm_face_centers(cageDM, sel);
2609                         }
2610                         
2611                         if (pass==0) {
2612                                 glDisable(GL_BLEND);
2613                                 glEnable(GL_DEPTH_TEST);
2614                         }
2615                 }
2616         }
2617
2618         if(v3d->zbuf) glDepthMask(1);
2619         glPointSize(1.0);
2620 }
2621
2622 static void draw_em_fancy_edges(Scene *scene, View3D *v3d,
2623                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2624                                 EditEdge *eed_act)
2625 {
2626         ToolSettings *ts= scene->toolsettings;
2627         int pass;
2628         unsigned char wireCol[4], selCol[4], actCol[4];
2629
2630         /* since this function does transparant... */
2631         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2632         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2633         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2634         
2635         /* when sel only is used, dont render wire, only selected, this is used for
2636          * textured draw mode when the 'edges' option is disabled */
2637         if (sel_only)
2638                 wireCol[3] = 0;
2639
2640         for (pass=0; pass<2; pass++) {
2641                         /* show wires in transparant when no zbuf clipping for select */
2642                 if (pass==0) {
2643                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2644                                 glEnable(GL_BLEND);
2645                                 glDisable(GL_DEPTH_TEST);
2646                                 selCol[3] = 85;
2647                                 if (!sel_only) wireCol[3] = 85;
2648                         } else {
2649                                 continue;
2650                         }
2651                 } else {
2652                         selCol[3] = 255;
2653                         if (!sel_only) wireCol[3] = 255;
2654                 }
2655
2656                 if(ts->selectmode == SCE_SELECT_FACE) {
2657                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2658                 }       
2659                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2660                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2661                                 glShadeModel(GL_SMOOTH);
2662                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2663                                 glShadeModel(GL_FLAT);
2664                         } else {
2665                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2666                         }
2667                 }
2668                 else {
2669                         if (!sel_only) {
2670                                 glColor4ubv(wireCol);
2671                                 draw_dm_edges(cageDM);
2672                         }
2673                 }
2674
2675                 if (pass==0) {
2676                         glDisable(GL_BLEND);
2677                         glEnable(GL_DEPTH_TEST);
2678                 }
2679         }
2680 }       
2681
2682 static void draw_em_measure_stats(View3D *v3d, Object *ob, EditMesh *em, UnitSettings *unit)
2683 {
2684         Mesh *me= ob->data;
2685         EditEdge *eed;
2686         EditFace *efa;
2687         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2688         float fvec[3];
2689         char numstr[32]; /* Stores the measurement display text here */
2690         const char *conv_float; /* Use a float conversion matching the grid size */
2691         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2692         float area; /* area of the face */
2693         float grid= unit->system ? unit->scale_length : v3d->grid;
2694         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2695         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2696         const int do_moving= G.moving;
2697
2698         /* make the precision of the pronted value proportionate to the gridsize */
2699
2700         if (grid < 0.01f)               conv_float= "%.6g";
2701         else if (grid < 0.1f)   conv_float= "%.5g";
2702         else if (grid < 1.0f)   conv_float= "%.4g";
2703         else if (grid < 10.0f)  conv_float= "%.3g";
2704         else                                    conv_float= "%.2g";
2705         
2706         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2707                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2708
2709                 for(eed= em->edges.first; eed; eed= eed->next) {
2710                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2711                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2712                                 copy_v3_v3(v1, eed->v1->co);
2713                                 copy_v3_v3(v2, eed->v2->co);
2714
2715                                 mid_v3_v3v3(vmid, v1, v2);
2716
2717                                 if(do_global) {
2718                                         mul_mat3_m4_v3(ob->obmat, v1);
2719                                         mul_mat3_m4_v3(ob->obmat, v2);
2720                                 }
2721
2722                                 if(unit->system) {
2723                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2724                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2725                                 }
2726                                 else {
2727                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2728                                 }
2729
2730                                 view3d_cached_text_draw_add(vmid, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2731                         }
2732                 }
2733         }
2734
2735         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2736 // XXX          extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
2737                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2738                 
2739                 for(efa= em->faces.first; efa; efa= efa->next) {
2740                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2741                                 copy_v3_v3(v1, efa->v1->co);
2742                                 copy_v3_v3(v2, efa->v2->co);
2743                                 copy_v3_v3(v3, efa->v3->co);
2744                                 if (efa->v4) {
2745                                         copy_v3_v3(v4, efa->v4->co);
2746                                 }
2747                                 if(do_global) {
2748                                         mul_mat3_m4_v3(ob->obmat, v1);
2749                                         mul_mat3_m4_v3(ob->obmat, v2);
2750                                         mul_mat3_m4_v3(ob->obmat, v3);
2751                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2752                                 }
2753                                 
2754                                 if (efa->v4)
2755                                         area=  area_quad_v3(v1, v2, v3, v4);
2756                                 else
2757                                         area = area_tri_v3(v1, v2, v3);
2758
2759                                 if(unit->system) {
2760                                         // XXX should be B_UNIT_AREA
2761                                         bUnit_AsString(numstr, sizeof(numstr), area * unit->scale_length, 3,
2762                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2763                                 }
2764                                 else {
2765                                         sprintf(numstr, conv_float, area);
2766                                 }
2767
2768                                 view3d_cached_text_draw_add(efa->cent, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2769                         }
2770                 }
2771         }
2772
2773         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2774                 EditEdge *e1, *e2, *e3, *e4;
2775                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2776                 for(efa= em->faces.first; efa; efa= efa->next) {
2777                         copy_v3_v3(v1, efa->v1->co);
2778                         copy_v3_v3(v2, efa->v2->co);
2779                         copy_v3_v3(v3, efa->v3->co);
2780                         if(efa->v4) {
2781                                 copy_v3_v3(v4, efa->v4->co); 
2782                         }
2783                         else {
2784                                 copy_v3_v3(v4, v3);
2785                         }
2786                         if(do_global) {
2787                                 mul_mat3_m4_v3(ob->obmat, v1);
2788                                 mul_mat3_m4_v3(ob->obmat, v2);
2789                                 mul_mat3_m4_v3(ob->obmat, v3);
2790                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2791                         }
2792                         
2793                         e1= efa->e1;
2794                         e2= efa->e2;
2795                         e3= efa->e3;
2796                         if(efa->e4) e4= efa->e4; else e4= e3;
2797                         
2798                         /* Calculate the angles */
2799                                 
2800                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2801                                 /* Vec 1 */
2802                                 sprintf(numstr,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2803                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2804                                 view3d_cached_text_draw_add(fvec, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2805                         }
2806                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2807                                 /* Vec 2 */
2808                                 sprintf(numstr,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2809                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2810                                 view3d_cached_text_draw_add(fvec, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2811                         }
2812                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2813                                 /* Vec 3 */
2814                                 if(efa->v4) 
2815                                         sprintf(numstr,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2816                                 else
2817                                         sprintf(numstr,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2818                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2819                                 view3d_cached_text_draw_add(fvec, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2820                         }
2821                                 /* Vec 4 */
2822                         if(efa->v4) {
2823                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2824                                         sprintf(numstr,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2825                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2826                                         view3d_cached_text_draw_add(fvec, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2827                                 }
2828                         }
2829                 }
2830         }
2831 }
2832
2833 static void draw_em_indices(EditMesh *em)
2834 {
2835         EditEdge *e;
2836         EditFace *f;
2837         EditVert *v;
2838         int i;
2839         char numstr[32];
2840         float pos[3];
2841         unsigned char col[4];
2842
2843         /* For now, reuse appropriate theme colors from stats text colors */
2844
2845         if (em->selectmode & SCE_SELECT_VERTEX) {
2846                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2847                 for (v = em->verts.first, i = 0; v; v = v->next, i++) {
2848                         if (v->f & SELECT) {
2849                                 sprintf(numstr, "%d", i);
2850                                 view3d_cached_text_draw_add(v->co, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2851                         }
2852                 }
2853         }
2854
2855         if (em->selectmode & SCE_SELECT_EDGE) {
2856                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2857                 for (e = em->edges.first, i = 0; e; e = e->next, i++) {
2858                         if (e->f & SELECT) {
2859                                 sprintf(numstr, "%d", i);
2860                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
2861                                 view3d_cached_text_draw_add(pos, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2862                         }
2863                 }
2864         }
2865
2866         if (em->selectmode & SCE_SELECT_FACE) {
2867                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2868                 for (f = em->faces.first, i = 0; f; f = f->next, i++) {
2869                         if (f->f & SELECT) {
2870                                 sprintf(numstr, "%d", i);
2871                                 view3d_cached_text_draw_add(f->cent, numstr, 0, V3D_CACHE_TEXT_ASCII, col);
2872                         }
2873                 }
2874         }
2875 }
2876
2877 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2878 {
2879         EditFace *efa = EM_get_face_for_index(index);
2880
2881         if (efa->h==0) {
2882                 GPU_enable_material(efa->mat_nr+1, NULL);
2883                 return 1;
2884         }
2885         else
2886                 return 0;
2887 }
2888
2889 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2890 {
2891         EditFace *efa = EM_get_face_for_index(index);
2892
2893         return (efa->h==0);
2894 }
2895
2896 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2897                           Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2898 {
2899         Mesh *me = ob->data;
2900         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2901         EditEdge *eed_act = NULL;
2902         EditVert *eve_act = NULL;
2903         
2904         if (em->selected.last) {
2905                 EditSelection *ese = em->selected.last;
2906                 /* face is handeled above */
2907                 /*if (ese->type == EDITFACE ) {
2908                         efa_act = (EditFace *)ese->data;
2909                 } else */ if ( ese->type == EDITEDGE ) {
2910                         eed_act = (EditEdge *)ese->data;
2911                 } else if ( ese->type == EDITVERT ) {
2912                         eve_act = (EditVert *)ese->data;
2913                 }
2914         }
2915         
2916         EM_init_index_arrays(em, 1, 1, 1);
2917
2918         if(dt>OB_WIRE) {
2919                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2920                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2921                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2922
2923                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2924                                                              draw_em_fancy__setGLSLFaceOpts, em);
2925                                 GPU_disable_material();
2926
2927                                 glFrontFace(GL_CCW);
2928                         }
2929                         else {
2930                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2931                         }
2932                 }
2933                 else {
2934                         /* 3 floats for position,
2935                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
2936                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2937
2938                         glEnable(GL_LIGHTING);
2939                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2940                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, NULL, 0);
2941
2942                         glFrontFace(GL_CCW);
2943                         glDisable(GL_LIGHTING);
2944                 }
2945                         
2946                 // Setup for drawing wire over, disable zbuffer
2947                 // write to show selected edge wires better
2948                 UI_ThemeColor(TH_WIRE);
2949
2950                 bglPolygonOffset(rv3d->dist, 1.0);
2951                 glDepthMask(0);
2952         } 
2953         else {
2954                 if (cageDM!=finalDM) {
2955                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2956                         finalDM->drawEdges(finalDM, 1, 0);
2957                 }
2958         }
2959         
2960         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2961                 unsigned char col1[4], col2[4], col3[4], col4[4];
2962                         
2963                 UI_GetThemeColor4ubv(TH_FACE, col1);
2964                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2965                 UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col3);
2966                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
2967                 
2968                 glEnable(GL_BLEND);
2969                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2970                 
2971                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2972                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2973                         col1[3] = 0;
2974                 
2975                 if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE))
2976                         col3[3] = 0;
2977
2978                 draw_dm_faces_sel(cageDM, col1, col2, col3, col4, efa_act);
2979
2980                 glDisable(GL_BLEND);
2981                 glDepthMask(1);         // restore write in zbuffer
2982         } else if (efa_act) {
2983                 /* even if draw faces is off it would be nice to draw the stipple face
2984                  * Make all other faces zero alpha except for the active
2985                  * */
2986                 unsigned char col1[4], col2[4], col3[4], col4[4];
2987                 col1[3] = col2[3] = col3[3] = 0; /* dont draw */
2988                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
2989                 
2990                 glEnable(GL_BLEND);
2991                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2992                 
2993                 draw_dm_faces_sel(cageDM, col1, col2, col3, col4, efa_act);
2994
2995                 glDisable(GL_BLEND);
2996                 glDepthMask(1);         // restore write in zbuffer
2997                 
2998         }
2999
3000         /* here starts all fancy draw-extra over */
3001         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
3002                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
3003                 
3004                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
3005                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
3006                 
3007         } else {
3008                 if(me->drawflag & ME_DRAWSEAMS) {
3009                         UI_ThemeColor(TH_EDGE_SEAM);
3010                         glLineWidth(2);
3011         
3012                         draw_dm_edges_seams(cageDM);
3013         
3014                         glColor3ub(0,0,0);
3015                         glLineWidth(1);
3016                 }
3017                 
3018                 if(me->drawflag & ME_DRAWSHARP) {
3019                         UI_ThemeColor(TH_EDGE_SHARP);
3020                         glLineWidth(2);
3021         
3022                         draw_dm_edges_sharp(cageDM);
3023         
3024                         glColor3ub(0,0,0);
3025                         glLineWidth(1);
3026                 }
3027         
3028                 if(me->drawflag & ME_DRAW_FREESTYLE_EDGE) {
3029                         UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
3030                         glLineWidth(2);
3031         
3032                         draw_dm_edges_freestyle(cageDM);
3033         
3034                         glColor3ub(0,0,0);
3035                         glLineWidth(1);
3036                 }
3037         
3038                 if(me->drawflag & ME_DRAWCREASES) {
3039                         draw_dm_creases(cageDM);
3040                 }
3041                 if(me->drawflag & ME_DRAWBWEIGHTS) {
3042                         draw_dm_bweights(scene, cageDM);
3043                 }
3044
3045                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
3046         }
3047         if(em) {
3048                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
3049
3050                 if(me->drawflag & ME_DRAWNORMALS) {
3051                         UI_ThemeColor(TH_NORMAL);
3052                         draw_dm_face_normals(scene, cageDM);
3053                 }
3054                 if(me->drawflag & ME_DRAW_VNORMALS) {
3055                         UI_ThemeColor(TH_VNORMAL);
3056                         draw_dm_vert_normals(scene, cageDM);
3057                 }
3058
3059                 if ( (me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG)) &&
3060                      !(v3d->flag2 & V3D_RENDER_OVERRIDE))
3061                 {
3062                         draw_em_measure_stats(v3d, ob, em, &scene->unit);
3063                 }
3064
3065                 if ((G.f & G_DEBUG) && (me->drawflag & ME_DRAWEXTRA_INDICES) &&
3066                     !(v3d->flag2 & V3D_RENDER_OVERRIDE)) {
3067                         draw_em_indices(em);
3068                 }
3069         }