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