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