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