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