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