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