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