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