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