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