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