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