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