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