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