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