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