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