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