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