Merging r40615 through r40652 from trunk into soc-2011-tomato
[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 vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1597         int i;
1598         float drawsize;
1599         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1600         MovieClip *clip= object_get_movieclip(scene, base->object);
1601
1602         const float scax= 1.0f / len_v3(ob->obmat[0]);
1603         const float scay= 1.0f / len_v3(ob->obmat[1]);
1604         const float scaz= 1.0f / len_v3(ob->obmat[2]);
1605
1606         /* draw data for movie clip set as active for scene */
1607         if(clip)
1608                 draw_viewport_reconstruction(scene, base, v3d, clip, flag);
1609
1610 #ifdef VIEW3D_CAMERA_BORDER_HACK
1611         if(is_view && !(G.f & G_PICKSEL)) {
1612                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1613                 view3d_camera_border_hack_test= TRUE;
1614                 return;
1615         }
1616 #endif
1617
1618         cam= ob->data;
1619         aspx= (float) scene->r.xsch*scene->r.xasp;
1620         aspy= (float) scene->r.ysch*scene->r.yasp;
1621
1622         if(aspx < aspy) {
1623                 caspx= aspx / aspy;
1624                 caspy= 1.0;
1625         }
1626         else {
1627                 caspx= 1.0;
1628                 caspy= aspy / aspx;
1629         }
1630         
1631         glDisable(GL_LIGHTING);
1632         glDisable(GL_CULL_FACE);
1633         
1634         if(cam->type==CAM_ORTHO) {
1635                 facx= 0.5f * cam->ortho_scale * caspx * scax;
1636                 facy= 0.5f * cam->ortho_scale * caspy * scay;
1637                 shx= cam->shiftx * cam->ortho_scale * scax;
1638                 shy= cam->shifty * cam->ortho_scale * scay;
1639                 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1640                 
1641                 drawsize= 0.5f * cam->ortho_scale;
1642         }
1643         else {
1644                 /* that way it's always visible - clipsta+0.1 */
1645                 float fac;
1646                 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1647
1648                 if(is_view) {
1649                         /* fixed depth, variable size (avoids exceeding clipping range) */
1650                         depth = -(cam->clipsta + 0.1f);
1651                         fac = depth / (cam->lens/ (cam->sensor_x / 2.0f));
1652                 }
1653                 else {
1654                         /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1655                         depth= drawsize * cam->lens/-16.0f * scaz;
1656                         fac= drawsize;
1657                 }
1658
1659                 facx= fac * caspx * scax;
1660                 facy= fac * caspy * scay;
1661                 shx= cam->shiftx*fac*2 * scax;
1662                 shy= cam->shifty*fac*2 * scay;
1663         }
1664         
1665         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1666         vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1667         vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1668         vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1669         vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1670
1671         /* camera frame */
1672         glBegin(GL_LINE_LOOP);
1673                 glVertex3fv(vec[1]); 
1674                 glVertex3fv(vec[2]); 
1675                 glVertex3fv(vec[3]); 
1676                 glVertex3fv(vec[4]);
1677         glEnd();
1678
1679         if(is_view)
1680                 return;
1681
1682         /* center point to camera frame */
1683         glBegin(GL_LINE_STRIP);
1684                 glVertex3fv(vec[2]); 
1685                 glVertex3fv(vec[0]);
1686                 glVertex3fv(vec[1]);
1687                 glVertex3fv(vec[4]);
1688                 glVertex3fv(vec[0]);
1689                 glVertex3fv(vec[3]); 
1690         glEnd();
1691
1692
1693         /* arrow on top */
1694         vec[0][2]= depth;
1695
1696
1697         /* draw an outline arrow for inactive cameras and filled
1698          * for active cameras. We actually draw both outline+filled
1699          * for active cameras so the wire can be seen side-on */        
1700         for (i=0;i<2;i++) {
1701                 if (i==0) glBegin(GL_LINE_LOOP);
1702                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1703                 else break;
1704
1705                 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1706                 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1707                 glVertex3fv(vec[0]); /* left */
1708                 
1709                 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1710                 glVertex3fv(vec[0]); /* right */
1711                 
1712                 vec[0][0]= shx;
1713                 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1714                 glVertex3fv(vec[0]); /* top */
1715         
1716                 glEnd();
1717         }
1718
1719         if(flag==0) {
1720                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1721                         float nobmat[4][4];
1722                         World *wrld;
1723         
1724                         /* draw in normalized object matrix space */
1725                         copy_m4_m4(nobmat, ob->obmat);
1726                         normalize_m4(nobmat);
1727
1728                         glPushMatrix();
1729                         glLoadMatrixf(rv3d->viewmat);
1730                         glMultMatrixf(nobmat);
1731
1732                         if(cam->flag & CAM_SHOWLIMITS) {
1733                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1734                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1735                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
1736                         }
1737
1738                         wrld= scene->world;
1739                         if(cam->flag & CAM_SHOWMIST) 
1740                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1741                                 
1742                         glPopMatrix();
1743                 }
1744         }
1745 }
1746
1747 /* flag similar to draw_object() */
1748 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag))
1749 {
1750         //Speaker *spk = ob->data;
1751
1752         float vec[3];
1753         int i, j;
1754
1755         glEnable(GL_BLEND);
1756
1757         for(j = 0; j < 3; j++) {
1758                 vec[2] = 0.25f * j -0.125f;
1759
1760                 glBegin(GL_LINE_LOOP);
1761                 for(i = 0; i < 16; i++) {
1762                         vec[0] = cosf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1763                         vec[1] = sinf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1764                         glVertex3fv(vec);
1765                 }
1766                 glEnd();
1767         }
1768
1769         for(j = 0; j < 4; j++) {
1770                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1771                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1772                 glBegin(GL_LINE_STRIP);
1773                 for(i = 0; i < 3; i++) {
1774                         if(i == 1) {
1775                                 vec[0] *= 0.5f;
1776                                 vec[1] *= 0.5f;
1777                         }
1778
1779                         vec[2] = 0.25f * i -0.125f;
1780                         glVertex3fv(vec);
1781                 }
1782                 glEnd();
1783         }
1784
1785         glDisable(GL_BLEND);
1786 }
1787
1788 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1789 {
1790         BPoint *bp = lt->def;
1791         float *co = dl?dl->verts:NULL;
1792         int u, v, w;
1793
1794         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1795         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1796         bglBegin(GL_POINTS);
1797
1798         for(w=0; w<lt->pntsw; w++) {
1799                 int wxt = (w==0 || w==lt->pntsw-1);
1800                 for(v=0; v<lt->pntsv; v++) {
1801                         int vxt = (v==0 || v==lt->pntsv-1);
1802                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1803                                 int uxt = (u==0 || u==lt->pntsu-1);
1804                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1805                                         if(bp->hide==0) {
1806                                                 if((bp->f1 & SELECT)==sel) {
1807                                                         bglVertex3fv(dl?co:bp->vec);
1808                                                 }
1809                                         }
1810                                 }
1811                         }
1812                 }
1813         }
1814         
1815         glPointSize(1.0);
1816         bglEnd();       
1817 }
1818
1819 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1820 {
1821         Object *obedit= vc->obedit;
1822         Lattice *lt= obedit->data;
1823         BPoint *bp = lt->editlatt->latt->def;
1824         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1825         float *co = dl?dl->verts:NULL;
1826         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1827         short s[2] = {IS_CLIPPED, 0};
1828
1829         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1830
1831         for (i=0; i<N; i++, bp++, co+=3) {
1832                 if (bp->hide==0) {
1833                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1834                         if (s[0] != IS_CLIPPED)
1835                                 func(userData, bp, s[0], s[1]);
1836                 }
1837         }
1838 }
1839
1840 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1841 {
1842         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1843
1844         if(use_wcol) {
1845                 float col[3];
1846                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1847                 
1848                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1849                 glColor3fv(col);
1850
1851         }
1852         
1853         if (dl) {
1854                 glVertex3fv(&dl->verts[index*3]);
1855         } else {
1856                 glVertex3fv(lt->def[index].vec);
1857         }
1858 }
1859
1860 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1861 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1862 {
1863         Lattice *lt= ob->data;
1864         DispList *dl;
1865         int u, v, w;
1866         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1867
1868         /* now we default make displist, this will modifiers work for non animated case */
1869         if(ob->disp.first==NULL)
1870                 lattice_calc_modifiers(scene, ob);
1871         dl= find_displist(&ob->disp, DL_VERTS);
1872         
1873         if(is_edit) {
1874                 lt= lt->editlatt->latt;
1875
1876                 cpack(0x004000);
1877                 
1878                 if(ob->defbase.first && lt->dvert) {
1879                         use_wcol= ob->actdef;
1880                         glShadeModel(GL_SMOOTH);
1881                 }
1882         }
1883         
1884         glBegin(GL_LINES);
1885         for(w=0; w<lt->pntsw; w++) {
1886                 int wxt = (w==0 || w==lt->pntsw-1);
1887                 for(v=0; v<lt->pntsv; v++) {
1888                         int vxt = (v==0 || v==lt->pntsv-1);
1889                         for(u=0; u<lt->pntsu; u++) {
1890                                 int uxt = (u==0 || u==lt->pntsu-1);
1891
1892                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1893                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1894                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1895                                 }
1896                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1897                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1898                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1899                                 }
1900                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1901                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1902                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1903                                 }
1904                         }
1905                 }
1906         }               
1907         glEnd();
1908         
1909         /* restoration for weight colors */
1910         if(use_wcol)
1911                 glShadeModel(GL_FLAT);
1912
1913         if(is_edit) {
1914                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1915                 
1916                 lattice_draw_verts(lt, dl, 0);
1917                 lattice_draw_verts(lt, dl, 1);
1918                 
1919                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1920         }
1921 }
1922
1923 /* ***************** ******************** */
1924
1925 /* Note! - foreach funcs should be called while drawing or directly after
1926  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1927  * but would not give correct results with dupli's for eg. which dont
1928  * use the object matrix in the useual way */
1929 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1930 {
1931         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1932         EditVert *eve = EM_get_vert_for_index(index);
1933
1934         if (eve->h==0) {
1935                 short s[2]= {IS_CLIPPED, 0};
1936
1937                 if (data->clipVerts) {
1938                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1939                 } else {
1940                         view3d_project_short_noclip(data->vc.ar, co, s);
1941                 }
1942
1943                 if (s[0]!=IS_CLIPPED)
1944                         data->func(data->userData, eve, s[0], s[1], index);
1945         }
1946 }
1947
1948 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1949 {
1950         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1951         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1952         
1953         data.vc= *vc;
1954         data.func = func;
1955         data.userData = userData;
1956         data.clipVerts = clipVerts;
1957
1958         if(clipVerts)
1959                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1960
1961         EM_init_index_arrays(vc->em, 1, 0, 0);
1962         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1963         EM_free_index_arrays();
1964
1965         dm->release(dm);
1966 }
1967
1968 /*  draw callback */
1969 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1970 {
1971         MVert *mv = &((MVert *)userData)[index];
1972
1973         if(!(mv->flag & ME_HIDE)) {
1974                 const char sel= mv->flag & SELECT;
1975
1976                 // TODO define selected color
1977                 if(sel) {
1978                         glColor3f(1.0f, 1.0f, 0.0f);
1979                 }
1980                 else {
1981                         glColor3f(0.0f, 0.0f, 0.0f);
1982                 }
1983
1984                 glVertex3fv(co);
1985         }
1986 }
1987
1988 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
1989 {
1990         glBegin(GL_POINTS);
1991         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
1992         glEnd();
1993 }
1994 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1995 {
1996         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;
1997         EditEdge *eed = EM_get_edge_for_index(index);
1998         short s[2][2];
1999
2000         if (eed->h==0) {
2001                 if (data->clipVerts==1) {
2002                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
2003                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
2004                 } else {
2005                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
2006                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
2007
2008                         if (data->clipVerts==2) {
2009                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
2010                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
2011                                                 return;
2012                         }
2013                 }
2014
2015                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2016         }
2017 }
2018
2019 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)
2020 {
2021         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
2022         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2023
2024         data.vc= *vc;
2025         data.func = func;
2026         data.userData = userData;
2027         data.clipVerts = clipVerts;
2028
2029         if(clipVerts)
2030                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2031
2032         EM_init_index_arrays(vc->em, 0, 1, 0);
2033         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2034         EM_free_index_arrays();
2035
2036         dm->release(dm);
2037 }
2038
2039 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2040 {
2041         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
2042         EditFace *efa = EM_get_face_for_index(index);
2043         short s[2];
2044
2045         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
2046                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
2047
2048                 data->func(data->userData, efa, s[0], s[1], index);
2049         }
2050 }
2051
2052 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
2053 {
2054         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
2055         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2056
2057         data.vc= *vc;
2058         data.func = func;
2059         data.userData = userData;
2060
2061         //if(clipVerts)
2062         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2063
2064         EM_init_index_arrays(vc->em, 0, 0, 1);
2065         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2066         EM_free_index_arrays();
2067
2068         dm->release(dm);
2069 }
2070
2071 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
2072 {
2073         Curve *cu= vc->obedit->data;
2074         short s[2] = {IS_CLIPPED, 0};
2075         Nurb *nu;
2076         int i;
2077         ListBase *nurbs= curve_editnurbs(cu);
2078
2079         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2080
2081         for (nu= nurbs->first; nu; nu=nu->next) {
2082                 if(nu->type == CU_BEZIER) {
2083                         for (i=0; i<nu->pntsu; i++) {
2084                                 BezTriple *bezt = &nu->bezt[i];
2085
2086                                 if(bezt->hide==0) {
2087                                         
2088                                         if(cu->drawflag & CU_HIDE_HANDLES) {
2089                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2090                                                 if (s[0] != IS_CLIPPED)
2091                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2092                                         } else {
2093                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
2094                                                 if (s[0] != IS_CLIPPED)
2095                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2096                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2097                                                 if (s[0] != IS_CLIPPED)
2098                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2099                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
2100                                                 if (s[0] != IS_CLIPPED)
2101                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2102                                         }
2103                                 }
2104                         }
2105                 }
2106                 else {
2107                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2108                                 BPoint *bp = &nu->bp[i];
2109
2110                                 if(bp->hide==0) {
2111                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
2112                                         if (s[0] != IS_CLIPPED)
2113                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2114                                 }
2115                         }
2116                 }
2117         }
2118 }
2119
2120 /* ************** DRAW MESH ****************** */
2121
2122 /* First section is all the "simple" draw routines, 
2123  * ones that just pass some sort of primitive to GL,
2124  * with perhaps various options to control lighting,
2125  * color, etc.
2126  *
2127  * These routines should not have user interface related
2128  * logic!!!
2129  */
2130
2131 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2132 {
2133         ToolSettings *ts= ((Scene *)userData)->toolsettings;
2134         EditFace *efa = EM_get_face_for_index(index);
2135
2136         if (efa->h==0 && efa->fgonf!=EM_FGON) {
2137                 glVertex3fv(cent);
2138                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
2139                                         cent[1] + no[1]*ts->normalsize,
2140                                         cent[2] + no[2]*ts->normalsize);
2141         }
2142 }
2143 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
2144 {
2145         glBegin(GL_LINES);
2146         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
2147         glEnd();
2148 }
2149
2150 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2151 {
2152         EditFace *efa = EM_get_face_for_index(index);
2153         int sel = *((int*) userData);
2154
2155         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
2156                 bglVertex3fv(cent);
2157         }
2158 }
2159 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
2160 {
2161         bglBegin(GL_POINTS);
2162         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
2163         bglEnd();
2164 }
2165
2166 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2167 {
2168         Scene *scene= (Scene *)userData;
2169         ToolSettings *ts= scene->toolsettings;
2170         EditVert *eve = EM_get_vert_for_index(index);
2171
2172         if (eve->h==0) {
2173                 glVertex3fv(co);
2174
2175                 if (no_f) {
2176                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
2177                                                 co[1] + no_f[1]*ts->normalsize,
2178                                                 co[2] + no_f[2]*ts->normalsize);
2179                 } else {
2180                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
2181                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
2182                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
2183                 }
2184         }
2185 }
2186 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
2187 {
2188         glBegin(GL_LINES);
2189         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
2190         glEnd();
2191 }
2192
2193         /* Draw verts with color set based on selection */
2194 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2195 {
2196         struct { int sel; EditVert *eve_act; } * data = userData;
2197         EditVert *eve = EM_get_vert_for_index(index);
2198
2199         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
2200                 /* draw active larger - need to stop/start point drawing for this :/ */
2201                 if (eve==data->eve_act) {
2202                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2203                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2204                         
2205                         bglEnd();
2206                         
2207                         glPointSize(size);
2208                         bglBegin(GL_POINTS);
2209                         bglVertex3fv(co);
2210                         bglEnd();
2211                         
2212                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2213                         glPointSize(size);
2214                         bglBegin(GL_POINTS);
2215                 } else {
2216                         bglVertex3fv(co);
2217                 }
2218         }
2219 }
2220
2221 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
2222 {
2223         struct { int sel; EditVert *eve_act; } data;
2224         data.sel = sel;
2225         data.eve_act = eve_act;
2226
2227         bglBegin(GL_POINTS);
2228         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2229         bglEnd();
2230 }
2231
2232         /* Draw edges with color set based on selection */
2233 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2234 {
2235         EditEdge *eed = EM_get_edge_for_index(index);
2236         //unsigned char **cols = userData, *col;
2237         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
2238         unsigned char *col;
2239
2240         if (eed->h==0) {
2241                 if (eed==data->eed_act) {
2242                         glColor4ubv(data->actCol);
2243                 } else {
2244                         if (eed->f&SELECT) {
2245                                 col = data->selCol;
2246                         } else {
2247                                 col = data->baseCol;
2248                         }
2249                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2250                         if (col[3]==0) return 0;
2251                         
2252                         glColor4ubv(col);
2253                 }
2254                 return 1;
2255         } else {
2256                 return 0;
2257         }
2258 }
2259 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
2260 {
2261         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
2262         
2263         data.baseCol = baseCol;
2264         data.selCol = selCol;
2265         data.actCol = actCol;
2266         data.eed_act = eed_act;
2267         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2268 }
2269
2270         /* Draw edges */
2271 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2272 {
2273         return EM_get_edge_for_index(index)->h==0;
2274 }
2275 static void draw_dm_edges(DerivedMesh *dm) 
2276 {
2277         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2278 }
2279
2280         /* Draw edges with color interpolated based on selection */
2281 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2282 {
2283         return EM_get_edge_for_index(index)->h==0;
2284 }
2285 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2286 {
2287         EditEdge *eed = EM_get_edge_for_index(index);
2288         unsigned char **cols = userData;
2289         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2290         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2291
2292         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2293                                 col0[1] + (col1[1]-col0[1])*t,
2294                                 col0[2] + (col1[2]-col0[2])*t,
2295                                 col0[3] + (col1[3]-col0[3])*t);
2296 }
2297
2298 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2299 {
2300         unsigned char *cols[2];
2301         cols[0]= baseCol;
2302         cols[1]= selCol;
2303         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2304 }
2305
2306         /* Draw only seam edges */
2307 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2308 {
2309         EditEdge *eed = EM_get_edge_for_index(index);
2310
2311         return (eed->h==0 && eed->seam);
2312 }
2313 static void draw_dm_edges_seams(DerivedMesh *dm)
2314 {
2315         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2316 }
2317
2318         /* Draw only sharp edges */
2319 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2320 {
2321         EditEdge *eed = EM_get_edge_for_index(index);
2322
2323         return (eed->h==0 && eed->sharp);
2324 }
2325 static void draw_dm_edges_sharp(DerivedMesh *dm)
2326 {
2327         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2328 }
2329
2330
2331         /* Draw faces with color set based on selection
2332          * return 2 for the active face so it renders with stipple enabled */
2333 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2334 {
2335         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2336         EditFace *efa = EM_get_face_for_index(index);
2337         unsigned char *col;
2338         
2339         if (efa->h==0) {
2340                 if (efa == data->efa_act) {
2341                         glColor4ubv(data->cols[2]);
2342                         return 2; /* stipple */
2343                 } else {
2344                         col = data->cols[(efa->f&SELECT)?1:0];
2345                         if (col[3]==0) return 0;
2346                         glColor4ubv(col);
2347                         return 1;
2348                 }
2349         }
2350         return 0;
2351 }
2352
2353 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2354 {
2355         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2356         EditFace *efa = EM_get_face_for_index(index);
2357         EditFace *next_efa = EM_get_face_for_index(next_index);
2358         unsigned char *col, *next_col;
2359
2360         if(efa == next_efa)
2361                 return 1;
2362
2363         if(efa == data->efa_act || next_efa == data->efa_act)
2364                 return 0;
2365
2366         col = data->cols[(efa->f&SELECT)?1:0];
2367         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2368
2369         if(col[3]==0 || next_col[3]==0)
2370                 return 0;
2371
2372         return col == next_col;
2373 }
2374
2375 /* also draws the active face */
2376 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2377 {
2378         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2379         data.cols[0] = baseCol;
2380         data.cols[1] = selCol;
2381         data.cols[2] = actCol;
2382         data.efa_act = efa_act;
2383
2384         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2385 }
2386
2387 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2388 {
2389         EditEdge *eed = EM_get_edge_for_index(index);
2390
2391         if (eed->h==0 && eed->crease != 0.0f) {
2392                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2393                 return 1;
2394         } else {
2395                 return 0;
2396         }
2397 }
2398 static void draw_dm_creases(DerivedMesh *dm)
2399 {
2400         glLineWidth(3.0);
2401         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2402         glLineWidth(1.0);
2403 }
2404
2405 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2406 {
2407         EditEdge *eed = EM_get_edge_for_index(index);
2408
2409         if (eed->h==0 && eed->bweight != 0.0f) {
2410                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2411                 return 1;
2412         } else {
2413                 return 0;
2414         }
2415 }
2416 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2417 {
2418         EditVert *eve = EM_get_vert_for_index(index);
2419
2420         if (eve->h==0 && eve->bweight != 0.0f) {
2421                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2422                 bglVertex3fv(co);
2423         }
2424 }
2425 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2426 {
2427         ToolSettings *ts= scene->toolsettings;
2428
2429         if (ts->selectmode & SCE_SELECT_VERTEX) {
2430                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2431                 bglBegin(GL_POINTS);
2432                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2433                 bglEnd();
2434         }
2435         else {
2436                 glLineWidth(3.0);
2437                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2438                 glLineWidth(1.0);
2439         }
2440 }
2441
2442 /* Second section of routines: Combine first sets to form fancy
2443  * drawing routines (for example rendering twice to get overlays).
2444  *
2445  * Also includes routines that are basic drawing but are too
2446  * specialized to be split out (like drawing creases or measurements).
2447  */
2448
2449 /* EditMesh drawing routines*/
2450
2451 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2452 {
2453         ToolSettings *ts= scene->toolsettings;
2454         int sel;
2455
2456         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2457
2458         for (sel=0; sel<2; sel++) {
2459                 unsigned char col[4], fcol[4];
2460                 int pass;
2461
2462                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2463                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2464
2465                 for (pass=0; pass<2; pass++) {
2466                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2467                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2468
2469                         if (pass==0) {
2470                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2471                                         glDisable(GL_DEPTH_TEST);
2472                                                 
2473                                         glEnable(GL_BLEND);
2474                                 } else {
2475                                         continue;
2476                                 }
2477
2478                                 size = (size > 2.1f ? size/2.0f:size);
2479                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2480                                 col[3] = fcol[3] = 100;
2481                         } else {
2482                                 col[3] = fcol[3] = 255;
2483                         }
2484                                 
2485                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2486                                 glPointSize(size);
2487                                 glColor4ubv(col);
2488                                 draw_dm_verts(cageDM, sel, eve_act);
2489                         }
2490                         
2491                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2492                                 glPointSize(fsize);
2493                                 glColor4ubv(fcol);
2494                                 draw_dm_face_centers(cageDM, sel);
2495                         }
2496                         
2497                         if (pass==0) {
2498                                 glDisable(GL_BLEND);
2499                                 glEnable(GL_DEPTH_TEST);
2500                         }
2501                 }
2502         }
2503
2504         if(v3d->zbuf) glDepthMask(1);
2505         glPointSize(1.0);
2506 }
2507
2508 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2509 {
2510         ToolSettings *ts= scene->toolsettings;
2511         int pass;
2512         unsigned char wireCol[4], selCol[4], actCol[4];
2513
2514         /* since this function does transparant... */
2515         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2516         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2517         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2518         
2519         /* when sel only is used, dont render wire, only selected, this is used for
2520          * textured draw mode when the 'edges' option is disabled */
2521         if (sel_only)
2522                 wireCol[3] = 0;
2523
2524         for (pass=0; pass<2; pass++) {
2525                         /* show wires in transparant when no zbuf clipping for select */
2526                 if (pass==0) {
2527                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2528                                 glEnable(GL_BLEND);
2529                                 glDisable(GL_DEPTH_TEST);
2530                                 selCol[3] = 85;
2531                                 if (!sel_only) wireCol[3] = 85;
2532                         } else {
2533                                 continue;
2534                         }
2535                 } else {
2536                         selCol[3] = 255;
2537                         if (!sel_only) wireCol[3] = 255;
2538                 }
2539
2540                 if(ts->selectmode == SCE_SELECT_FACE) {
2541                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2542                 }       
2543                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2544                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2545                                 glShadeModel(GL_SMOOTH);
2546                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2547                                 glShadeModel(GL_FLAT);
2548                         } else {
2549                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2550                         }
2551                 }
2552                 else {
2553                         if (!sel_only) {
2554                                 glColor4ubv(wireCol);
2555                                 draw_dm_edges(cageDM);
2556                         }
2557                 }
2558
2559                 if (pass==0) {
2560                         glDisable(GL_BLEND);
2561                         glEnable(GL_DEPTH_TEST);
2562                 }
2563         }
2564 }       
2565
2566 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2567 {
2568         Mesh *me= ob->data;
2569         EditEdge *eed;
2570         EditFace *efa;
2571         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2572         float fvec[3];
2573         char val[32]; /* Stores the measurement display text here */
2574         const char *conv_float; /* Use a float conversion matching the grid size */
2575         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2576         float area; /* area of the face */
2577         float grid= unit->system ? unit->scale_length : v3d->grid;
2578         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2579         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2580         const int do_moving= G.moving;
2581
2582         /* make the precision of the pronted value proportionate to the gridsize */
2583
2584         if (grid < 0.01f)               conv_float= "%.6g";
2585         else if (grid < 0.1f)   conv_float= "%.5g";
2586         else if (grid < 1.0f)   conv_float= "%.4g";
2587         else if (grid < 10.0f)  conv_float= "%.3g";
2588         else                                    conv_float= "%.2g";
2589
2590         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2591                 glDisable(GL_DEPTH_TEST);
2592
2593         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2594         
2595         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2596                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2597
2598                 for(eed= em->edges.first; eed; eed= eed->next) {
2599                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2600                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2601                                 copy_v3_v3(v1, eed->v1->co);
2602                                 copy_v3_v3(v2, eed->v2->co);
2603
2604                                 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2605
2606                                 if(do_global) {
2607                                         mul_mat3_m4_v3(ob->obmat, v1);
2608                                         mul_mat3_m4_v3(ob->obmat, v2);
2609                                 }
2610                                 if(unit->system)
2611                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2612                                 else
2613                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2614
2615                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2616                         }
2617                 }
2618         }
2619
2620         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2621 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2622                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2623                 
2624                 for(efa= em->faces.first; efa; efa= efa->next) {
2625                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2626                                 copy_v3_v3(v1, efa->v1->co);
2627                                 copy_v3_v3(v2, efa->v2->co);
2628                                 copy_v3_v3(v3, efa->v3->co);
2629                                 if (efa->v4) {
2630                                         copy_v3_v3(v4, efa->v4->co);
2631                                 }
2632                                 if(do_global) {
2633                                         mul_mat3_m4_v3(ob->obmat, v1);
2634                                         mul_mat3_m4_v3(ob->obmat, v2);
2635                                         mul_mat3_m4_v3(ob->obmat, v3);
2636                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2637                                 }
2638                                 
2639                                 if (efa->v4)
2640                                         area=  area_quad_v3(v1, v2, v3, v4);
2641                                 else
2642                                         area = area_tri_v3(v1, v2, v3);
2643
2644                                 if(unit->system)
2645                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2646                                 else
2647                                         sprintf(val, conv_float, area);
2648
2649                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2650                         }
2651                 }
2652         }
2653
2654         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2655                 EditEdge *e1, *e2, *e3, *e4;
2656                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2657                 for(efa= em->faces.first; efa; efa= efa->next) {
2658                         copy_v3_v3(v1, efa->v1->co);
2659                         copy_v3_v3(v2, efa->v2->co);
2660                         copy_v3_v3(v3, efa->v3->co);
2661                         if(efa->v4) {
2662                                 copy_v3_v3(v4, efa->v4->co); 
2663                         }
2664                         else {
2665                                 copy_v3_v3(v4, v3);
2666                         }
2667                         if(do_global) {
2668                                 mul_mat3_m4_v3(ob->obmat, v1);
2669                                 mul_mat3_m4_v3(ob->obmat, v2);
2670                                 mul_mat3_m4_v3(ob->obmat, v3);
2671                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2672                         }
2673                         
2674                         e1= efa->e1;
2675                         e2= efa->e2;
2676                         e3= efa->e3;
2677                         if(efa->e4) e4= efa->e4; else e4= e3;
2678                         
2679                         /* Calculate the angles */
2680                                 
2681                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2682                                 /* Vec 1 */
2683                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2684                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2685                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2686                         }
2687                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2688                                 /* Vec 2 */
2689                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2690                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2691                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2692                         }
2693                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2694                                 /* Vec 3 */
2695                                 if(efa->v4) 
2696                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2697                                 else
2698                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2699                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2700                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2701                         }
2702                                 /* Vec 4 */
2703                         if(efa->v4) {
2704                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2705                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2706                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2707                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2708                                 }
2709                         }
2710                 }
2711         }
2712
2713         /* useful for debugging index vs shape key index */
2714 #if 0
2715         {
2716                 EditVert *eve;
2717                 int j;
2718                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2719                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2720                         sprintf(val, "%d:%d", j, eve->keyindex);
2721                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2722                 }
2723         }
2724 #endif
2725
2726         if(v3d->zbuf) {
2727                 glEnable(GL_DEPTH_TEST);
2728                 bglPolygonOffset(rv3d->dist, 0.0f);
2729         }
2730 }
2731
2732 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2733 {
2734         EditFace *efa = EM_get_face_for_index(index);
2735
2736         if (efa->h==0) {
2737                 GPU_enable_material(efa->mat_nr+1, NULL);
2738                 return 1;
2739         }
2740         else
2741                 return 0;
2742 }
2743
2744 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2745 {
2746         EditFace *efa = EM_get_face_for_index(index);
2747
2748         return (efa->h==0);
2749 }
2750
2751 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2752 {
2753         Mesh *me = ob->data;
2754         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2755         EditEdge *eed_act = NULL;
2756         EditVert *eve_act = NULL;
2757         
2758         if (em->selected.last) {
2759                 EditSelection *ese = em->selected.last;
2760                 /* face is handeled above */
2761                 /*if (ese->type == EDITFACE ) {
2762                         efa_act = (EditFace *)ese->data;
2763                 } else */ if ( ese->type == EDITEDGE ) {
2764                         eed_act = (EditEdge *)ese->data;
2765                 } else if ( ese->type == EDITVERT ) {
2766                         eve_act = (EditVert *)ese->data;
2767                 }
2768         }
2769         
2770         EM_init_index_arrays(em, 1, 1, 1);
2771
2772         if(dt>OB_WIRE) {
2773                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2774                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2775                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2776
2777                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2778                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2779                                 GPU_disable_material();
2780
2781                                 glFrontFace(GL_CCW);
2782                         }
2783                         else {
2784                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2785                         }
2786                 }
2787                 else {
2788                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2789                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2790
2791                         glEnable(GL_LIGHTING);
2792                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2793
2794                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
2795
2796                         glFrontFace(GL_CCW);
2797                         glDisable(GL_LIGHTING);
2798                 }
2799                         
2800                 // Setup for drawing wire over, disable zbuffer
2801                 // write to show selected edge wires better
2802                 UI_ThemeColor(TH_WIRE);
2803
2804                 bglPolygonOffset(rv3d->dist, 1.0);
2805                 glDepthMask(0);
2806         } 
2807         else {
2808                 if (cageDM!=finalDM) {
2809                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2810                         finalDM->drawEdges(finalDM, 1, 0);
2811                 }
2812         }
2813         
2814         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2815                 unsigned char col1[4], col2[4], col3[4];
2816                         
2817                 UI_GetThemeColor4ubv(TH_FACE, col1);
2818                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2819                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2820                 
2821                 glEnable(GL_BLEND);
2822                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2823                 
2824                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2825                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2826                         col1[3] = 0;
2827                 
2828                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2829
2830                 glDisable(GL_BLEND);
2831                 glDepthMask(1);         // restore write in zbuffer
2832         } else if (efa_act) {
2833                 /* even if draw faces is off it would be nice to draw the stipple face
2834                  * Make all other faces zero alpha except for the active
2835                  * */
2836                 unsigned char col1[4], col2[4], col3[4];
2837                 col1[3] = col2[3] = 0; /* dont draw */
2838                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2839                 
2840                 glEnable(GL_BLEND);
2841                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2842                 
2843                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2844
2845                 glDisable(GL_BLEND);
2846                 glDepthMask(1);         // restore write in zbuffer
2847                 
2848         }
2849
2850         /* here starts all fancy draw-extra over */
2851         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2852                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2853                 
2854                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2855                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2856                 
2857         } else {
2858                 if(me->drawflag & ME_DRAWSEAMS) {
2859                         UI_ThemeColor(TH_EDGE_SEAM);
2860                         glLineWidth(2);
2861         
2862                         draw_dm_edges_seams(cageDM);
2863         
2864                         glColor3ub(0,0,0);
2865                         glLineWidth(1);
2866                 }
2867                 
2868                 if(me->drawflag & ME_DRAWSHARP) {
2869                         UI_ThemeColor(TH_EDGE_SHARP);
2870                         glLineWidth(2);
2871         
2872                         draw_dm_edges_sharp(cageDM);
2873         
2874                         glColor3ub(0,0,0);
2875                         glLineWidth(1);
2876                 }
2877         
2878                 if(me->drawflag & ME_DRAWCREASES) {
2879                         draw_dm_creases(cageDM);
2880                 }
2881                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2882                         draw_dm_bweights(scene, cageDM);
2883                 }
2884         
2885                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2886         }
2887         if(em) {
2888 // XXX          retopo_matrix_update(v3d);
2889
2890                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2891
2892                 if(me->drawflag & ME_DRAWNORMALS) {
2893                         UI_ThemeColor(TH_NORMAL);
2894                         draw_dm_face_normals(scene, cageDM);
2895                 }
2896                 if(me->drawflag & ME_DRAW_VNORMALS) {
2897                         UI_ThemeColor(TH_VNORMAL);
2898                         draw_dm_vert_normals(scene, cageDM);
2899                 }
2900
2901                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2902                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2903         }
2904
2905         if(dt>OB_WIRE) {
2906                 glDepthMask(1);
2907                 bglPolygonOffset(rv3d->dist, 0.0);
2908                 GPU_disable_material();
2909         }
2910
2911         EM_free_index_arrays();
2912 }
2913
2914 /* Mesh drawing routines */
2915
2916 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2917 {
2918         
2919         if(v3d->transp==0) {    // not when we draw the transparent pass
2920                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2921                 glDepthMask(0);
2922                 
2923                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2924                    drawFacesSolid() doesn't draw the transparent faces */
2925                 if(ob->dtx & OB_DRAWTRANSP) {
2926                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2927                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2928                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2929                         GPU_disable_material();
2930                 }
2931                 else {
2932                         dm->drawEdges(dm, 0, 1);
2933                 }
2934                                         
2935                 glLineWidth(1.0);
2936                 glDepthMask(1);
2937         }
2938 }
2939
2940 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2941 {
2942         *drawSmooth_r = 1;
2943         return 1;
2944 }
2945
2946 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2947 {
2948         Object *ob= base->object;
2949         Mesh *me = ob->data;
2950         Material *ma= give_current_material(ob, 1);
2951         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2952         const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2953         int draw_wire = 0;
2954         int /* totvert,*/ totedge, totface;
2955         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2956
2957         if(!dm)
2958                 return;
2959         
2960         if (ob->dtx&OB_DRAWWIRE) {
2961                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2962         }
2963         
2964         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2965         totedge = dm->getNumEdges(dm);
2966         totface = dm->getNumFaces(dm);
2967         
2968         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2969         if(dt!=OB_SHADED)
2970                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2971
2972                 // Unwanted combination.
2973         if (is_paint_sel) draw_wire = 0;
2974
2975         if(dt==OB_BOUNDBOX) {
2976                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2977                         draw_bounding_volume(scene, ob);
2978         }
2979         else if(hasHaloMat || (totface==0 && totedge==0)) {
2980                 glPointSize(1.5);
2981                 dm->drawVerts(dm);
2982                 glPointSize(1.0);
2983         }
2984         else if(dt==OB_WIRE || totface==0) {
2985                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2986         }
2987         else if(        (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2988                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2989         {
2990                 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2991                         draw_mesh_object_outline(v3d, ob, dm);
2992                 }
2993
2994                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2995                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2996
2997                         dm->drawFacesGLSL(dm, GPU_enable_material);
2998 //                      if(get_ob_property(ob, "Text"))
2999 // XXX                          draw_mesh_text(ob, 1);
3000                         GPU_disable_material();
3001
3002                         glFrontFace(GL_CCW);
3003                 }
3004                 else {
3005                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
3006                 }
3007
3008                 if(!is_paint_sel) {
3009                         if(base->flag & SELECT)
3010                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
3011                         else
3012                                 UI_ThemeColor(TH_WIRE);
3013
3014                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3015                                 dm->drawLooseEdges(dm);
3016                 }
3017         }
3018         else if(dt==OB_SOLID) {
3019                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
3020                         /* weight paint in solid mode, special case. focus on making the weights clear
3021                          * rather than the shading, this is also forced in wire view */
3022                         GPU_enable_material(0, NULL);
3023                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
3024                 
3025                         bglPolygonOffset(rv3d->dist, 1.0);
3026                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3027
3028                         glEnable(GL_BLEND);
3029                         glColor4ub(255, 255, 255, 96);
3030                         glEnable(GL_LINE_STIPPLE);
3031                         glLineStipple(1, 0xAAAA);
3032
3033                         dm->drawEdges(dm, 1, 1);
3034
3035                         bglPolygonOffset(rv3d->dist, 0.0);
3036                         glDepthMask(1);
3037                         glDisable(GL_LINE_STIPPLE);
3038
3039                         GPU_disable_material();
3040                         
3041                         /* since we already draw wire as wp guide, dont draw over the top */
3042                         draw_wire= 0;
3043                 }
3044                 else {
3045                         Paint *p;
3046
3047                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
3048                                 draw_mesh_object_outline(v3d, ob, dm);
3049
3050                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
3051
3052                         glEnable(GL_LIGHTING);
3053                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3054
3055                         if(ob->sculpt && (p=paint_get_active(scene))) {
3056                                 float planes[4][4];
3057                                 float (*fpl)[4] = NULL;
3058                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
3059
3060                                 if(ob->sculpt->partial_redraw) {
3061                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
3062                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
3063                                                 fpl = planes;
3064                                                 ob->sculpt->partial_redraw = 0;
3065                                         }
3066                                 }
3067
3068                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
3069                         }
3070                         else
3071                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3072
3073                         GPU_disable_material();
3074
3075                         glFrontFace(GL_CCW);
3076                         glDisable(GL_LIGHTING);
3077
3078                         if(base->flag & SELECT) {
3079                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
3080                         } else {
3081                                 UI_ThemeColor(TH_WIRE);
3082                         }
3083                         if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3084                                 dm->drawLooseEdges(dm);
3085                 }
3086         }
3087         else if(dt==OB_SHADED) {
3088                 if(ob==OBACT) {
3089                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
3090                                 /* enforce default material settings */
3091                                 GPU_enable_material(0, NULL);
3092                                 
3093                                 /* but set default spec */
3094                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
3095                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
3096                                 glColor3ub(120, 120, 120);
3097                                 glDisable(GL_COLOR_MATERIAL);
3098                                 /* diffuse */
3099                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
3100                                 glEnable(GL_LIGHTING);
3101                                 glEnable(GL_COLOR_MATERIAL);
3102
3103                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
3104                                 glDisable(GL_COLOR_MATERIAL);
3105                                 glDisable(GL_LIGHTING);
3106
3107                                 GPU_disable_material();
3108                         }
3109                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
3110                                 if(me->mcol)
3111