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