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