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