centralize function for calculating pixel size. (no functional changes)
[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);
647                                 }
648                                 else {
649                                         BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], (depth_write)? 0.0f: 2.0f, str);
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         World *wrld;
1222         float nobmat[4][4], vec[8][4], fac, facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1223         int i;
1224
1225         cam= ob->data;
1226         aspx= (float) scene->r.xsch*scene->r.xasp;
1227         aspy= (float) scene->r.ysch*scene->r.yasp;
1228
1229         if(aspx < aspy) {
1230                 caspx= aspx / aspy;
1231                 caspy= 1.0;
1232         }
1233         else {
1234                 caspx= 1.0;
1235                 caspy= aspy / aspx;
1236         }
1237         
1238         glDisable(GL_LIGHTING);
1239         glDisable(GL_CULL_FACE);
1240         
1241         if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1242                 facx= 0.5*cam->ortho_scale*caspx;
1243                 facy= 0.5*cam->ortho_scale*caspy;
1244                 shx= cam->shiftx * cam->ortho_scale;
1245                 shy= cam->shifty * cam->ortho_scale;
1246                 depth= -cam->clipsta-0.1;
1247         }
1248         else {
1249                 fac= cam->drawsize;
1250                 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1251                 
1252                 depth= - fac*cam->lens/16.0;
1253                 facx= fac*caspx;
1254                 facy= fac*caspy;
1255                 shx= cam->shiftx*fac*2;
1256                 shy= cam->shifty*fac*2;
1257         }
1258         
1259         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001;       /* GLBUG: for picking at iris Entry (well thats old!) */
1260         vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1261         vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1262         vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1263         vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1264
1265         glBegin(GL_LINE_LOOP);
1266                 glVertex3fv(vec[1]); 
1267                 glVertex3fv(vec[2]); 
1268                 glVertex3fv(vec[3]); 
1269                 glVertex3fv(vec[4]);
1270         glEnd();
1271         
1272
1273         if(rv3d->persp>=2 && ob==v3d->camera) return;
1274         
1275         glBegin(GL_LINE_STRIP);
1276                 glVertex3fv(vec[2]); 
1277                 glVertex3fv(vec[0]);
1278                 glVertex3fv(vec[1]);
1279                 glVertex3fv(vec[4]);
1280                 glVertex3fv(vec[0]);
1281                 glVertex3fv(vec[3]); 
1282         glEnd();
1283
1284
1285         /* arrow on top */
1286         vec[0][2]= depth;
1287
1288         
1289         /* draw an outline arrow for inactive cameras and filled
1290          * for active cameras. We actually draw both outline+filled
1291          * for active cameras so the wire can be seen side-on */        
1292         for (i=0;i<2;i++) {
1293                 if (i==0) glBegin(GL_LINE_LOOP);
1294                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1295                 else break;
1296
1297                 vec[0][0]= shx + (-0.7 * cam->drawsize);
1298                 vec[0][1]= shy + (cam->drawsize * (caspy + 0.1));
1299                 glVertex3fv(vec[0]); /* left */
1300                 
1301                 vec[0][0]= shx + (0.7 * cam->drawsize);
1302                 glVertex3fv(vec[0]); /* right */
1303                 
1304                 vec[0][0]= shx;
1305                 vec[0][1]= shy + (1.1 * cam->drawsize * (caspy + 0.7));
1306                 glVertex3fv(vec[0]); /* top */
1307         
1308                 glEnd();
1309         }
1310
1311         if(flag==0) {
1312                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1313                         /* draw in normalized object matrix space */
1314                         copy_m4_m4(nobmat, ob->obmat);
1315                         normalize_m4(nobmat);
1316
1317                         glPushMatrix();
1318                         glLoadMatrixf(rv3d->viewmat);
1319                         glMultMatrixf(nobmat);
1320
1321                         if(cam->flag & CAM_SHOWLIMITS) {
1322                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1323                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1324                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
1325                         }
1326
1327                         wrld= scene->world;
1328                         if(cam->flag & CAM_SHOWMIST) 
1329                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1330                                 
1331                         glPopMatrix();
1332                 }
1333         }
1334 }
1335
1336 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1337 {
1338         BPoint *bp = lt->def;
1339         float *co = dl?dl->verts:NULL;
1340         int u, v, w;
1341
1342         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1343         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1344         bglBegin(GL_POINTS);
1345
1346         for(w=0; w<lt->pntsw; w++) {
1347                 int wxt = (w==0 || w==lt->pntsw-1);
1348                 for(v=0; v<lt->pntsv; v++) {
1349                         int vxt = (v==0 || v==lt->pntsv-1);
1350                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1351                                 int uxt = (u==0 || u==lt->pntsu-1);
1352                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1353                                         if(bp->hide==0) {
1354                                                 if((bp->f1 & SELECT)==sel) {
1355                                                         bglVertex3fv(dl?co:bp->vec);
1356                                                 }
1357                                         }
1358                                 }
1359                         }
1360                 }
1361         }
1362         
1363         glPointSize(1.0);
1364         bglEnd();       
1365 }
1366
1367 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1368 {
1369         Object *obedit= vc->obedit;
1370         Lattice *lt= obedit->data;
1371         BPoint *bp = lt->editlatt->latt->def;
1372         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1373         float *co = dl?dl->verts:NULL;
1374         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1375         short s[2] = {IS_CLIPPED, 0};
1376
1377         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1378
1379         for (i=0; i<N; i++, bp++, co+=3) {
1380                 if (bp->hide==0) {
1381                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1382                         if (s[0] != IS_CLIPPED)
1383                                 func(userData, bp, s[0], s[1]);
1384                 }
1385         }
1386 }
1387
1388 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1389 {
1390         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1391
1392         if(use_wcol) {
1393                 float col[3];
1394                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1395                 
1396                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1397                 glColor3fv(col);
1398
1399         }
1400         
1401         if (dl) {
1402                 glVertex3fv(&dl->verts[index*3]);
1403         } else {
1404                 glVertex3fv(lt->def[index].vec);
1405         }
1406 }
1407
1408 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1409 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1410 {
1411         Lattice *lt= ob->data;
1412         DispList *dl;
1413         int u, v, w;
1414         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1415
1416         /* now we default make displist, this will modifiers work for non animated case */
1417         if(ob->disp.first==NULL)
1418                 lattice_calc_modifiers(scene, ob);
1419         dl= find_displist(&ob->disp, DL_VERTS);
1420         
1421         if(is_edit) {
1422                 lt= lt->editlatt->latt;
1423
1424                 cpack(0x004000);
1425                 
1426                 if(ob->defbase.first && lt->dvert) {
1427                         use_wcol= ob->actdef;
1428                         glShadeModel(GL_SMOOTH);
1429                 }
1430         }
1431         
1432         glBegin(GL_LINES);
1433         for(w=0; w<lt->pntsw; w++) {
1434                 int wxt = (w==0 || w==lt->pntsw-1);
1435                 for(v=0; v<lt->pntsv; v++) {
1436                         int vxt = (v==0 || v==lt->pntsv-1);
1437                         for(u=0; u<lt->pntsu; u++) {
1438                                 int uxt = (u==0 || u==lt->pntsu-1);
1439
1440                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1441                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1442                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1443                                 }
1444                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1445                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1446                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1447                                 }
1448                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1449                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1450                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1451                                 }
1452                         }
1453                 }
1454         }               
1455         glEnd();
1456         
1457         /* restoration for weight colors */
1458         if(use_wcol)
1459                 glShadeModel(GL_FLAT);
1460
1461         if(is_edit) {
1462                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1463                 
1464                 lattice_draw_verts(lt, dl, 0);
1465                 lattice_draw_verts(lt, dl, 1);
1466                 
1467                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1468         }
1469 }
1470
1471 /* ***************** ******************** */
1472
1473 /* Note! - foreach funcs should be called while drawing or directly after
1474  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1475  * but would not give correct results with dupli's for eg. which dont
1476  * use the object matrix in the useual way */
1477 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1478 {
1479         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1480         EditVert *eve = EM_get_vert_for_index(index);
1481
1482         if (eve->h==0) {
1483                 short s[2]= {IS_CLIPPED, 0};
1484
1485                 if (data->clipVerts) {
1486                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1487                 } else {
1488                         view3d_project_short_noclip(data->vc.ar, co, s);
1489                 }
1490
1491                 if (s[0]!=IS_CLIPPED)
1492                         data->func(data->userData, eve, s[0], s[1], index);
1493         }
1494 }
1495
1496 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1497 {
1498         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1499         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1500         
1501         data.vc= *vc;
1502         data.func = func;
1503         data.userData = userData;
1504         data.clipVerts = clipVerts;
1505
1506         if(clipVerts)
1507                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1508
1509         EM_init_index_arrays(vc->em, 1, 0, 0);
1510         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1511         EM_free_index_arrays();
1512
1513         dm->release(dm);
1514 }
1515
1516 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1517 {
1518         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;
1519         EditEdge *eed = EM_get_edge_for_index(index);
1520         short s[2][2];
1521
1522         if (eed->h==0) {
1523                 if (data->clipVerts==1) {
1524                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1525                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1526                 } else {
1527                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1528                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1529
1530                         if (data->clipVerts==2) {
1531                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1532                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1533                                                 return;
1534                         }
1535                 }
1536
1537                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1538         }
1539 }
1540
1541 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)
1542 {
1543         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1544         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1545
1546         data.vc= *vc;
1547         data.func = func;
1548         data.userData = userData;
1549         data.clipVerts = clipVerts;
1550
1551         if(clipVerts)
1552                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1553
1554         EM_init_index_arrays(vc->em, 0, 1, 0);
1555         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1556         EM_free_index_arrays();
1557
1558         dm->release(dm);
1559 }
1560
1561 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1562 {
1563         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1564         EditFace *efa = EM_get_face_for_index(index);
1565         short s[2];
1566
1567         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1568                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1569
1570                 data->func(data->userData, efa, s[0], s[1], index);
1571         }
1572 }
1573
1574 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1575 {
1576         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1577         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1578
1579         data.vc= *vc;
1580         data.func = func;
1581         data.userData = userData;
1582
1583         //if(clipVerts)
1584         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1585
1586         EM_init_index_arrays(vc->em, 0, 0, 1);
1587         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1588         EM_free_index_arrays();
1589
1590         dm->release(dm);
1591 }
1592
1593 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1594 {
1595         Curve *cu= vc->obedit->data;
1596         short s[2] = {IS_CLIPPED, 0};
1597         Nurb *nu;
1598         int i;
1599         ListBase *nurbs= ED_curve_editnurbs(cu);
1600
1601         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1602
1603         for (nu= nurbs->first; nu; nu=nu->next) {
1604                 if(nu->type == CU_BEZIER) {
1605                         for (i=0; i<nu->pntsu; i++) {
1606                                 BezTriple *bezt = &nu->bezt[i];
1607
1608                                 if(bezt->hide==0) {
1609                                         
1610                                         if(cu->drawflag & CU_HIDE_HANDLES) {
1611                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1612                                                 if (s[0] != IS_CLIPPED)
1613                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1614                                         } else {
1615                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1616                                                 if (s[0] != IS_CLIPPED)
1617                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1618                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1619                                                 if (s[0] != IS_CLIPPED)
1620                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1621                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1622                                                 if (s[0] != IS_CLIPPED)
1623                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1624                                         }
1625                                 }
1626                         }
1627                 }
1628                 else {
1629                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1630                                 BPoint *bp = &nu->bp[i];
1631
1632                                 if(bp->hide==0) {
1633                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1634                                         if (s[0] != IS_CLIPPED)
1635                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1636                                 }
1637                         }
1638                 }
1639         }
1640 }
1641
1642 /* ************** DRAW MESH ****************** */
1643
1644 /* First section is all the "simple" draw routines, 
1645  * ones that just pass some sort of primitive to GL,
1646  * with perhaps various options to control lighting,
1647  * color, etc.
1648  *
1649  * These routines should not have user interface related
1650  * logic!!!
1651  */
1652
1653 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1654 {
1655         ToolSettings *ts= ((Scene *)userData)->toolsettings;
1656         EditFace *efa = EM_get_face_for_index(index);
1657
1658         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1659                 glVertex3fv(cent);
1660                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1661                                         cent[1] + no[1]*ts->normalsize,
1662                                         cent[2] + no[2]*ts->normalsize);
1663         }
1664 }
1665 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1666 {
1667         glBegin(GL_LINES);
1668         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1669         glEnd();
1670 }
1671
1672 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1673 {
1674         EditFace *efa = EM_get_face_for_index(index);
1675         int sel = *((int*) userData);
1676
1677         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1678                 bglVertex3fv(cent);
1679         }
1680 }
1681 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1682 {
1683         bglBegin(GL_POINTS);
1684         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1685         bglEnd();
1686 }
1687
1688 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1689 {
1690         Scene *scene= (Scene *)userData;
1691         ToolSettings *ts= scene->toolsettings;
1692         EditVert *eve = EM_get_vert_for_index(index);
1693
1694         if (eve->h==0) {
1695                 glVertex3fv(co);
1696
1697                 if (no_f) {
1698                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1699                                                 co[1] + no_f[1]*ts->normalsize,
1700                                                 co[2] + no_f[2]*ts->normalsize);
1701                 } else {
1702                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1703                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1704                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1705                 }
1706         }
1707 }
1708 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1709 {
1710         glBegin(GL_LINES);
1711         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1712         glEnd();
1713 }
1714
1715         /* Draw verts with color set based on selection */
1716 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1717 {
1718         struct { int sel; EditVert *eve_act; } * data = userData;
1719         EditVert *eve = EM_get_vert_for_index(index);
1720
1721         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1722                 /* draw active larger - need to stop/start point drawing for this :/ */
1723                 if (eve==data->eve_act) {
1724                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1725                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1726                         
1727                         bglEnd();
1728                         
1729                         glPointSize(size);
1730                         bglBegin(GL_POINTS);
1731                         bglVertex3fv(co);
1732                         bglEnd();
1733                         
1734                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1735                         glPointSize(size);
1736                         bglBegin(GL_POINTS);
1737                 } else {
1738                         bglVertex3fv(co);
1739                 }
1740         }
1741 }
1742
1743 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1744 {
1745         struct { int sel; EditVert *eve_act; } data;
1746         data.sel = sel;
1747         data.eve_act = eve_act;
1748
1749         bglBegin(GL_POINTS);
1750         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1751         bglEnd();
1752 }
1753
1754         /* Draw edges with color set based on selection */
1755 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1756 {
1757         EditEdge *eed = EM_get_edge_for_index(index);
1758         //unsigned char **cols = userData, *col;
1759         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1760         unsigned char *col;
1761
1762         if (eed->h==0) {
1763                 if (eed==data->eed_act) {
1764                         glColor4ubv(data->actCol);
1765                 } else {
1766                         if (eed->f&SELECT) {
1767                                 col = data->selCol;
1768                         } else {
1769                                 col = data->baseCol;
1770                         }
1771                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1772                         if (col[3]==0) return 0;
1773                         
1774                         glColor4ubv(col);
1775                 }
1776                 return 1;
1777         } else {
1778                 return 0;
1779         }
1780 }
1781 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1782 {
1783         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1784         
1785         data.baseCol = baseCol;
1786         data.selCol = selCol;
1787         data.actCol = actCol;
1788         data.eed_act = eed_act;
1789         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1790 }
1791
1792         /* Draw edges */
1793 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
1794 {
1795         return EM_get_edge_for_index(index)->h==0;
1796 }
1797 static void draw_dm_edges(DerivedMesh *dm) 
1798 {
1799         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1800 }
1801
1802         /* Draw edges with color interpolated based on selection */
1803 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
1804 {
1805         return EM_get_edge_for_index(index)->h==0;
1806 }
1807 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1808 {
1809         EditEdge *eed = EM_get_edge_for_index(index);
1810         unsigned char **cols = userData;
1811         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1812         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1813
1814         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1815                                 col0[1] + (col1[1]-col0[1])*t,
1816                                 col0[2] + (col1[2]-col0[2])*t,
1817                                 col0[3] + (col1[3]-col0[3])*t);
1818 }
1819
1820 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1821 {
1822         unsigned char *cols[2];
1823         cols[0]= baseCol;
1824         cols[1]= selCol;
1825         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1826 }
1827
1828         /* Draw only seam edges */
1829 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
1830 {
1831         EditEdge *eed = EM_get_edge_for_index(index);
1832
1833         return (eed->h==0 && eed->seam);
1834 }
1835 static void draw_dm_edges_seams(DerivedMesh *dm)
1836 {
1837         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1838 }
1839
1840         /* Draw only sharp edges */
1841 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
1842 {
1843         EditEdge *eed = EM_get_edge_for_index(index);
1844
1845         return (eed->h==0 && eed->sharp);
1846 }
1847 static void draw_dm_edges_sharp(DerivedMesh *dm)
1848 {
1849         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1850 }
1851
1852
1853         /* Draw faces with color set based on selection
1854          * return 2 for the active face so it renders with stipple enabled */
1855 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
1856 {
1857         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1858         EditFace *efa = EM_get_face_for_index(index);
1859         unsigned char *col;
1860         
1861         if (efa->h==0) {
1862                 if (efa == data->efa_act) {
1863                         glColor4ubv(data->cols[2]);
1864                         return 2; /* stipple */
1865                 } else {
1866                         col = data->cols[(efa->f&SELECT)?1:0];
1867                         if (col[3]==0) return 0;
1868                         glColor4ubv(col);
1869                         return 1;
1870                 }
1871         }
1872         return 0;
1873 }
1874
1875 /* also draws the active face */
1876 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1877 {
1878         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1879         data.cols[0] = baseCol;
1880         data.cols[1] = selCol;
1881         data.cols[2] = actCol;
1882         data.efa_act = efa_act;
1883
1884         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
1885 }
1886
1887 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
1888 {
1889         EditEdge *eed = EM_get_edge_for_index(index);
1890
1891         if (eed->h==0 && eed->crease!=0.0) {
1892                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
1893                 return 1;
1894         } else {
1895                 return 0;
1896         }
1897 }
1898 static void draw_dm_creases(DerivedMesh *dm)
1899 {
1900         glLineWidth(3.0);
1901         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1902         glLineWidth(1.0);
1903 }
1904
1905 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
1906 {
1907         EditEdge *eed = EM_get_edge_for_index(index);
1908
1909         if (eed->h==0 && eed->bweight!=0.0) {
1910                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1911                 return 1;
1912         } else {
1913                 return 0;
1914         }
1915 }
1916 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1917 {
1918         EditVert *eve = EM_get_vert_for_index(index);
1919
1920         if (eve->h==0 && eve->bweight!=0.0) {
1921                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1922                 bglVertex3fv(co);
1923         }
1924 }
1925 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1926 {
1927         ToolSettings *ts= scene->toolsettings;
1928
1929         if (ts->selectmode & SCE_SELECT_VERTEX) {
1930                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1931                 bglBegin(GL_POINTS);
1932                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1933                 bglEnd();
1934         }
1935         else {
1936                 glLineWidth(3.0);
1937                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1938                 glLineWidth(1.0);
1939         }
1940 }
1941
1942 /* Second section of routines: Combine first sets to form fancy
1943  * drawing routines (for example rendering twice to get overlays).
1944  *
1945  * Also includes routines that are basic drawing but are too
1946  * specialized to be split out (like drawing creases or measurements).
1947  */
1948
1949 /* EditMesh drawing routines*/
1950
1951 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
1952 {
1953         ToolSettings *ts= scene->toolsettings;
1954         int sel;
1955
1956         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
1957
1958         for (sel=0; sel<2; sel++) {
1959                 char col[4], fcol[4];
1960                 int pass;
1961
1962                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1963                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1964
1965                 for (pass=0; pass<2; pass++) {
1966                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1967                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1968
1969                         if (pass==0) {
1970                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1971                                         glDisable(GL_DEPTH_TEST);
1972                                                 
1973                                         glEnable(GL_BLEND);
1974                                 } else {
1975                                         continue;
1976                                 }
1977
1978                                 size = (size>2.1?size/2.0:size);
1979                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1980                                 col[3] = fcol[3] = 100;
1981                         } else {
1982                                 col[3] = fcol[3] = 255;
1983                         }
1984                                 
1985                         if(ts->selectmode & SCE_SELECT_VERTEX) {
1986                                 glPointSize(size);
1987                                 glColor4ubv((GLubyte *)col);
1988                                 draw_dm_verts(cageDM, sel, eve_act);
1989                         }
1990                         
1991                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
1992                                 glPointSize(fsize);
1993                                 glColor4ubv((GLubyte *)fcol);
1994                                 draw_dm_face_centers(cageDM, sel);
1995                         }
1996                         
1997                         if (pass==0) {
1998                                 glDisable(GL_BLEND);
1999                                 glEnable(GL_DEPTH_TEST);
2000                         }
2001                 }
2002         }
2003
2004         if(v3d->zbuf) glDepthMask(1);
2005         glPointSize(1.0);
2006 }
2007
2008 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2009 {
2010         ToolSettings *ts= scene->toolsettings;
2011         int pass;
2012         unsigned char wireCol[4], selCol[4], actCol[4];
2013
2014         /* since this function does transparant... */
2015         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
2016         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
2017         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
2018         
2019         /* when sel only is used, dont render wire, only selected, this is used for
2020          * textured draw mode when the 'edges' option is disabled */
2021         if (sel_only)
2022                 wireCol[3] = 0;
2023
2024         for (pass=0; pass<2; pass++) {
2025                         /* show wires in transparant when no zbuf clipping for select */
2026                 if (pass==0) {
2027                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2028                                 glEnable(GL_BLEND);
2029                                 glDisable(GL_DEPTH_TEST);
2030                                 selCol[3] = 85;
2031                                 if (!sel_only) wireCol[3] = 85;
2032                         } else {
2033                                 continue;
2034                         }
2035                 } else {
2036                         selCol[3] = 255;
2037                         if (!sel_only) wireCol[3] = 255;
2038                 }
2039
2040                 if(ts->selectmode == SCE_SELECT_FACE) {
2041                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2042                 }       
2043                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2044                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2045                                 glShadeModel(GL_SMOOTH);
2046                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2047                                 glShadeModel(GL_FLAT);
2048                         } else {
2049                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2050                         }
2051                 }
2052                 else {
2053                         if (!sel_only) {
2054                                 glColor4ubv(wireCol);
2055                                 draw_dm_edges(cageDM);
2056                         }
2057                 }
2058
2059                 if (pass==0) {
2060                         glDisable(GL_BLEND);
2061                         glEnable(GL_DEPTH_TEST);
2062                 }
2063         }
2064 }       
2065
2066 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2067 {
2068         Mesh *me= ob->data;
2069         EditEdge *eed;
2070         EditFace *efa;
2071         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2072         float fvec[3];
2073         char val[32]; /* Stores the measurement display text here */
2074         char conv_float[5]; /* Use a float conversion matching the grid size */
2075         float area, col[3]; /* area of the face,  color of the text to draw */
2076         float grid= unit->system ? unit->scale_length : v3d->grid;
2077         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2078         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2079         const int do_moving= G.moving;
2080
2081         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
2082                 return;
2083
2084         /* make the precision of the pronted value proportionate to the gridsize */
2085
2086         if (grid < 0.01f)
2087                 strcpy(conv_float, "%.6f");
2088         else if (grid < 0.1f)
2089                 strcpy(conv_float, "%.5f");
2090         else if (grid < 1.0f)
2091                 strcpy(conv_float, "%.4f");
2092         else if (grid < 10.0f)
2093                 strcpy(conv_float, "%.3f");
2094         else
2095                 strcpy(conv_float, "%.2f");
2096         
2097         
2098         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2099                 glDisable(GL_DEPTH_TEST);
2100
2101         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2102         
2103         if(me->drawflag & ME_DRAW_EDGELEN) {
2104                 UI_GetThemeColor3fv(TH_TEXT, col);
2105                 /* make color a bit more red */
2106                 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2107                 else col[0]= col[0]*0.7f + 0.3f;
2108                 glColor3fv(col);
2109                 
2110                 for(eed= em->edges.first; eed; eed= eed->next) {
2111                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2112                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2113                                 copy_v3_v3(v1, eed->v1->co);
2114                                 copy_v3_v3(v2, eed->v2->co);
2115
2116                                 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2117
2118                                 if(do_global) {
2119                                         mul_mat3_m4_v3(ob->obmat, v1);
2120                                         mul_mat3_m4_v3(ob->obmat, v2);
2121                                 }
2122                                 if(unit->system)
2123                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2124                                 else
2125                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2126                                 
2127                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII);
2128                         }
2129                 }
2130         }
2131
2132         if(me->drawflag & ME_DRAW_FACEAREA) {
2133 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2134                 
2135                 UI_GetThemeColor3fv(TH_TEXT, col);
2136                 /* make color a bit more green */
2137                 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2138                 else col[1]= col[1]*0.7f + 0.3f;
2139                 glColor3fv(col);
2140                 
2141                 for(efa= em->faces.first; efa; efa= efa->next) {
2142                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2143                                 copy_v3_v3(v1, efa->v1->co);
2144                                 copy_v3_v3(v2, efa->v2->co);
2145                                 copy_v3_v3(v3, efa->v3->co);
2146                                 if (efa->v4) {
2147                                         copy_v3_v3(v4, efa->v4->co);
2148                                 }
2149                                 if(do_global) {
2150                                         mul_mat3_m4_v3(ob->obmat, v1);
2151                                         mul_mat3_m4_v3(ob->obmat, v2);
2152                                         mul_mat3_m4_v3(ob->obmat, v3);
2153                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2154                                 }
2155                                 
2156                                 if (efa->v4)
2157                                         area=  area_quad_v3(v1, v2, v3, v4);
2158                                 else
2159                                         area = area_tri_v3(v1, v2, v3);
2160
2161                                 if(unit->system)
2162                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2163                                 else
2164                                         sprintf(val, conv_float, area);
2165
2166                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII);
2167                         }
2168                 }
2169         }
2170
2171         if(me->drawflag & ME_DRAW_EDGEANG) {
2172                 EditEdge *e1, *e2, *e3, *e4;
2173                 
2174                 UI_GetThemeColor3fv(TH_TEXT, col);
2175                 /* make color a bit more blue */
2176                 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2177                 else col[2]= col[2]*0.7f + 0.3f;
2178                 glColor3fv(col);
2179                 
2180                 for(efa= em->faces.first; efa; efa= efa->next) {
2181                         copy_v3_v3(v1, efa->v1->co);
2182                         copy_v3_v3(v2, efa->v2->co);
2183                         copy_v3_v3(v3, efa->v3->co);
2184                         if(efa->v4) {
2185                                 copy_v3_v3(v4, efa->v4->co); 
2186                         }
2187                         else {
2188                                 copy_v3_v3(v4, v3);
2189                         }
2190                         if(do_global) {
2191                                 mul_mat3_m4_v3(ob->obmat, v1);
2192                                 mul_mat3_m4_v3(ob->obmat, v2);
2193                                 mul_mat3_m4_v3(ob->obmat, v3);
2194                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2195                         }
2196                         
2197                         e1= efa->e1;
2198                         e2= efa->e2;
2199                         e3= efa->e3;
2200                         if(efa->e4) e4= efa->e4; else e4= e3;
2201                         
2202                         /* Calculate the angles */
2203                                 
2204                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2205                                 /* Vec 1 */
2206                                 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v4, v1, v2)));
2207                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2208                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII);
2209                         }
2210                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2211                                 /* Vec 2 */
2212                                 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v1, v2, v3)));
2213                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2214                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII);
2215                         }
2216                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2217                                 /* Vec 3 */
2218                                 if(efa->v4) 
2219                                         sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v4)));
2220                                 else
2221                                         sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v1)));
2222                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2223                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII);
2224                         }
2225                                 /* Vec 4 */
2226                         if(efa->v4) {
2227                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2228                                         sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v3, v4, v1)));
2229                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2230                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII);
2231                                 }
2232                         }
2233                 }
2234         }
2235         
2236         if(v3d->zbuf) {
2237                 glEnable(GL_DEPTH_TEST);
2238                 bglPolygonOffset(rv3d->dist, 0.0f);
2239         }
2240 }
2241
2242 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2243 {
2244         EditFace *efa = EM_get_face_for_index(index);
2245
2246         if (efa->h==0) {
2247                 GPU_enable_material(efa->mat_nr+1, NULL);
2248                 return 1;
2249         }
2250         else
2251                 return 0;
2252 }
2253
2254 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2255 {
2256         EditFace *efa = EM_get_face_for_index(index);
2257
2258         return (efa->h==0);
2259 }
2260
2261 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2262 {
2263         Mesh *me = ob->data;
2264         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2265         EditEdge *eed_act = NULL;
2266         EditVert *eve_act = NULL;
2267         
2268         if (em->selected.last) {
2269                 EditSelection *ese = em->selected.last;
2270                 /* face is handeled above */
2271                 /*if (ese->type == EDITFACE ) {
2272                         efa_act = (EditFace *)ese->data;
2273                 } else */ if ( ese->type == EDITEDGE ) {
2274                         eed_act = (EditEdge *)ese->data;
2275                 } else if ( ese->type == EDITVERT ) {
2276                         eve_act = (EditVert *)ese->data;
2277                 }
2278         }
2279         
2280         EM_init_index_arrays(em, 1, 1, 1);
2281
2282         if(dt>OB_WIRE) {
2283                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2284                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2285                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2286
2287                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2288                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2289                                 GPU_disable_material();
2290
2291                                 glFrontFace(GL_CCW);
2292                         }
2293                         else {
2294                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2295                         }
2296                 }
2297                 else {
2298                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2299                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2300
2301                         glEnable(GL_LIGHTING);
2302                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2303
2304                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0, GPU_enable_material);
2305
2306                         glFrontFace(GL_CCW);
2307                         glDisable(GL_LIGHTING);
2308                 }
2309                         
2310                 // Setup for drawing wire over, disable zbuffer
2311                 // write to show selected edge wires better
2312                 UI_ThemeColor(TH_WIRE);
2313
2314                 bglPolygonOffset(rv3d->dist, 1.0);
2315                 glDepthMask(0);
2316         } 
2317         else {
2318                 if (cageDM!=finalDM) {
2319                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2320                         finalDM->drawEdges(finalDM, 1, 0);
2321                 }
2322         }
2323         
2324         if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2325                 unsigned char col1[4], col2[4], col3[4];
2326                         
2327                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2328                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2329                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2330                 
2331                 glEnable(GL_BLEND);
2332                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2333                 
2334                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2335                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2336                         col1[3] = 0;
2337                 
2338                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2339
2340                 glDisable(GL_BLEND);
2341                 glDepthMask(1);         // restore write in zbuffer
2342         } else if (efa_act) {
2343                 /* even if draw faces is off it would be nice to draw the stipple face
2344                  * Make all other faces zero alpha except for the active
2345                  * */
2346                 unsigned char col1[4], col2[4], col3[4];
2347                 col1[3] = col2[3] = 0; /* dont draw */
2348                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2349                 
2350                 glEnable(GL_BLEND);
2351                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2352                 
2353                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2354
2355                 glDisable(GL_BLEND);
2356                 glDepthMask(1);         // restore write in zbuffer
2357                 
2358         }
2359
2360         /* here starts all fancy draw-extra over */
2361         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2362                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2363                 
2364                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2365                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2366                 
2367         } else {
2368                 if(me->drawflag & ME_DRAWSEAMS) {
2369                         UI_ThemeColor(TH_EDGE_SEAM);
2370                         glLineWidth(2);
2371         
2372                         draw_dm_edges_seams(cageDM);
2373         
2374                         glColor3ub(0,0,0);
2375                         glLineWidth(1);
2376                 }
2377                 
2378                 if(me->drawflag & ME_DRAWSHARP) {
2379                         UI_ThemeColor(TH_EDGE_SHARP);
2380                         glLineWidth(2);
2381         
2382                         draw_dm_edges_sharp(cageDM);
2383         
2384                         glColor3ub(0,0,0);
2385                         glLineWidth(1);
2386                 }
2387         
2388                 if(me->drawflag & ME_DRAWCREASES) {
2389                         draw_dm_creases(cageDM);
2390                 }
2391                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2392                         draw_dm_bweights(scene, cageDM);
2393                 }
2394         
2395                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2396         }
2397         if(em) {
2398 // XXX          retopo_matrix_update(v3d);
2399
2400                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2401
2402                 if(me->drawflag & ME_DRAWNORMALS) {
2403                         UI_ThemeColor(TH_NORMAL);
2404                         draw_dm_face_normals(scene, cageDM);
2405                 }
2406                 if(me->drawflag & ME_DRAW_VNORMALS) {
2407                         UI_ThemeColor(TH_VNORMAL);
2408                         draw_dm_vert_normals(scene, cageDM);
2409                 }
2410
2411                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2412                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2413         }
2414
2415         if(dt>OB_WIRE) {
2416                 glDepthMask(1);
2417                 bglPolygonOffset(rv3d->dist, 0.0);
2418                 GPU_disable_material();
2419         }
2420
2421         EM_free_index_arrays();
2422 }
2423
2424 /* Mesh drawing routines */
2425
2426 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2427 {
2428         
2429         if(v3d->transp==0) {    // not when we draw the transparent pass
2430                 glLineWidth(2.0);
2431                 glDepthMask(0);
2432                 
2433                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2434                    drawFacesSolid() doesn't draw the transparent faces */
2435                 if(ob->dtx & OB_DRAWTRANSP) {
2436                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2437                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2438                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2439                         GPU_disable_material();
2440                 }
2441                 else {
2442                         dm->drawEdges(dm, 0, 1);
2443                 }
2444                                         
2445                 glLineWidth(1.0);
2446                 glDepthMask(1);
2447         }
2448 }
2449
2450 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2451 {
2452         *drawSmooth_r = 1;
2453         return 1;
2454 }
2455
2456 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2457 {
2458         Object *ob= base->object;
2459         Mesh *me = ob->data;
2460         Material *ma= give_current_material(ob, 1);
2461         int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2462         int draw_wire = 0;
2463         int totvert, totedge, totface;
2464         DispList *dl;
2465         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2466
2467         if(!dm)
2468                 return;
2469         
2470         if (ob->dtx&OB_DRAWWIRE) {
2471                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2472         }
2473         
2474         totvert = dm->getNumVerts(dm);
2475         totedge = dm->getNumEdges(dm);
2476         totface = dm->getNumFaces(dm);
2477         
2478         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2479         if(dt!=OB_SHADED)
2480                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2481
2482                 // Unwanted combination.
2483         if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2484
2485         if(dt==OB_BOUNDBOX) {
2486                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2487                         draw_bounding_volume(scene, ob);
2488         }
2489         else if(hasHaloMat || (totface==0 && totedge==0)) {
2490                 glPointSize(1.5);
2491                 dm->drawVerts(dm);
2492                 glPointSize(1.0);
2493         }
2494         else if(dt==OB_WIRE || totface==0) {
2495                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2496         }
2497         else if(        (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2498                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2499         {
2500                 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2501                 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2502                         draw_mesh_object_outline(v3d, ob, dm);
2503                 }
2504
2505                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2506                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2507
2508                         dm->drawFacesGLSL(dm, GPU_enable_material);
2509 //                      if(get_ob_property(ob, "Text"))
2510 // XXX                          draw_mesh_text(ob, 1);
2511                         GPU_disable_material();
2512
2513                         glFrontFace(GL_CCW);
2514                 }
2515                 else {
2516                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2517                 }
2518
2519                 if(!faceselect) {
2520                         if(base->flag & SELECT)
2521                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2522                         else
2523                                 UI_ThemeColor(TH_WIRE);
2524
2525                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2526                                 dm->drawLooseEdges(dm);
2527                 }
2528         }
2529         else if(dt==OB_SOLID) {
2530                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2531                         /* weight paint in solid mode, special case. focus on making the weights clear
2532                          * rather then the shading, this is also forced in wire view */
2533                         GPU_enable_material(0, NULL);
2534                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2535                 
2536                         bglPolygonOffset(rv3d->dist, 1.0);
2537                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2538
2539                         glEnable(GL_BLEND);
2540                         glColor4ub(255, 255, 255, 96);
2541                         glEnable(GL_LINE_STIPPLE);
2542                         glLineStipple(1, 0xAAAA);
2543
2544                         dm->drawEdges(dm, 1, 1);
2545
2546                         bglPolygonOffset(rv3d->dist, 0.0);
2547                         glDepthMask(1);
2548                         glDisable(GL_LINE_STIPPLE);
2549
2550                         GPU_disable_material();
2551                         
2552                         /* since we already draw wire as wp guide, dont draw over the top */
2553                         draw_wire= 0;
2554                 }
2555                 else {
2556                         Paint *p;
2557
2558                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2559                                 draw_mesh_object_outline(v3d, ob, dm);
2560
2561                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2562
2563                         glEnable(GL_LIGHTING);
2564                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2565
2566                         if(ob->sculpt && (p=paint_get_active(scene))) {
2567                                 float planes[4][4];
2568                                 float (*fpl)[4] = NULL;
2569                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2570
2571                                 if(ob->sculpt->partial_redraw) {
2572                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
2573                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2574                                                 fpl = planes;
2575                                                 ob->sculpt->partial_redraw = 0;
2576                                         }
2577                                 }
2578
2579                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2580                         }
2581                         else
2582                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2583
2584                         GPU_disable_material();
2585
2586                         glFrontFace(GL_CCW);
2587                         glDisable(GL_LIGHTING);
2588
2589                         if(base->flag & SELECT) {
2590                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2591                         } else {
2592                                 UI_ThemeColor(TH_WIRE);
2593                         }
2594                         if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2595                                 dm->drawLooseEdges(dm);
2596                 }
2597         }
2598         else if(dt==OB_SHADED) {
2599                 int do_draw= 1; /* to resolve all G.f settings below... */
2600                 
2601                 if(ob==OBACT) {
2602                         do_draw= 0;
2603                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2604                                 /* enforce default material settings */
2605                                 GPU_enable_material(0, NULL);
2606                                 
2607                                 /* but set default spec */
2608                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2609                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2610                                 glColor3ub(120, 120, 120);
2611                                 glDisable(GL_COLOR_MATERIAL);
2612                                 /* diffuse */
2613                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2614                                 glEnable(GL_LIGHTING);
2615                                 glEnable(GL_COLOR_MATERIAL);
2616
2617                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2618                                 glDisable(GL_COLOR_MATERIAL);
2619                                 glDisable(GL_LIGHTING);
2620
2621                                 GPU_disable_material();
2622                         }
2623                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2624                                 if(me->mcol)
2625                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2626                                 else {
2627                                         glColor3f(1.0f, 1.0f, 1.0f);
2628                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2629                                 }
2630                         }
2631                         else do_draw= 1;
2632                 }
2633                 if(do_draw) {
2634                         dl = ob->disp.first;
2635                         if (!dl || !dl->col1) {
2636                                 /* release and reload derivedmesh because it might be freed in
2637                                    shadeDispList due to a different datamask */
2638                                 dm->release(dm);
2639                                 shadeDispList(scene, base);
2640                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2641                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2642                         }
2643
2644                         if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire) {
2645                                 draw_mesh_object_outline(v3d, ob, dm);
2646                         }
2647
2648                                 /* False for dupliframe objects */
2649                         if (dl) {
2650                                 unsigned int *obCol1 = dl->col1;
2651                                 unsigned int *obCol2 = dl->col2;
2652
2653                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2654                         }
2655
2656                         if(base->flag & SELECT) {
2657                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2658                         } else {
2659                                 UI_ThemeColor(TH_WIRE);
2660                         }
2661                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2662                                 dm->drawLooseEdges(dm);
2663                 }
2664         }
2665         
2666         /* set default draw color back for wire or for draw-extra later on */
2667         if (dt!=OB_WIRE) {
2668                 if(base->flag & SELECT) {
2669                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2670                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2671                         else if(ob->flag & OB_FROMGROUP) 
2672                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2673                         else if(flag!=DRAW_CONSTCOLOR)
2674                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2675                         else
2676                                 glColor3ub(80,80,80);
2677                 } else {
2678                         if (ob->flag & OB_FROMGROUP) 
2679                                 UI_ThemeColor(TH_GROUP);
2680                         else {
2681                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2682                                         glColor3ub(80,80,80);
2683                                 else
2684                                         UI_ThemeColor(TH_WIRE);
2685                         }
2686                 }
2687         }
2688         if (draw_wire) {
2689
2690                 /* When using wireframe object traw in particle edit mode
2691                  * the mesh gets in the way of seeing the particles, fade the wire color
2692                  * with the background. */
2693                 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2694                         float col_wire[4], col_bg[4], col[3];
2695
2696                         UI_GetThemeColor3fv(TH_BACK, col_bg);
2697                         glGetFloatv(GL_CURRENT_COLOR, col_wire);
2698                         interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2699                         glColor3fv(col);
2700                 }
2701
2702                 /* If drawing wire and drawtype is not OB_WIRE then we are
2703                  * overlaying the wires.
2704                  *
2705                  * UPDATE bug #10290 - With this wire-only objects can draw
2706                  * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2707                  *
2708                  * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2709                  * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2710                  */
2711                 if (dt!=OB_WIRE && draw_wire==2) {
2712                         bglPolygonOffset(rv3d->dist, 1.0);
2713                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2714                 }
2715                 
2716                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2717                         dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2718
2719                 if (dt!=OB_WIRE && draw_wire==2) {
2720                         glDepthMask(1);
2721                         bglPolygonOffset(rv3d->dist, 0.0);
2722                 }
2723         }
2724
2725         dm->release(dm);
2726 }
2727
2728 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2729 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2730 {
2731         Object *ob= base->object;
2732         Object *obedit= scene->obedit;
2733         Mesh *me= ob->data;
2734         EditMesh *em= me->edit_mesh;
2735         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2736         
2737         if(obedit && ob!=obedit && ob->data==obedit->data) {
2738                 if(ob_get_key(ob) || ob_get_key(obedit));
2739                 else if(ob->modifiers.first || obedit->modifiers.first);
2740                 else drawlinked= 1;
2741         }
2742         
2743         if(ob==obedit || drawlinked) {
2744                 DerivedMesh *finalDM, *cageDM;
2745                 
2746                 if (obedit!=ob)
2747                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2748                 else
2749                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2750                                                                                         v3d->customdata_mask);
2751
2752                 if(dt>OB_WIRE) {
2753                         // no transp in editmode, the fancy draw over goes bad then
2754                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2755                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2756                 }
2757
2758                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2759
2760                 GPU_end_object_materials();
2761
2762                 if (obedit!=ob && finalDM)
2763                         finalDM->release(finalDM);
2764         }
2765         else {
2766                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2767                 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2768                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2769                         check_alpha = check_material_alpha(base, me, glsl);
2770
2771                         if(dt==OB_SOLID || glsl) {
2772                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2773                                         (check_alpha)? &do_alpha_pass: NULL);
2774                         }
2775
2776                         draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2777
2778                         GPU_end_object_materials();
2779                         
2780                         if(me->totvert==0) retval= 1;
2781                 }
2782         }
2783         
2784         /* GPU_begin_object_materials checked if this is needed */
2785         if(do_alpha_pass) {
2786                 if(ob->dtx & OB_DRAWXRAY) {
2787                         add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2788                 }
2789                 else {
2790                         add_view3d_after(&v3d->afterdraw_transp, base, flag);
2791                 }
2792         }
2793         else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2794                 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2795                 if(v3d->xray == 0 && v3d->transp == 0) {
2796                         add_view3d_after(&v3d->afterdraw_xray, base, flag);
2797                 }
2798         }
2799         
2800         return retval;
2801 }
2802
2803 /* ************** DRAW DISPLIST ****************** */
2804
2805 static int draw_index_wire= 1;
2806 static int index3_nors_incr= 1;
2807
2808 /* returns 1 when nothing was drawn */
2809 static int drawDispListwire(ListBase *dlbase)
2810 {
2811         DispList *dl;
2812         int parts, nr;
2813         float *data;
2814
2815         if(dlbase==NULL) return 1;
2816         
2817         glEnableClientState(GL_VERTEX_ARRAY);
2818         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2819
2820         for(dl= dlbase->first; dl; dl= dl->next) {
2821                 if(dl->parts==0 || dl->nr==0)
2822                         continue;
2823                 
2824                 data= dl->verts;
2825         
2826                 switch(dl->type) {
2827                 case DL_SEGM:
2828                         
2829                         glVertexPointer(3, GL_FLOAT, 0, data);
2830                         
2831                         for(parts=0; parts<dl->parts; parts++)
2832                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2833                                 
2834                         break;
2835                 case DL_POLY:
2836                         
2837                         glVertexPointer(3, GL_FLOAT, 0, data);
2838                         
2839                         for(parts=0; parts<dl->parts; parts++)
2840                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2841                         
2842                         break;
2843                 case DL_SURF:
2844                         
2845                         glVertexPointer(3, GL_FLOAT, 0, data);
2846                         
2847                         for(parts=0; parts<dl->parts; parts++) {
2848                                 if(dl->flag & DL_CYCL_U) 
2849                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2850                                 else
2851                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2852                         }
2853                         
2854                         for(nr=0; nr<dl->nr; nr++) {
2855                                 int ofs= 3*dl->nr;
2856                                 
2857                                 data= (  dl->verts )+3*nr;
2858                                 parts= dl->parts;
2859
2860                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2861                                 else glBegin(GL_LINE_STRIP);
2862                                 
2863                                 while(parts--) {
2864                                         glVertex3fv(data);
2865                                         data+=ofs;
2866                                 }
2867                                 glEnd();
2868                                 
2869                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2870 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2871 //                              if(dl->flag & DL_CYCL_V) 
2872 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2873 //                              else
2874 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2875                         }
2876                         break;
2877                         
2878                 case DL_INDEX3:
2879                         if(draw_index_wire) {
2880                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2881                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2882                         }
2883                         break;
2884                         
2885                 case DL_INDEX4:
2886                         if(draw_index_wire) {
2887                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2888                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2889                         }
2890                         break;
2891                 }
2892         }
2893         
2894         glDisableClientState(GL_VERTEX_ARRAY);
2895         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2896         
2897         return 0;
2898 }
2899
2900 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2901 {
2902         DispList *dl;
2903         GPUVertexAttribs gattribs;
2904         float *data, curcol[4];
2905         float *ndata;
2906         
2907         if(lb==NULL) return;
2908         
2909         /* for drawing wire */
2910         glGetFloatv(GL_CURRENT_COLOR, curcol);
2911
2912         glEnable(GL_LIGHTING);
2913         glEnableClientState(GL_VERTEX_ARRAY);
2914         
2915         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2916         else glFrontFace(GL_CCW);
2917         
2918         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2919                 glShadeModel(GL_SMOOTH);
2920         }
2921         
2922         dl= lb->first;
2923         while(dl) {
2924                 data= dl->verts;
2925                 ndata= dl->nors;
2926
2927                 switch(dl->type) {
2928                 case DL_SEGM:
2929                         if(ob->type==OB_SURF) {
2930                                 int nr;
2931
2932                                 glDisable(GL_LIGHTING);
2933                                 glColor3fv(curcol);
2934                                 
2935                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2936                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2937
2938                                 glBegin(GL_LINE_STRIP);
2939                                 for(nr= dl->nr; nr; nr--, data+=3)
2940                                         glVertex3fv(data);
2941                                 glEnd();
2942
2943                                 glEnable(GL_LIGHTING);
2944                         }
2945                         break;
2946                 case DL_POLY:
2947                         if(ob->type==OB_SURF) {
2948                                 int nr;
2949
2950                                 glDisable(GL_LIGHTING);
2951                                 
2952                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2953                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2954                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2955                                 
2956                                 glBegin(GL_LINE_LOOP);
2957                                 for(nr= dl->nr; nr; nr--, data+=3)
2958                                         glVertex3fv(data);
2959                                 glEnd();
2960                                 
2961                                 glEnable(GL_LIGHTING);
2962                                 break;
2963                         }
2964                 case DL_SURF:
2965                         
2966                         if(dl->index) {
2967                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2968                                 
2969                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2970                                 else glShadeModel(GL_FLAT);
2971
2972                                 glEnableClientState(GL_NORMAL_ARRAY);
2973                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2974                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2975                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2976                                 glDisableClientState(GL_NORMAL_ARRAY);
2977                         }                       
2978                         break;
2979
2980                 case DL_INDEX3:
2981                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2982                         
2983                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2984                         
2985                         /* voor polys only one normal needed */
2986                         if(index3_nors_incr) {
2987                                 glEnableClientState(GL_NORMAL_ARRAY);
2988                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2989                         }
2990                         else
2991                                 glNormal3fv(ndata);
2992                         
2993                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2994                         
2995                         if(index3_nors_incr)
2996                                 glDisableClientState(GL_NORMAL_ARRAY);
2997
2998                         break;
2999
3000                 case DL_INDEX4:
3001                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
3002                         
3003                         glEnableClientState(GL_NORMAL_ARRAY);
3004                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3005                         glNormalPointer(GL_FLOAT, 0, dl->nors);
3006                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
3007                         glDisableClientState(GL_NORMAL_ARRAY);
3008
3009                         break;
3010                 }
3011                 dl= dl->next;
3012         }
3013
3014         glDisableClientState(GL_VERTEX_ARRAY);
3015         glShadeModel(GL_FLAT);
3016         glDisable(GL_LIGHTING);
3017         glFrontFace(GL_CCW);
3018 }
3019
3020 static void drawDispListshaded(ListBase *lb, Object *ob)
3021 {
3022         DispList *dl, *dlob;
3023         unsigned int *cdata;
3024
3025         if(lb==NULL) return;
3026
3027         glShadeModel(GL_SMOOTH);
3028         glEnableClientState(GL_VERTEX_ARRAY);
3029         glEnableClientState(GL_COLOR_ARRAY);
3030         
3031         dl= lb->first;
3032         dlob= ob->disp.first;
3033         while(dl && dlob) {
3034                 
3035                 cdata= dlob->col1;
3036                 if(cdata==NULL) break;
3037                 
3038                 switch(dl->type) {
3039                 case DL_SURF:
3040                         if(dl->index) {
3041                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3042                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
3043                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
3044                         }                       
3045                         break;
3046
3047                 case DL_INDEX3:
3048                         
3049                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3050                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
3051                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3052                         break;
3053
3054                 case DL_INDEX4: