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