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