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