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