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