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