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