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