Tomato Cycles: fix incorrect memory read when synchronizing mesh motion
[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_bg[3], col[3];
199         float col_wire[3] = {ob_wire_col[0] / 255.0f,
200                              ob_wire_col[1] / 255.0f,
201                              ob_wire_col[2] / 255.0f};
202
203         UI_GetThemeColor3fv(theme_id, col_bg);
204         interp_v3_v3v3(col, col_bg, col_wire, fac);
205         glColor3fv(col);
206 }
207
208 /* this condition has been made more complex since editmode can draw textures */
209 static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
210 {
211         /* texture and material draw modes */
212         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID)
213                 return TRUE;
214
215         /* textured solid */
216         if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene))
217                 return TRUE;
218         
219         return FALSE;
220 }
221
222 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
223 {
224         if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
225                 return 0;
226
227         if (G.f & G_BACKBUFSEL)
228                 return 0;
229
230         if ((vd->flag & V3D_ZBUF_SELECT) == 0)
231                 return 1;
232
233         /* if its drawing textures with zbuf sel, then don't draw dots */
234         if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
235                 return 0;
236
237         if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
238                 return 0;
239
240         return 1;
241 }
242
243 /* ************* only use while object drawing **************
244  * or after running ED_view3d_init_mats_rv3d
245  * */
246 static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int is_local)
247 {
248         RegionView3D *rv3d = ar->regiondata;
249         float fx, fy, vec4[4];
250         
251         adr[0] = IS_CLIPPED;
252         
253         /* clipplanes in eye space */
254         if (rv3d->rflag & RV3D_CLIPPING) {
255                 if (ED_view3d_clipping_test(rv3d, vec, is_local))
256                         return;
257         }
258         
259         copy_v3_v3(vec4, vec);
260         vec4[3] = 1.0;
261         
262         mul_m4_v4(rv3d->persmatob, vec4);
263         
264         /* clipplanes in window space */
265         if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
266                 fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
267                 
268                 if (fx > 0 && fx < ar->winx) {
269                         
270                         fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
271                         
272                         if (fy > 0.0f && fy < (float)ar->winy) {
273                                 adr[0] = (short)floorf(fx);
274                                 adr[1] = (short)floorf(fy);
275                         }
276                 }
277         }
278 }
279
280 /* BMESH NOTE: this function is unused in bmesh only */
281
282 /* only use while object drawing */
283 static void UNUSED_FUNCTION(view3d_project_short_noclip) (ARegion * ar, const float vec[3], short adr[2])
284 {
285         RegionView3D *rv3d = ar->regiondata;
286         float fx, fy, vec4[4];
287         
288         adr[0] = IS_CLIPPED;
289         
290         copy_v3_v3(vec4, vec);
291         vec4[3] = 1.0;
292         
293         mul_m4_v4(rv3d->persmatob, vec4);
294         
295         if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
296                 fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
297                 
298                 if (fx > -32700 && fx < 32700) {
299                         
300                         fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
301                         
302                         if (fy > -32700.0f && fy < 32700.0f) {
303                                 adr[0] = (short)floorf(fx);
304                                 adr[1] = (short)floorf(fy);
305                         }
306                 }
307         }
308 }
309
310 /* same as view3d_project_short_clip but use persmat instead of persmatob for projection */
311 static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], short adr[2], int is_local)
312 {
313         RegionView3D *rv3d = ar->regiondata;
314         float fx, fy, vec4[4];
315
316         adr[0] = IS_CLIPPED;
317
318         /* clipplanes in eye space */
319         if (rv3d->rflag & RV3D_CLIPPING) {
320                 if (ED_view3d_clipping_test(rv3d, vec, is_local))
321                         return;
322         }
323
324         copy_v3_v3(vec4, vec);
325         vec4[3] = 1.0;
326
327         mul_m4_v4(rv3d->persmat, vec4);
328
329         /* clipplanes in window space */
330         if (vec4[3] > (float)BL_NEAR_CLIP) {    /* is the NEAR clipping cutoff for picking */
331                 fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]);
332
333                 if (fx > 0 && fx < ar->winx) {
334
335                         fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]);
336
337                         if (fy > 0.0f && fy < (float)ar->winy) {
338                                 adr[0] = (short)floorf(fx);
339                                 adr[1] = (short)floorf(fy);
340                         }
341                 }
342         }
343 }
344 /* ************************ */
345
346 /* check for glsl drawing */
347
348 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt)
349 {
350         if (!GPU_glsl_support())
351                 return 0;
352         if (G.f & G_PICKSEL)
353                 return 0;
354         if (!check_object_draw_texture(scene, v3d, dt))
355                 return 0;
356         if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
357                 return 0;
358         if (BKE_scene_use_new_shading_nodes(scene))
359                 return 0;
360         
361         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
362 }
363
364 static int check_alpha_pass(Base *base)
365 {
366         if (base->flag & OB_FROMDUPLI)
367                 return 0;
368
369         if (G.f & G_PICKSEL)
370                 return 0;
371         
372         return (base->object->dtx & OB_DRAWTRANSP);
373 }
374
375 /***/
376 static unsigned int colortab[24] =
377 {0x0,       0xFF88FF, 0xFFBBFF,
378  0x403000,  0xFFFF88, 0xFFFFBB,
379  0x104040,  0x66CCCC, 0x77CCCC,
380  0x104010,  0x55BB55, 0x66FF66,
381  0xFFFFFF};
382
383
384 static float cube[8][3] = {
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         { 1.0,  1.0, -1.0},
393 };
394
395 /* ----------------- OpenGL Circle Drawing - Tables for Optimized Drawing Speed ------------------ */
396 /* 32 values of sin function (still same result!) */
397 #define CIRCLE_RESOL 32
398
399 static const float sinval[CIRCLE_RESOL] = {
400         0.00000000,
401         0.20129852,
402         0.39435585,
403         0.57126821,
404         0.72479278,
405         0.84864425,
406         0.93775213,
407         0.98846832,
408         0.99871650,
409         0.96807711,
410         0.89780453,
411         0.79077573,
412         0.65137248,
413         0.48530196,
414         0.29936312,
415         0.10116832,
416         -0.10116832,
417         -0.29936312,
418         -0.48530196,
419         -0.65137248,
420         -0.79077573,
421         -0.89780453,
422         -0.96807711,
423         -0.99871650,
424         -0.98846832,
425         -0.93775213,
426         -0.84864425,
427         -0.72479278,
428         -0.57126821,
429         -0.39435585,
430         -0.20129852,
431         0.00000000
432 };
433
434 /* 32 values of cos function (still same result!) */
435 static const float cosval[CIRCLE_RESOL] = {
436         1.00000000,
437         0.97952994,
438         0.91895781,
439         0.82076344,
440         0.68896691,
441         0.52896401,
442         0.34730525,
443         0.15142777,
444         -0.05064916,
445         -0.25065253,
446         -0.44039415,
447         -0.61210598,
448         -0.75875812,
449         -0.87434661,
450         -0.95413925,
451         -0.99486932,
452         -0.99486932,
453         -0.95413925,
454         -0.87434661,
455         -0.75875812,
456         -0.61210598,
457         -0.44039415,
458         -0.25065253,
459         -0.05064916,
460         0.15142777,
461         0.34730525,
462         0.52896401,
463         0.68896691,
464         0.82076344,
465         0.91895781,
466         0.97952994,
467         1.00000000
468 };
469
470 static void draw_xyz_wire(const float c[3], float size, int axis)
471 {
472         float v1[3] = {0.f, 0.f, 0.f}, v2[3] = {0.f, 0.f, 0.f};
473         float dim = size * 0.1f;
474         float dx[3], dy[3], dz[3];
475
476         dx[0] = dim; dx[1] = 0.f; dx[2] = 0.f;
477         dy[0] = 0.f; dy[1] = dim; dy[2] = 0.f;
478         dz[0] = 0.f; dz[1] = 0.f; dz[2] = dim;
479
480         switch (axis) {
481                 case 0:     /* x axis */
482                         glBegin(GL_LINES);
483                         
484                         /* bottom left to top right */
485                         sub_v3_v3v3(v1, c, dx);
486                         sub_v3_v3(v1, dy);
487                         add_v3_v3v3(v2, c, dx);
488                         add_v3_v3(v2, dy);
489                         
490                         glVertex3fv(v1);
491                         glVertex3fv(v2);
492                         
493                         /* top left to bottom right */
494                         mul_v3_fl(dy, 2.f);
495                         add_v3_v3(v1, dy);
496                         sub_v3_v3(v2, dy);
497                         
498                         glVertex3fv(v1);
499                         glVertex3fv(v2);
500                         
501                         glEnd();
502                         break;
503                 case 1:     /* y axis */
504                         glBegin(GL_LINES);
505                         
506                         /* bottom left to top right */
507                         mul_v3_fl(dx, 0.75f);
508                         sub_v3_v3v3(v1, c, dx);
509                         sub_v3_v3(v1, dy);
510                         add_v3_v3v3(v2, c, dx);
511                         add_v3_v3(v2, dy);
512                         
513                         glVertex3fv(v1);
514                         glVertex3fv(v2);
515                         
516                         /* top left to center */
517                         mul_v3_fl(dy, 2.f);
518                         add_v3_v3(v1, dy);
519                         copy_v3_v3(v2, c);
520                         
521                         glVertex3fv(v1);
522                         glVertex3fv(v2);
523                         
524                         glEnd();
525                         break;
526                 case 2:     /* z axis */
527                         glBegin(GL_LINE_STRIP);
528                         
529                         /* start at top left */
530                         sub_v3_v3v3(v1, c, dx);
531                         add_v3_v3v3(v1, c, dz);
532                         
533                         glVertex3fv(v1);
534                         
535                         mul_v3_fl(dx, 2.f);
536                         add_v3_v3(v1, dx);
537
538                         glVertex3fv(v1);
539                         
540                         mul_v3_fl(dz, 2.f);
541                         sub_v3_v3(v1, dx);
542                         sub_v3_v3(v1, dz);
543                         
544                         glVertex3fv(v1);
545                         
546                         add_v3_v3(v1, dx);
547                 
548                         glVertex3fv(v1);
549                         
550                         glEnd();
551                         break;
552         }
553         
554 }
555
556 void drawaxes(float size, char drawtype)
557 {
558         int axis;
559         float v1[3] = {0.0, 0.0, 0.0};
560         float v2[3] = {0.0, 0.0, 0.0};
561         float v3[3] = {0.0, 0.0, 0.0};
562         
563         switch (drawtype) {
564
565                 case OB_PLAINAXES:
566                         for (axis = 0; axis < 3; axis++) {
567                                 glBegin(GL_LINES);
568
569                                 v1[axis] = size;
570                                 v2[axis] = -size;
571                                 glVertex3fv(v1);
572                                 glVertex3fv(v2);
573
574                                 /* reset v1 & v2 to zero */
575                                 v1[axis] = v2[axis] = 0.0f;
576
577                                 glEnd();
578                         }
579                         break;
580                 case OB_SINGLE_ARROW:
581
582                         glBegin(GL_LINES);
583                         /* in positive z direction only */
584                         v1[2] = size;
585                         glVertex3fv(v1);
586                         glVertex3fv(v2);
587                         glEnd();
588
589                         /* square pyramid */
590                         glBegin(GL_TRIANGLES);
591
592                         v2[0] = size * 0.035f; v2[1] = size * 0.035f;
593                         v3[0] = size * -0.035f; v3[1] = size * 0.035f;
594                         v2[2] = v3[2] = size * 0.75f;
595
596                         for (axis = 0; axis < 4; axis++) {
597                                 if (axis % 2 == 1) {
598                                         v2[0] = -v2[0];
599                                         v3[1] = -v3[1];
600                                 }
601                                 else {
602                                         v2[1] = -v2[1];
603                                         v3[0] = -v3[0];
604                                 }
605
606                                 glVertex3fv(v1);
607                                 glVertex3fv(v2);
608                                 glVertex3fv(v3);
609
610                         }
611                         glEnd();
612
613                         break;
614                 case OB_CUBE:
615                         drawcube_size(size);
616                         break;
617
618                 case OB_CIRCLE:
619                         drawcircle_size(size);
620                         break;
621
622                 case OB_EMPTY_SPHERE:
623                         draw_empty_sphere(size);
624                         break;
625
626                 case OB_EMPTY_CONE:
627                         draw_empty_cone(size);
628                         break;
629
630                 case OB_ARROWS:
631                 default:
632                 {
633                         for (axis = 0; axis < 3; axis++) {
634                                 const int arrow_axis = (axis == 0) ? 1 : 0;
635
636                                 glBegin(GL_LINES);
637
638                                 v2[axis] = size;
639                                 glVertex3fv(v1);
640                                 glVertex3fv(v2);
641                                 
642                                 v1[axis] = size * 0.85f;
643                                 v1[arrow_axis] = -size * 0.08f;
644                                 glVertex3fv(v1);
645                                 glVertex3fv(v2);
646                                 
647                                 v1[arrow_axis] = size * 0.08f;
648                                 glVertex3fv(v1);
649                                 glVertex3fv(v2);
650
651                                 glEnd();
652                                 
653                                 v2[axis] += size * 0.125f;
654
655                                 draw_xyz_wire(v2, size, axis);
656
657
658                                 /* reset v1 & v2 to zero */
659                                 v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
660                         }
661                         break;
662                 }
663         }
664 }
665
666
667 /* Function to draw an Image on a empty Object */
668 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
669 {
670         Image *ima = (Image *)ob->data;
671         ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
672
673         float scale, ofs_x, ofs_y, sca_x, sca_y;
674         int ima_x, ima_y;
675
676         if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
677                 IMB_rect_from_float(ibuf);
678         }
679
680         /* Get the buffer dimensions so we can fallback to fake ones */
681         if (ibuf && ibuf->rect) {
682                 ima_x = ibuf->x;
683                 ima_y = ibuf->y;
684         }
685         else {
686                 ima_x = 1;
687                 ima_y = 1;
688         }
689
690         /* Get the image aspect even if the buffer is invalid */
691         if (ima) {
692                 if (ima->aspx > ima->aspy) {
693                         sca_x = 1.0f;
694                         sca_y = ima->aspy / ima->aspx;
695                 }
696                 else if (ima->aspx < ima->aspy) {
697                         sca_x = ima->aspx / ima->aspy;
698                         sca_y = 1.0f;
699                 }
700                 else {
701                         sca_x = 1.0f;
702                         sca_y = 1.0f;
703                 }
704         }
705         else {
706                 sca_x = 1.0f;
707                 sca_y = 1.0f;
708         }
709
710         /* Calculate the scale center based on objects origin */
711         ofs_x = ob->ima_ofs[0] * ima_x;
712         ofs_y = ob->ima_ofs[1] * ima_y;
713
714         glMatrixMode(GL_MODELVIEW);
715         glPushMatrix();
716
717         /* Make sure we are drawing at the origin */
718         glTranslatef(0.0f,  0.0f,  0.0f);
719
720         /* Calculate Image scale */
721         scale = (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y));
722
723         /* Set the object scale */
724         glScalef(scale * sca_x, scale * sca_y, 1.0f);
725
726         if (ibuf && ibuf->rect) {
727                 /* Setup GL params */
728                 glEnable(GL_BLEND);
729                 glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
730
731                 /* Use the object color and alpha */
732                 glColor4fv(ob->col);
733
734                 /* Draw the Image on the screen */
735                 glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
736                 glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
737
738                 glDisable(GL_BLEND);
739         }
740
741         if ((dflag & DRAW_CONSTCOLOR) == 0) {
742                 glColor3ubv(ob_wire_col);
743
744                 /* Calculate the outline vertex positions */
745                 glBegin(GL_LINE_LOOP);
746                 glVertex2f(ofs_x, ofs_y);
747                 glVertex2f(ofs_x + ima_x, ofs_y);
748                 glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
749                 glVertex2f(ofs_x, ofs_y + ima_y);
750                 glEnd();
751         }
752
753         /* Reset GL settings */
754         glMatrixMode(GL_MODELVIEW);
755         glPopMatrix();
756 }
757
758 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
759 {
760         float vx[3], vy[3];
761         float *viter = (float *)verts;
762         unsigned int a;
763
764         mul_v3_v3fl(vx, tmat[0], rad);
765         mul_v3_v3fl(vy, tmat[1], rad);
766
767         for (a = 0; a < CIRCLE_RESOL; a++, viter += 3) {
768                 viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0];
769                 viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1];
770                 viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2];
771         }
772 }
773
774 void drawcircball(int mode, const float cent[3], float rad, float tmat[][4])
775 {
776         float verts[CIRCLE_RESOL][3];
777
778         circball_array_fill(verts, cent, rad, tmat);
779
780         glEnableClientState(GL_VERTEX_ARRAY);
781         glVertexPointer(3, GL_FLOAT, 0, verts);
782         glDrawArrays(mode, 0, CIRCLE_RESOL);
783         glDisableClientState(GL_VERTEX_ARRAY);
784 }
785
786 /* circle for object centers, special_color is for library or ob users */
787 static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, int special_color)
788 {
789         const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
790         float verts[CIRCLE_RESOL][3];
791
792         /* using gldepthfunc guarantees that it does write z values,
793          * but not checks for it, so centers remain visible independent order of drawing */
794         if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
795         glEnable(GL_BLEND);
796         
797         if (special_color) {
798                 if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
799
800                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
801         }
802         else {
803                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
804                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
805                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
806         }
807
808         circball_array_fill(verts, co, size, rv3d->viewinv);
809
810         /* enable vertex array */
811         glEnableClientState(GL_VERTEX_ARRAY);
812         glVertexPointer(3, GL_FLOAT, 0, verts);
813
814         /* 1. draw filled, blended polygon */
815         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
816
817         /* 2. draw outline */
818         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
819         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
820
821         /* finish up */
822         glDisableClientState(GL_VERTEX_ARRAY);
823
824         glDisable(GL_BLEND);
825
826         if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
827 }
828
829 /* *********** text drawing for object/particles/armature ************* */
830 static ListBase CachedText[3];
831 static int CachedTextLevel = 0;
832
833 typedef struct ViewCachedString {
834         struct ViewCachedString *next, *prev;
835         float vec[3];
836         union {
837                 unsigned char ub[4];
838                 int pack;
839         } col;
840         short sco[2];
841         short xoffs;
842         short flag;
843         int str_len, pad;
844         /* str is allocated past the end */
845 } ViewCachedString;
846
847 void view3d_cached_text_draw_begin(void)
848 {
849         ListBase *strings = &CachedText[CachedTextLevel];
850         strings->first = strings->last = NULL;
851         CachedTextLevel++;
852 }
853
854 void view3d_cached_text_draw_add(const float co[3],
855                                  const char *str,
856                                  short xoffs, short flag,
857                                  const unsigned char col[4])
858 {
859         int alloc_len = strlen(str) + 1;
860         ListBase *strings = &CachedText[CachedTextLevel - 1];
861         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
862         ViewCachedString *vos = MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
863
864         BLI_addtail(strings, vos);
865         copy_v3_v3(vos->vec, co);
866         copy_v4_v4_char((char *)vos->col.ub, (const char *)col);
867         vos->xoffs = xoffs;
868         vos->flag = flag;
869         vos->str_len = alloc_len - 1;
870
871         /* allocate past the end */
872         memcpy(++vos, str, alloc_len);
873 }
874
875 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
876 {
877         RegionView3D *rv3d = ar->regiondata;
878         ListBase *strings = &CachedText[CachedTextLevel - 1];
879         ViewCachedString *vos;
880         int tot = 0;
881         
882         /* project first and test */
883         for (vos = strings->first; vos; vos = vos->next) {
884                 if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
885                         mul_m4_v3(mat, vos->vec);
886
887                 if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE)
888                         view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
889                 else
890                         view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0);
891
892                 if (vos->sco[0] != IS_CLIPPED)
893                         tot++;
894         }
895
896         if (tot) {
897                 int col_pack_prev = 0;
898
899 #if 0
900                 bglMats mats; /* ZBuffer depth vars */
901                 double ux, uy, uz;
902                 float depth;
903
904                 if (v3d->zbuf)
905                         bgl_get_mats(&mats);
906 #endif
907                 if (rv3d->rflag & RV3D_CLIPPING) {
908                         ED_view3d_clipping_disable();
909                 }
910
911                 glMatrixMode(GL_PROJECTION);
912                 glPushMatrix();
913                 glMatrixMode(GL_MODELVIEW);
914                 glPushMatrix();
915                 ED_region_pixelspace(ar);
916                 
917                 if (depth_write) {
918                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
919                 }
920                 else {
921                         glDepthMask(0);
922                 }
923                 
924                 for (vos = strings->first; vos; vos = vos->next) {
925                         /* too slow, reading opengl info while drawing is very bad,
926                          * better to see if we can use the zbuffer while in pixel space - campbell */
927 #if 0
928                         if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
929                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
930                                 glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
931
932                                 if (uz > depth)
933                                         continue;
934                         }
935 #endif
936                         if (vos->sco[0] != IS_CLIPPED) {
937                                 const char *str = (char *)(vos + 1);
938
939                                 if (col_pack_prev != vos->col.pack) {
940                                         glColor3ubv(vos->col.ub);
941                                         col_pack_prev = vos->col.pack;
942                                 }
943
944                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
945                                  BLF_draw_default_ascii :
946                                  BLF_draw_default
947                                 )( (float)vos->sco[0] + vos->xoffs,
948                                    (float)vos->sco[1],
949                                    (depth_write) ? 0.0f : 2.0f,
950                                    str,
951                                    vos->str_len);
952                         }
953                 }
954                 
955                 if (depth_write) {
956                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
957                 }
958                 else glDepthMask(1);
959                 
960                 glMatrixMode(GL_PROJECTION);
961                 glPopMatrix();
962                 glMatrixMode(GL_MODELVIEW);
963                 glPopMatrix();
964
965                 if (rv3d->rflag & RV3D_CLIPPING) {
966                         ED_view3d_clipping_enable();
967                 }
968         }
969         
970         if (strings->first)
971                 BLI_freelistN(strings);
972         
973         CachedTextLevel--;
974 }
975
976 /* ******************** primitive drawing ******************* */
977
978 static void drawcube(void)
979 {
980
981         glBegin(GL_LINE_STRIP);
982         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
983         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
984         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
985         glEnd();
986
987         glBegin(GL_LINE_STRIP);
988         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
989         glEnd();
990
991         glBegin(GL_LINE_STRIP);
992         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
993         glEnd();
994
995         glBegin(GL_LINE_STRIP);
996         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
997         glEnd();
998 }
999
1000 /* draws a cube on given the scaling of the cube, assuming that 
1001  * all required matrices have been set (used for drawing empties)
1002  */
1003 static void drawcube_size(float size)
1004 {
1005         glBegin(GL_LINE_STRIP);
1006         glVertex3f(-size, -size, -size); glVertex3f(-size, -size, size);
1007         glVertex3f(-size, size, size); glVertex3f(-size, size, -size);
1008
1009         glVertex3f(-size, -size, -size); glVertex3f(size, -size, -size);
1010         glVertex3f(size, -size, size); glVertex3f(size, size, size);
1011
1012         glVertex3f(size, size, -size); glVertex3f(size, -size, -size);
1013         glEnd();
1014
1015         glBegin(GL_LINE_STRIP);
1016         glVertex3f(-size, -size, size); glVertex3f(size, -size, size);
1017         glEnd();
1018
1019         glBegin(GL_LINE_STRIP);
1020         glVertex3f(-size, size, size); glVertex3f(size, size, size);
1021         glEnd();
1022
1023         glBegin(GL_LINE_STRIP);
1024         glVertex3f(-size, size, -size); glVertex3f(size, size, -size);
1025         glEnd();
1026 }
1027
1028 /* this is an unused (old) cube-drawing function based on a given size */
1029 #if 0
1030 static void drawcube_size(const float size[3])
1031 {
1032
1033         glPushMatrix();
1034         glScalef(size[0],  size[1],  size[2]);
1035         
1036
1037         glBegin(GL_LINE_STRIP);
1038         glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
1039         glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[6]);
1040         glVertex3fv(cube[7]); glVertex3fv(cube[4]);
1041         glEnd();
1042
1043         glBegin(GL_LINE_STRIP);
1044         glVertex3fv(cube[1]); glVertex3fv(cube[5]);
1045         glEnd();
1046
1047         glBegin(GL_LINE_STRIP);
1048         glVertex3fv(cube[2]); glVertex3fv(cube[6]);
1049         glEnd();
1050
1051         glBegin(GL_LINE_STRIP);
1052         glVertex3fv(cube[3]); glVertex3fv(cube[7]);
1053         glEnd();
1054         
1055         glPopMatrix();
1056 }
1057 #endif
1058
1059 static void drawshadbuflimits(Lamp *la, float mat[][4])
1060 {
1061         float sta[3], end[3], lavec[3];
1062
1063         negate_v3_v3(lavec, mat[2]);
1064         normalize_v3(lavec);
1065
1066         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
1067         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
1068
1069         glBegin(GL_LINE_STRIP);
1070         glVertex3fv(sta);
1071         glVertex3fv(end);
1072         glEnd();
1073
1074         glPointSize(3.0);
1075         bglBegin(GL_POINTS);
1076         bglVertex3fv(sta);
1077         bglVertex3fv(end);
1078         bglEnd();
1079         glPointSize(1.0);
1080 }
1081
1082
1083
1084 static void spotvolume(float lvec[3], float vvec[3], const float inp)
1085 {
1086         /* camera is at 0,0,0 */
1087         float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
1088
1089         normalize_v3(lvec);
1090         normalize_v3(vvec);             /* is this the correct vector ? */
1091
1092         cross_v3_v3v3(temp, vvec, lvec);      /* equation for a plane through vvec en lvec */
1093         cross_v3_v3v3(plane, lvec, temp);     /* a plane perpendicular to this, parrallel with lvec */
1094
1095         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1096         if (normalize_v3(plane) == 0.0f)
1097                 plane[1] = 1.0f;
1098
1099         /* now we've got two equations: one of a cone and one of a plane, but we have
1100          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
1101
1102         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1103         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1104
1105         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1106         
1107         q[1] =  plane[1];
1108         q[2] = -plane[0];
1109         q[3] =  0;
1110         normalize_v3(&q[1]);
1111
1112         angle = saacos(plane[2]) / 2.0f;
1113         co = cosf(angle);
1114         si = sqrtf(1 - co * co);
1115
1116         q[0] =  co;
1117         q[1] *= si;
1118         q[2] *= si;
1119         q[3] =  0;
1120
1121         quat_to_mat3(mat1, q);
1122
1123         /* rotate lamp vector now over acos(inp) degrees */
1124         copy_v3_v3(vvec, lvec);
1125
1126         unit_m3(mat2);
1127         co = inp;
1128         si = sqrtf(1.0f - inp * inp);
1129
1130         mat2[0][0] =  co;
1131         mat2[1][0] = -si;
1132         mat2[0][1] =  si;
1133         mat2[1][1] =  co;
1134         mul_m3_m3m3(mat3, mat2, mat1);
1135
1136         mat2[1][0] =  si;
1137         mat2[0][1] = -si;
1138         mul_m3_m3m3(mat4, mat2, mat1);
1139         transpose_m3(mat1);
1140
1141         mul_m3_m3m3(mat2, mat1, mat3);
1142         mul_m3_v3(mat2, lvec);
1143         mul_m3_m3m3(mat2, mat1, mat4);
1144         mul_m3_v3(mat2, vvec);
1145
1146         return;
1147 }
1148
1149 static void draw_spot_cone(Lamp *la, float x, float z)
1150 {
1151         z = fabs(z);
1152
1153         glBegin(GL_TRIANGLE_FAN);
1154         glVertex3f(0.0f, 0.0f, -x);
1155
1156         if (la->mode & LA_SQUARE) {
1157                 glVertex3f(z, z, 0);
1158                 glVertex3f(-z, z, 0);
1159                 glVertex3f(-z, -z, 0);
1160                 glVertex3f(z, -z, 0);
1161                 glVertex3f(z, z, 0);
1162         }
1163         else {
1164                 float angle;
1165                 int a;
1166
1167                 for (a = 0; a < 33; a++) {
1168                         angle = a * M_PI * 2 / (33 - 1);
1169                         glVertex3f(z * cosf(angle), z * sinf(angle), 0);
1170                 }
1171         }
1172
1173         glEnd();
1174 }
1175
1176 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1177 {
1178         glEnable(GL_CULL_FACE);
1179         glEnable(GL_BLEND);
1180         glDepthMask(0);
1181
1182         /* draw backside darkening */
1183         glCullFace(GL_FRONT);
1184
1185         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1186         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1187
1188         draw_spot_cone(la, x, z);
1189
1190         /* draw front side lighting */
1191         glCullFace(GL_BACK);
1192
1193         glBlendFunc(GL_ONE, GL_ONE);
1194         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1195
1196         draw_spot_cone(la, x, z);
1197
1198         /* restore state */
1199         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1200         glDisable(GL_BLEND);
1201         glDepthMask(1);
1202         glDisable(GL_CULL_FACE);
1203         glCullFace(GL_BACK);
1204 }
1205
1206 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1207                      const short dt, const short dflag, const unsigned char ob_wire_col[4])
1208 {
1209         Object *ob = base->object;
1210         const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1211         Lamp *la = ob->data;
1212         float vec[3], lvec[3], vvec[3], circrad, x, y, z;
1213         float lampsize;
1214         float imat[4][4];
1215
1216         unsigned char curcol[4];
1217         unsigned char col[4];
1218         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1219         /* the moment of view3d_draw_transp() call */
1220         const short is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1221         const short drawcone = ((dt > OB_WIRE) &&
1222                                 !(G.f & G_PICKSEL) &&
1223                                 (la->type == LA_SPOT) &&
1224                                 (la->mode & LA_SHOW_CONE) &&
1225                                 !(base->flag & OB_FROMDUPLI) &&
1226                                 !is_view);
1227
1228         if (drawcone && !v3d->transp) {
1229                 /* in this case we need to draw delayed */
1230                 ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
1231                 return;
1232         }
1233         
1234         /* we first draw only the screen aligned & fixed scale stuff */
1235         glPushMatrix();
1236         glLoadMatrixf(rv3d->viewmat);
1237
1238         /* lets calculate the scale: */
1239         lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1240
1241         /* and view aligned matrix: */
1242         copy_m4_m4(imat, rv3d->viewinv);
1243         normalize_v3(imat[0]);
1244         normalize_v3(imat[1]);
1245
1246         /* lamp center */
1247         copy_v3_v3(vec, ob->obmat[3]);
1248
1249         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1250                 /* for AA effects */
1251                 curcol[0] = ob_wire_col[0];
1252                 curcol[1] = ob_wire_col[1];
1253                 curcol[2] = ob_wire_col[2];
1254                 curcol[3] = 154;
1255                 glColor4ubv(curcol);
1256         }
1257
1258         if (lampsize > 0.0f) {
1259
1260                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1261                         if (ob->id.us > 1) {
1262                                 if (ob == OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1263                                 else glColor4ub(0x77, 0xCC, 0xCC, 155);
1264                         }
1265                 }
1266                 
1267                 /* Inner Circle */
1268                 glEnable(GL_BLEND);
1269                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1270                 glDisable(GL_BLEND);
1271                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1272                 
1273                 /* restore */
1274                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1275                         if (ob->id.us > 1)
1276                                 glColor4ubv(curcol);
1277                 }
1278
1279                 /* Outer circle */
1280                 circrad = 3.0f * lampsize;
1281                 setlinestyle(3);
1282
1283                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1284
1285                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1286                 if (la->type != LA_HEMI) {
1287                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1288                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1289                         }
1290                 }
1291         }
1292         else {
1293                 setlinestyle(3);
1294                 circrad = 0.0f;
1295         }
1296         
1297         /* draw the pretty sun rays */
1298         if (la->type == LA_SUN) {
1299                 float v1[3], v2[3], mat[3][3];
1300                 short axis;
1301                 
1302                 /* setup a 45 degree rotation matrix */
1303                 vec_rot_to_mat3(mat, imat[2], (float)M_PI / 4.0f);
1304                 
1305                 /* vectors */
1306                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1307                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1308                 
1309                 /* center */
1310                 glTranslatef(vec[0], vec[1], vec[2]);
1311                 
1312                 setlinestyle(3);
1313                 
1314                 glBegin(GL_LINES);
1315                 for (axis = 0; axis < 8; axis++) {
1316                         glVertex3fv(v1);
1317                         glVertex3fv(v2);
1318                         mul_m3_v3(mat, v1);
1319                         mul_m3_v3(mat, v2);
1320                 }
1321                 glEnd();
1322                 
1323                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1324
1325         }
1326         
1327         if (la->type == LA_LOCAL) {
1328                 if (la->mode & LA_SPHERE) {
1329                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1330                 }
1331         }
1332         
1333         glPopMatrix();  /* back in object space */
1334         zero_v3(vec);
1335         
1336         if (is_view) {
1337                 /* skip drawing extra info */
1338         }
1339         else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
1340                 lvec[0] = lvec[1] = 0.0;
1341                 lvec[2] = 1.0;
1342                 x = rv3d->persmat[0][2];
1343                 y = rv3d->persmat[1][2];
1344                 z = rv3d->persmat[2][2];
1345                 vvec[0] = x * ob->obmat[0][0] + y * ob->obmat[0][1] + z * ob->obmat[0][2];
1346                 vvec[1] = x * ob->obmat[1][0] + y * ob->obmat[1][1] + z * ob->obmat[1][2];
1347                 vvec[2] = x * ob->obmat[2][0] + y * ob->obmat[2][1] + z * ob->obmat[2][2];
1348
1349                 y = cosf(la->spotsize * (float)(M_PI / 360.0));
1350                 spotvolume(lvec, vvec, y);
1351                 x = -la->dist;
1352                 mul_v3_fl(lvec, x);
1353                 mul_v3_fl(vvec, x);
1354
1355                 /* draw the angled sides of the cone */
1356                 glBegin(GL_LINE_STRIP);
1357                 glVertex3fv(vvec);
1358                 glVertex3fv(vec);
1359                 glVertex3fv(lvec);
1360                 glEnd();
1361                 
1362                 z = x * sqrtf(1.0f - y * y);
1363                 x *= y;
1364
1365                 /* draw the circle/square at the end of the cone */
1366                 glTranslatef(0.0, 0.0,  x);
1367                 if (la->mode & LA_SQUARE) {
1368                         float tvec[3];
1369                         float z_abs = fabs(z);
1370
1371                         tvec[0] = tvec[1] = z_abs;
1372                         tvec[2] = 0.0;
1373
1374                         glBegin(GL_LINE_LOOP);
1375                         glVertex3fv(tvec);
1376                         tvec[1] = -z_abs; /* neg */
1377                         glVertex3fv(tvec);
1378                         tvec[0] = -z_abs; /* neg */
1379                         glVertex3fv(tvec);
1380                         tvec[1] = z_abs; /* pos */
1381                         glVertex3fv(tvec);
1382                         glEnd();
1383                 }
1384                 else circ(0.0, 0.0, fabsf(z));
1385                 
1386                 /* draw the circle/square representing spotbl */
1387                 if (la->type == LA_SPOT) {
1388                         float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2));
1389                         /* hide line if it is zero size or overlaps with outer border,
1390                          * previously it adjusted to always to show it but that seems
1391                          * confusing because it doesn't show the actual blend size */
1392                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1393                                 circ(0.0, 0.0, spotblcirc);
1394                 }
1395
1396                 if (drawcone)
1397                         draw_transp_spot_volume(la, x, z);
1398
1399                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1400                 glTranslatef(0.0, 0.0, -x);  /* reverse translation above */
1401                 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1402                         float lvec_clip[3];
1403                         float vvec_clip[3];
1404                         float clipsta_fac = la->clipsta / -x;
1405
1406                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1407                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1408
1409                         glBegin(GL_LINE_STRIP);
1410                         glVertex3fv(lvec_clip);
1411                         glVertex3fv(vvec_clip);
1412                         glEnd();
1413                 }
1414         }
1415         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1416                 
1417                 /* draw the line from the circle along the dist */
1418                 glBegin(GL_LINE_STRIP);
1419                 vec[2] = -circrad;
1420                 glVertex3fv(vec);
1421                 vec[2] = -la->dist;
1422                 glVertex3fv(vec);
1423                 glEnd();
1424                 
1425                 if (la->type == LA_HEMI) {
1426                         /* draw the hemisphere curves */
1427                         short axis, steps, dir;
1428                         float outdist, zdist, mul;
1429                         zero_v3(vec);
1430                         outdist = 0.14; mul = 1.4; dir = 1;
1431                         
1432                         setlinestyle(4);
1433                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1434                         for (axis = 0; axis < 4; axis++) {
1435                                 float v[3] = {0.0, 0.0, 0.0};
1436                                 zdist = 0.02;
1437                                 
1438                                 glBegin(GL_LINE_STRIP);
1439                                 
1440                                 for (steps = 0; steps < 6; steps++) {
1441                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1442                                                 /* make the arcs start at the edge of the energy circle */
1443                                                 if (steps == 0) v[0] = dir * circrad;
1444                                                 else v[0] = v[0] + dir * (steps * outdist);
1445                                         }
1446                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1447                                                 /* make the arcs start at the edge of the energy circle */
1448                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1449                                         }
1450
1451                                         v[2] = v[2] - steps * zdist;
1452                                         
1453                                         glVertex3fv(v);
1454                                         
1455                                         zdist = zdist * mul;
1456                                 }
1457                                 
1458                                 glEnd();
1459                                 /* flip the direction */
1460                                 dir = -dir;
1461                         }
1462                 }
1463         }
1464         else if (la->type == LA_AREA) {
1465                 setlinestyle(3);
1466                 if (la->area_shape == LA_AREA_SQUARE)
1467                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1468                 else if (la->area_shape == LA_AREA_RECT)
1469                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1470
1471                 glBegin(GL_LINE_STRIP);
1472                 glVertex3f(0.0, 0.0, -circrad);
1473                 glVertex3f(0.0, 0.0, -la->dist);
1474                 glEnd();
1475         }
1476         
1477         /* and back to viewspace */
1478         glLoadMatrixf(rv3d->viewmat);
1479         copy_v3_v3(vec, ob->obmat[3]);
1480
1481         setlinestyle(0);
1482         
1483         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1484                 drawshadbuflimits(la, ob->obmat);
1485         }
1486         
1487         UI_GetThemeColor4ubv(TH_LAMP, col);
1488         glColor4ubv(col);
1489
1490         glEnable(GL_BLEND);
1491         
1492         if (vec[2] > 0) vec[2] -= circrad;
1493         else vec[2] += circrad;
1494         
1495         glBegin(GL_LINE_STRIP);
1496         glVertex3fv(vec);
1497         vec[2] = 0;
1498         glVertex3fv(vec);
1499         glEnd();
1500         
1501         glPointSize(2.0);
1502         glBegin(GL_POINTS);
1503         glVertex3fv(vec);
1504         glEnd();
1505         glPointSize(1.0);
1506         
1507         glDisable(GL_BLEND);
1508         
1509         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1510                 /* restore for drawing extra stuff */
1511                 glColor3ubv(ob_wire_col);
1512         }
1513 }
1514
1515 static void draw_limit_line(float sta, float end, unsigned int col)
1516 {
1517         glBegin(GL_LINES);
1518         glVertex3f(0.0, 0.0, -sta);
1519         glVertex3f(0.0, 0.0, -end);
1520         glEnd();
1521
1522         glPointSize(3.0);
1523         glBegin(GL_POINTS);
1524         cpack(col);
1525         glVertex3f(0.0, 0.0, -sta);
1526         glVertex3f(0.0, 0.0, -end);
1527         glEnd();
1528         glPointSize(1.0);
1529 }               
1530
1531
1532 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1533 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1534 static void draw_focus_cross(float dist, float size)
1535 {
1536         glBegin(GL_LINES);
1537         glVertex3f(-size, 0.f, -dist);
1538         glVertex3f(size, 0.f, -dist);
1539         glVertex3f(0.f, -size, -dist);
1540         glVertex3f(0.f, size, -dist);
1541         glEnd();
1542 }
1543
1544 #ifdef VIEW3D_CAMERA_BORDER_HACK
1545 unsigned char view3d_camera_border_hack_col[3];
1546 short view3d_camera_border_hack_test = FALSE;
1547 #endif
1548
1549 /* ****************** draw clip data *************** */
1550
1551 static void draw_bundle_sphere(void)
1552 {
1553         static GLuint displist = 0;
1554
1555         if (displist == 0) {
1556                 GLUquadricObj *qobj;
1557
1558                 displist = glGenLists(1);
1559                 glNewList(displist, GL_COMPILE);
1560
1561                 qobj = gluNewQuadric();
1562                 gluQuadricDrawStyle(qobj, GLU_FILL);
1563                 glShadeModel(GL_SMOOTH);
1564                 gluSphere(qobj, 0.05, 8, 8);
1565                 glShadeModel(GL_FLAT);
1566                 gluDeleteQuadric(qobj);
1567
1568                 glEndList();
1569         }
1570
1571         glCallList(displist);
1572 }
1573
1574 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1575                                                 MovieClip *clip, MovieTrackingObject *tracking_object,
1576                                                 const short dflag, 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[4], scol[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);
1586         UI_GetThemeColor4ubv(TH_SELECT, scol);
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 (selected) {
1630                                 if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1631                                 else UI_ThemeColor(TH_SELECT);
1632                         }
1633                         else {
1634                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1635                                 else UI_ThemeColor(TH_WIRE);
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 (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1647                                         else UI_ThemeColor(TH_SELECT);
1648
1649                                         glLineWidth(2.f);
1650                                         glDisable(GL_LIGHTING);
1651                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1652
1653                                         draw_bundle_sphere();
1654
1655                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1656                                         glEnable(GL_LIGHTING);
1657                                         glLineWidth(1.f);
1658                                 }
1659
1660                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1661                                 else UI_ThemeColor(TH_BUNDLE_SOLID);
1662
1663                                 draw_bundle_sphere();
1664                         }
1665                         else {
1666                                 glDisable(GL_LIGHTING);
1667
1668                                 if (selected) {
1669                                         if (base == BASACT) UI_ThemeColor(TH_ACTIVE);
1670                                         else UI_ThemeColor(TH_SELECT);
1671                                 }
1672                                 else {
1673                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1674                                         else UI_ThemeColor(TH_WIRE);
1675                                 }
1676
1677                                 drawaxes(0.05f, v3d->bundle_drawtype);
1678
1679                                 glEnable(GL_LIGHTING);
1680                         }
1681                 }
1682
1683                 glPopMatrix();
1684
1685                 if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1686                         float pos[3];
1687                         unsigned char tcol[4];
1688
1689                         if (selected) memcpy(tcol, scol, sizeof(tcol));
1690                         else memcpy(tcol, col, sizeof(tcol));
1691
1692                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1693                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
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, &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                 return DM_DRAW_OPTION_NORMAL;
3147         }
3148         else
3149            &nb