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