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