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