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