3f11703973dda1a6f01cdce7cd9f3ac51f7c6151
[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], StereoViews 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) ?
930                                  BLF_draw_default_ascii :
931                                  BLF_draw_default
932                                  )((float)(vos->sco[0] + vos->xoffs),
933                                    (float)(vos->sco[1]),
934                                    (depth_write) ? 0.0f : 2.0f,
935                                    vos->str,
936                                    vos->str_len);
937                         }
938                 }
939
940                 if (depth_write) {
941                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
942                 }
943                 else {
944                         glDepthMask(1);
945                 }
946                 
947                 glMatrixMode(GL_PROJECTION);
948                 glPopMatrix();
949                 glMatrixMode(GL_MODELVIEW);
950                 glPopMatrix();
951
952                 if (rv3d->rflag & RV3D_CLIPPING) {
953                         ED_view3d_clipping_enable();
954                 }
955         }
956
957         g_v3d_strings[g_v3d_string_level] = NULL;
958
959         if (g_v3d_string_level == 0) {
960                 if (g_v3d_strings_arena) {
961                         BLI_memarena_free(g_v3d_strings_arena);
962                         g_v3d_strings_arena = NULL;
963                 }
964         }
965
966         g_v3d_string_level--;
967 }
968
969 /* ******************** primitive drawing ******************* */
970
971 /* draws a cube given the scaling of the cube, assuming that
972  * all required matrices have been set (used for drawing empties)
973  */
974 static void drawcube_size(float size)
975 {
976         const GLfloat pos[8][3] = {
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                 { size,  size, -size},
984                 { size,  size,  size}
985         };
986
987         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};
988
989         glEnableClientState(GL_VERTEX_ARRAY);
990         glVertexPointer(3, GL_FLOAT, 0, pos);
991         glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
992         glDisableClientState(GL_VERTEX_ARRAY);
993 }
994
995 static void drawshadbuflimits(Lamp *la, float mat[4][4])
996 {
997         float sta[3], end[3], lavec[3];
998
999         negate_v3_v3(lavec, mat[2]);
1000         normalize_v3(lavec);
1001
1002         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
1003         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
1004
1005         glBegin(GL_LINES);
1006         glVertex3fv(sta);
1007         glVertex3fv(end);
1008         glEnd();
1009
1010         glPointSize(3.0);
1011         glBegin(GL_POINTS);
1012         glVertex3fv(sta);
1013         glVertex3fv(end);
1014         glEnd();
1015 }
1016
1017 static void spotvolume(float lvec[3], float vvec[3], const float inp)
1018 {
1019         /* camera is at 0,0,0 */
1020         float temp[3], plane[3], mat1[3][3], mat2[3][3], mat3[3][3], mat4[3][3], q[4], co, si, angle;
1021
1022         normalize_v3(lvec);
1023         normalize_v3(vvec);             /* is this the correct vector ? */
1024
1025         cross_v3_v3v3(temp, vvec, lvec);      /* equation for a plane through vvec and lvec */
1026         cross_v3_v3v3(plane, lvec, temp);     /* a plane perpendicular to this, parallel with lvec */
1027
1028         /* vectors are exactly aligned, use the X axis, this is arbitrary */
1029         if (normalize_v3(plane) == 0.0f)
1030                 plane[1] = 1.0f;
1031
1032         /* now we've got two equations: one of a cone and one of a plane, but we have
1033          * three unknowns. We remove one unknown by rotating the plane to z=0 (the plane normal) */
1034
1035         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1036         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1037
1038         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1039         
1040         q[1] =  plane[1];
1041         q[2] = -plane[0];
1042         q[3] =  0;
1043         normalize_v3(&q[1]);
1044
1045         angle = saacos(plane[2]) / 2.0f;
1046         co = cosf(angle);
1047         si = sqrtf(1 - co * co);
1048
1049         q[0] =  co;
1050         q[1] *= si;
1051         q[2] *= si;
1052         q[3] =  0;
1053
1054         quat_to_mat3(mat1, q);
1055
1056         /* rotate lamp vector now over acos(inp) degrees */
1057         copy_v3_v3(vvec, lvec);
1058
1059         unit_m3(mat2);
1060         co = inp;
1061         si = sqrtf(1.0f - inp * inp);
1062
1063         mat2[0][0] =  co;
1064         mat2[1][0] = -si;
1065         mat2[0][1] =  si;
1066         mat2[1][1] =  co;
1067         mul_m3_m3m3(mat3, mat2, mat1);
1068
1069         mat2[1][0] =  si;
1070         mat2[0][1] = -si;
1071         mul_m3_m3m3(mat4, mat2, mat1);
1072         transpose_m3(mat1);
1073
1074         mul_m3_m3m3(mat2, mat1, mat3);
1075         mul_m3_v3(mat2, lvec);
1076         mul_m3_m3m3(mat2, mat1, mat4);
1077         mul_m3_v3(mat2, vvec);
1078 }
1079
1080 static void draw_spot_cone(Lamp *la, float x, float z)
1081 {
1082         z = fabsf(z);
1083
1084         glBegin(GL_TRIANGLE_FAN);
1085         glVertex3f(0.0f, 0.0f, -x);
1086
1087         if (la->mode & LA_SQUARE) {
1088                 glVertex3f(z, z, 0);
1089                 glVertex3f(-z, z, 0);
1090                 glVertex3f(-z, -z, 0);
1091                 glVertex3f(z, -z, 0);
1092                 glVertex3f(z, z, 0);
1093         }
1094         else {
1095                 for (int a = 0; a < 33; a++) {
1096                         float angle = a * M_PI * 2 / (33 - 1);
1097                         glVertex3f(z * cosf(angle), z * sinf(angle), 0);
1098                 }
1099         }
1100
1101         glEnd();
1102 }
1103
1104 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1105 {
1106         glEnable(GL_CULL_FACE);
1107         glEnable(GL_BLEND);
1108         glDepthMask(0);
1109
1110         /* draw backside darkening */
1111         glCullFace(GL_FRONT);
1112
1113         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1114         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1115
1116         draw_spot_cone(la, x, z);
1117
1118         /* draw front side lighting */
1119         glCullFace(GL_BACK);
1120
1121         glBlendFunc(GL_ONE, GL_ONE);
1122         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1123
1124         draw_spot_cone(la, x, z);
1125
1126         /* restore state */
1127         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1128         glDisable(GL_BLEND);
1129         glDepthMask(1);
1130         glDisable(GL_CULL_FACE);
1131         glCullFace(GL_BACK);
1132 }
1133
1134 #ifdef WITH_GAMEENGINE
1135 static void draw_transp_sun_volume(Lamp *la)
1136 {
1137         float box[8][3];
1138
1139         /* construct box */
1140         box[0][0] = box[1][0] = box[2][0] = box[3][0] = -la->shadow_frustum_size;
1141         box[4][0] = box[5][0] = box[6][0] = box[7][0] = +la->shadow_frustum_size;
1142         box[0][1] = box[1][1] = box[4][1] = box[5][1] = -la->shadow_frustum_size;
1143         box[2][1] = box[3][1] = box[6][1] = box[7][1] = +la->shadow_frustum_size;
1144         box[0][2] = box[3][2] = box[4][2] = box[7][2] = -la->clipend;
1145         box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta;
1146
1147         /* draw edges */
1148         draw_box(box, false);
1149
1150         /* draw faces */
1151         glEnable(GL_CULL_FACE);
1152         glEnable(GL_BLEND);
1153         glDepthMask(0);
1154
1155         /* draw backside darkening */
1156         glCullFace(GL_FRONT);
1157
1158         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1159         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1160
1161         draw_box(box, true);
1162
1163         /* draw front side lighting */
1164         glCullFace(GL_BACK);
1165
1166         glBlendFunc(GL_ONE, GL_ONE);
1167         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1168
1169         draw_box(box, true);
1170
1171         /* restore state */
1172         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1173         glDisable(GL_BLEND);
1174         glDepthMask(1);
1175         glDisable(GL_CULL_FACE);
1176         glCullFace(GL_BACK);
1177 }
1178 #endif
1179
1180 static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
1181                      const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
1182 {
1183         Object *ob = base->object;
1184         const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1185         Lamp *la = ob->data;
1186         float vec[3], lvec[3], vvec[3], circrad;
1187         float lampsize;
1188         float imat[4][4];
1189
1190         unsigned char curcol[4];
1191         unsigned char col[4];
1192         /* cone can't be drawn for duplicated lamps, because duplilist would be freed */
1193         /* the moment of view3d_draw_transp() call */
1194         const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
1195         const bool drawcone = ((dt > OB_WIRE) &&
1196                                !(G.f & G_PICKSEL) &&
1197                                (la->type == LA_SPOT) &&
1198                                (la->mode & LA_SHOW_CONE) &&
1199                                !(base->flag & OB_FROMDUPLI) &&
1200                                !is_view);
1201
1202 #ifdef WITH_GAMEENGINE
1203         const bool drawshadowbox = (
1204                 (rv3d->rflag & RV3D_IS_GAME_ENGINE) &&
1205                 (dt > OB_WIRE) &&
1206                 !(G.f & G_PICKSEL) &&
1207                 (la->type == LA_SUN) &&
1208                 ((la->mode & LA_SHAD_BUF) || 
1209                 (la->mode & LA_SHAD_RAY)) &&
1210                 (la->mode & LA_SHOW_SHADOW_BOX) &&
1211                 !(base->flag & OB_FROMDUPLI) &&
1212                 !is_view);
1213 #else
1214         const bool drawshadowbox = false;
1215 #endif
1216
1217         if ((drawcone || drawshadowbox) && !v3d->transp) {
1218                 /* in this case we need to draw delayed */
1219                 ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag);
1220                 return;
1221         }
1222         
1223         /* we first draw only the screen aligned & fixed scale stuff */
1224         glPushMatrix();
1225         glLoadMatrixf(rv3d->viewmat);
1226
1227         /* lets calculate the scale: */
1228         lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
1229
1230         /* and view aligned matrix: */
1231         copy_m4_m4(imat, rv3d->viewinv);
1232         normalize_v3(imat[0]);
1233         normalize_v3(imat[1]);
1234
1235         /* lamp center */
1236         copy_v3_v3(vec, ob->obmat[3]);
1237
1238         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1239                 /* for AA effects */
1240                 curcol[0] = ob_wire_col[0];
1241                 curcol[1] = ob_wire_col[1];
1242                 curcol[2] = ob_wire_col[2];
1243                 curcol[3] = 154;
1244                 glColor4ubv(curcol);
1245         }
1246
1247         glLineWidth(1);
1248
1249         if (lampsize > 0.0f) {
1250
1251                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1252                         if (ob->id.us > 1) {
1253                                 if (is_obact || (ob->flag & SELECT)) {
1254                                         glColor4ub(0x88, 0xFF, 0xFF, 155);
1255                                 }
1256                                 else {
1257                                         glColor4ub(0x77, 0xCC, 0xCC, 155);
1258                                 }
1259                         }
1260                 }
1261                 
1262                 /* Inner Circle */
1263                 glEnable(GL_BLEND);
1264                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1265                 glDisable(GL_BLEND);
1266                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1267                 
1268                 /* restore */
1269                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1270                         if (ob->id.us > 1)
1271                                 glColor4ubv(curcol);
1272                 }
1273
1274                 /* Outer circle */
1275                 circrad = 3.0f * lampsize;
1276                 setlinestyle(3);
1277
1278                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1279
1280                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1281                 if (la->type != LA_HEMI) {
1282                         if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
1283                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
1284                         }
1285                 }
1286         }
1287         else {
1288                 setlinestyle(3);
1289                 circrad = 0.0f;
1290         }
1291         
1292         /* draw the pretty sun rays */
1293         if (la->type == LA_SUN) {
1294                 float v1[3], v2[3], mat[3][3];
1295                 short axis;
1296                 
1297                 /* setup a 45 degree rotation matrix */
1298                 axis_angle_normalized_to_mat3_ex(mat, imat[2], M_SQRT1_2, M_SQRT1_2);
1299
1300                 /* vectors */
1301                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1302                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1303                 
1304                 /* center */
1305                 glTranslate3fv(vec);
1306                 
1307                 setlinestyle(3);
1308                 
1309                 glBegin(GL_LINES);
1310                 for (axis = 0; axis < 8; axis++) {
1311                         glVertex3fv(v1);
1312                         glVertex3fv(v2);
1313                         mul_m3_v3(mat, v1);
1314                         mul_m3_v3(mat, v2);
1315                 }
1316                 glEnd();
1317                 
1318                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1319
1320         }
1321         
1322         if (la->type == LA_LOCAL) {
1323                 if (la->mode & LA_SPHERE) {
1324                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1325                 }
1326         }
1327         
1328         glPopMatrix();  /* back in object space */
1329         zero_v3(vec);
1330         
1331         if (is_view) {
1332                 /* skip drawing extra info */
1333         }
1334         else if (la->type == LA_SPOT) {
1335                 float x, y, z, z_abs;
1336                 copy_v3_fl3(lvec, 0.0f, 0.0f, 1.0f);
1337                 copy_v3_fl3(vvec, rv3d->persmat[0][2], rv3d->persmat[1][2], rv3d->persmat[2][2]);
1338                 mul_transposed_mat3_m4_v3(ob->obmat, vvec);
1339
1340                 x = -la->dist;
1341                 y = cosf(la->spotsize * 0.5f);
1342                 z = x * sqrtf(1.0f - y * y);
1343
1344                 spotvolume(lvec, vvec, y);
1345                 mul_v3_fl(lvec, x);
1346                 mul_v3_fl(vvec, x);
1347
1348                 x *= y;
1349
1350                 z_abs = fabsf(z);
1351
1352                 if (la->mode & LA_SQUARE) {
1353                         /* draw pyramid */
1354                         const float vertices[5][3] = {
1355                             /* 5 of vertex coords of pyramid */
1356                             {0.0f, 0.0f, 0.0f},
1357                             {z_abs, z_abs, x},
1358                             {-z_abs, -z_abs, x},
1359                             {z_abs, -z_abs, x},
1360                             {-z_abs, z_abs, x},
1361                         };
1362                         const unsigned char indices[] = {
1363                             0, 1, 3,
1364                             0, 3, 2,
1365                             0, 2, 4,
1366                             0, 1, 4,
1367                         };
1368
1369                         /* Draw call:
1370                          * activate and specify pointer to vertex array */
1371                         glEnableClientState(GL_VERTEX_ARRAY);
1372                         glVertexPointer(3, GL_FLOAT, 0, vertices);
1373                         /* draw the pyramid */
1374                         glDrawElements(GL_LINE_STRIP, 12, GL_UNSIGNED_BYTE, indices);
1375
1376                         /* deactivate vertex arrays after drawing */
1377                         glDisableClientState(GL_VERTEX_ARRAY);
1378
1379                         glTranslatef(0.0f, 0.0f, x);
1380
1381                         /* draw the square representing spotbl */
1382                         if (la->type == LA_SPOT) {
1383                                 float blend = z_abs * (1.0f - pow2f(la->spotblend));
1384
1385                                 /* hide line if it is zero size or overlaps with outer border,
1386                                  * previously it adjusted to always to show it but that seems
1387                                  * confusing because it doesn't show the actual blend size */
1388                                 if (blend != 0.0f && blend != z_abs) {
1389                                         fdrawbox(blend, -blend, -blend, blend);
1390                                 }
1391                         }
1392                 }
1393                 else {
1394
1395                         /* draw the angled sides of the cone */
1396                         glBegin(GL_LINE_STRIP);
1397                         glVertex3fv(vvec);
1398                         glVertex3fv(vec);
1399                         glVertex3fv(lvec);
1400                         glEnd();
1401
1402                         /* draw the circle at the end of the cone */
1403                         glTranslatef(0.0f, 0.0f, x);
1404                         circ(0.0f, 0.0f, z_abs);
1405
1406                         /* draw the circle representing spotbl */
1407                         if (la->type == LA_SPOT) {
1408                                 float blend = z_abs * (1.0f - pow2f(la->spotblend));
1409
1410                                 /* hide line if it is zero size or overlaps with outer border,
1411                                  * previously it adjusted to always to show it but that seems
1412                                  * confusing because it doesn't show the actual blend size */
1413                                 if (blend != 0.0f && blend != z_abs) {
1414                                         circ(0.0f, 0.0f, blend);
1415                                 }
1416                         }
1417                 }
1418
1419                 if (drawcone)
1420                         draw_transp_spot_volume(la, x, z);
1421
1422                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1423                 glTranslatef(0.0, 0.0, -x);  /* reverse translation above */
1424                 glBegin(GL_LINES);
1425                 if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) {
1426                         float lvec_clip[3];
1427                         float vvec_clip[3];
1428                         float clipsta_fac = la->clipsta / -x;
1429
1430                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1431                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1432
1433                         glVertex3fv(lvec_clip);
1434                         glVertex3fv(vvec_clip);
1435                 }
1436                 /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */
1437                 else {
1438                         glVertex3f(0.0, 0.0, -circrad);
1439                         glVertex3f(0.0, 0.0, -la->dist);
1440                 }
1441                 glEnd();
1442         }
1443         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1444                 
1445                 /* draw the line from the circle along the dist */
1446                 glBegin(GL_LINES);
1447                 vec[2] = -circrad;
1448                 glVertex3fv(vec);
1449                 vec[2] = -la->dist;
1450                 glVertex3fv(vec);
1451                 glEnd();
1452                 
1453                 if (la->type == LA_HEMI) {
1454                         /* draw the hemisphere curves */
1455                         short axis, steps, dir;
1456                         float outdist, zdist, mul;
1457                         zero_v3(vec);
1458                         outdist = 0.14; mul = 1.4; dir = 1;
1459                         
1460                         setlinestyle(4);
1461                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1462                         for (axis = 0; axis < 4; axis++) {
1463                                 float v[3] = {0.0, 0.0, 0.0};
1464                                 zdist = 0.02;
1465                                 
1466                                 glBegin(GL_LINE_STRIP);
1467                                 
1468                                 for (steps = 0; steps < 6; steps++) {
1469                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1470                                                 /* make the arcs start at the edge of the energy circle */
1471                                                 if (steps == 0) v[0] = dir * circrad;
1472                                                 else v[0] = v[0] + dir * (steps * outdist);
1473                                         }
1474                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1475                                                 /* make the arcs start at the edge of the energy circle */
1476                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1477                                         }
1478
1479                                         v[2] = v[2] - steps * zdist;
1480                                         
1481                                         glVertex3fv(v);
1482                                         
1483                                         zdist = zdist * mul;
1484                                 }
1485                                 
1486                                 glEnd();
1487                                 /* flip the direction */
1488                                 dir = -dir;
1489                         }
1490                 }
1491
1492 #ifdef WITH_GAMEENGINE
1493                 if (drawshadowbox) {
1494                         draw_transp_sun_volume(la);
1495                 }
1496 #endif
1497
1498         }
1499         else if (la->type == LA_AREA) {
1500                 setlinestyle(3);
1501                 if (la->area_shape == LA_AREA_SQUARE)
1502                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1503                 else if (la->area_shape == LA_AREA_RECT)
1504                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1505
1506                 glBegin(GL_LINES);
1507                 glVertex3f(0.0, 0.0, -circrad);
1508                 glVertex3f(0.0, 0.0, -la->dist);
1509                 glEnd();
1510         }
1511         
1512         /* and back to viewspace */
1513         glPushMatrix();
1514         glLoadMatrixf(rv3d->viewmat);
1515         copy_v3_v3(vec, ob->obmat[3]);
1516
1517         setlinestyle(0);
1518         
1519         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) {
1520                 drawshadbuflimits(la, ob->obmat);
1521         }
1522         
1523         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1524                 UI_GetThemeColor4ubv(TH_LAMP, col);
1525                 glColor4ubv(col);
1526         }
1527
1528         glEnable(GL_BLEND);
1529         
1530         if (vec[2] > 0) vec[2] -= circrad;
1531         else vec[2] += circrad;
1532         
1533         glBegin(GL_LINES);
1534         glVertex3fv(vec);
1535         vec[2] = 0;
1536         glVertex3fv(vec);
1537         glEnd();
1538         
1539         glPointSize(2.0);
1540         glBegin(GL_POINTS);
1541         glVertex3fv(vec);
1542         glEnd();
1543         
1544         glDisable(GL_BLEND);
1545         
1546         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1547                 /* restore for drawing extra stuff */
1548                 glColor3ubv(ob_wire_col);
1549         }
1550         /* and finally back to org object space! */
1551         glPopMatrix();
1552 }
1553
1554 static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3])
1555 {
1556         glBegin(GL_LINES);
1557         glVertex3f(0.0, 0.0, -sta);
1558         glVertex3f(0.0, 0.0, -end);
1559         glEnd();
1560
1561         if (!(dflag & DRAW_PICKING)) {
1562                 glPointSize(3.0);
1563                 glBegin(GL_POINTS);
1564                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1565                         glColor3ubv(col);
1566                 }
1567                 glVertex3f(0.0, 0.0, -sta);
1568                 glVertex3f(0.0, 0.0, -end);
1569                 glEnd();
1570         }
1571 }
1572
1573
1574 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1575 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1576 static void draw_focus_cross(float dist, float size)
1577 {
1578         glBegin(GL_LINES);
1579         glVertex3f(-size, 0.0f, -dist);
1580         glVertex3f(size, 0.0f, -dist);
1581         glVertex3f(0.0f, -size, -dist);
1582         glVertex3f(0.0f, size, -dist);
1583         glEnd();
1584 }
1585
1586 #ifdef VIEW3D_CAMERA_BORDER_HACK
1587 unsigned char view3d_camera_border_hack_col[3];
1588 bool view3d_camera_border_hack_test = false;
1589 #endif
1590
1591 /* ****************** draw clip data *************** */
1592
1593 static void draw_bundle_sphere(void)
1594 {
1595         static GLuint displist = 0;
1596
1597         if (displist == 0) {
1598                 GLUquadricObj *qobj;
1599
1600                 displist = glGenLists(1);
1601                 glNewList(displist, GL_COMPILE);
1602                 qobj = gluNewQuadric();
1603                 gluQuadricDrawStyle(qobj, GLU_FILL);
1604                 gluSphere(qobj, 0.05, 8, 8);
1605                 gluDeleteQuadric(qobj);
1606
1607                 glEndList();
1608         }
1609
1610         glCallList(displist);
1611 }
1612
1613 static void draw_viewport_object_reconstruction(
1614         Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d,
1615         MovieClip *clip, MovieTrackingObject *tracking_object,
1616         const short dflag, const unsigned char ob_wire_col[4],
1617         int *global_track_index, bool draw_selected)
1618 {
1619         MovieTracking *tracking = &clip->tracking;
1620         MovieTrackingTrack *track;
1621         float mat[4][4], imat[4][4];
1622         unsigned char col_unsel[4], col_sel[4];
1623         int tracknr = *global_track_index;
1624         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
1625         float camera_size[3];
1626
1627         UI_GetThemeColor4ubv(TH_TEXT, col_unsel);
1628         UI_GetThemeColor4ubv(TH_SELECT, col_sel);
1629
1630         BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
1631
1632         /* we're compensating camera size for bundles size,
1633          * to make it so bundles are always displayed with the same size */
1634         copy_v3_v3(camera_size, base->object->size);
1635         if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
1636                 mul_v3_fl(camera_size, tracking_object->scale);
1637
1638         glPushMatrix();
1639
1640         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1641                 /* current ogl matrix is translated in camera space, bundles should
1642                  * be rendered in world space, so camera matrix should be "removed"
1643                  * from current ogl matrix */
1644                 invert_m4_m4(imat, base->object->obmat);
1645
1646                 glMultMatrixf(imat);
1647                 glMultMatrixf(mat);
1648         }
1649         else {
1650                 float obmat[4][4];
1651                 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
1652
1653                 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat);
1654
1655                 invert_m4_m4(imat, obmat);
1656                 glMultMatrixf(imat);
1657         }
1658
1659         for (track = tracksbase->first; track; track = track->next) {
1660                 bool selected = TRACK_SELECTED(track);
1661
1662                 if (draw_selected && !selected)
1663                         continue;
1664
1665                 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1666                         continue;
1667
1668                 if (dflag & DRAW_PICKING)
1669                         GPU_select_load_id(base->selcol + (tracknr << 16));
1670
1671                 glPushMatrix();
1672                 glTranslate3fv(track->bundle_pos);
1673                 glScalef(v3d->bundle_size / 0.05f / camera_size[0],
1674                          v3d->bundle_size / 0.05f / camera_size[1],
1675                          v3d->bundle_size / 0.05f / camera_size[2]);
1676
1677                 const int v3d_drawtype = view3d_effective_drawtype(v3d);
1678                 if (v3d_drawtype == OB_WIRE) {
1679                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1680                                 if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
1681                                         glColor3ubv(ob_wire_col);
1682                                 }
1683                                 else {
1684                                         glColor3fv(track->color);
1685                                 }
1686                         }
1687
1688                         drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
1689                 }
1690                 else if (v3d_drawtype > OB_WIRE) {
1691                         if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1692                                 /* selection outline */
1693                                 if (selected) {
1694                                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1695                                                 glColor3ubv(ob_wire_col);
1696                                         }
1697
1698                                         glLineWidth(2.0f);
1699                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1700
1701                                         draw_bundle_sphere();
1702
1703                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1704                                 }
1705
1706                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1707                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1708                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1709                                 }
1710
1711                                 draw_bundle_sphere();
1712                         }
1713                         else {
1714                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1715                                         if (selected) {
1716                                                 glColor3ubv(ob_wire_col);
1717                                         }
1718                                         else {
1719                                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1720                                                 else UI_ThemeColor(TH_WIRE);
1721                                         }
1722                                 }
1723
1724                                 drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
1725                         }
1726                 }
1727
1728                 glPopMatrix();
1729
1730                 if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1731                         float pos[3];
1732
1733                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1734                         view3d_cached_text_draw_add(pos,
1735                                                     track->name, strlen(track->name),
1736                                                     10, V3D_CACHE_TEXT_GLOBALSPACE,
1737                                                     selected ? col_sel : col_unsel);
1738                 }
1739
1740                 tracknr++;
1741         }
1742
1743         if ((dflag & DRAW_PICKING) == 0) {
1744                 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1745                         MovieTrackingReconstruction *reconstruction;
1746                         reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
1747
1748                         if (reconstruction->camnr) {
1749                                 MovieReconstructedCamera *camera = reconstruction->cameras;
1750
1751                                 UI_ThemeColor(TH_CAMERA_PATH);
1752                                 glLineWidth(2.0f);
1753
1754                                 glBegin(GL_LINE_STRIP);
1755                                 for (int a = 0; a < reconstruction->camnr; a++, camera++) {
1756                                         glVertex3fv(camera->mat[3]);
1757                                 }
1758                                 glEnd();
1759                         }
1760                 }
1761         }
1762
1763         glPopMatrix();
1764
1765         *global_track_index = tracknr;
1766 }
1767
1768 static void draw_viewport_reconstruction(
1769         Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip,
1770         const short dflag, const unsigned char ob_wire_col[4],
1771         const bool draw_selected)
1772 {
1773         MovieTracking *tracking = &clip->tracking;
1774         MovieTrackingObject *tracking_object;
1775         int global_track_index = 1;
1776
1777         if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1778                 return;
1779
1780         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1781                 return;
1782
1783         GPU_basic_shader_colors(NULL, NULL, 0, 1.0f);
1784         GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
1785
1786         tracking_object = tracking->objects.first;
1787         while (tracking_object) {
1788                 draw_viewport_object_reconstruction(
1789                         scene, base, v3d, rv3d, clip, tracking_object,
1790                         dflag, ob_wire_col, &global_track_index, draw_selected);
1791
1792                 tracking_object = tracking_object->next;
1793         }
1794
1795         /* restore */
1796         GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1797
1798         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1799                 glColor3ubv(ob_wire_col);
1800         }
1801
1802         if (dflag & DRAW_PICKING)
1803                 GPU_select_load_id(base->selcol);
1804 }
1805
1806 static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode)
1807 {
1808         glBegin(mode);
1809         glVertex3fv(near_plane[0]);
1810         glVertex3fv(far_plane[0]);
1811         glVertex3fv(far_plane[1]);
1812         glVertex3fv(near_plane[1]);
1813         glEnd();
1814
1815         glBegin(mode);
1816         glVertex3fv(near_plane[1]);
1817         glVertex3fv(far_plane[1]);
1818         glVertex3fv(far_plane[2]);
1819         glVertex3fv(near_plane[2]);
1820         glEnd();
1821
1822         glBegin(mode);
1823         glVertex3fv(near_plane[2]);
1824         glVertex3fv(far_plane[2]);
1825         glVertex3fv(far_plane[3]);
1826         glVertex3fv(near_plane[3]);
1827         glEnd();
1828
1829         glBegin(mode);
1830         glVertex3fv(far_plane[3]);
1831         glVertex3fv(near_plane[3]);
1832         glVertex3fv(near_plane[0]);
1833         glVertex3fv(far_plane[0]);
1834         glEnd();
1835 }
1836
1837 /* camera frame */
1838 static void drawcamera_frame(float vec[4][3], const GLenum mode)
1839 {
1840         glBegin(mode);
1841         glVertex3fv(vec[0]);
1842         glVertex3fv(vec[1]);
1843         glVertex3fv(vec[2]);
1844         glVertex3fv(vec[3]);
1845         glEnd();
1846 }
1847
1848 /* center point to camera frame */
1849 static void drawcamera_framelines(float vec[4][3], float origin[3])
1850 {
1851         glBegin(GL_LINE_STRIP);
1852         glVertex3fv(vec[1]);
1853         glVertex3fv(origin);
1854         glVertex3fv(vec[0]);
1855         glVertex3fv(vec[3]);
1856         glVertex3fv(origin);
1857         glVertex3fv(vec[2]);
1858         glEnd();
1859 }
1860
1861 static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
1862 {
1863         return (ob == v3d->camera) &&
1864                 (scene->r.scemode & R_MULTIVIEW) != 0 &&
1865                 (v3d->stereo3d_flag);
1866 }
1867
1868 static void drawcamera_stereo3d(
1869         Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam,
1870         float vec[4][3], float drawsize, const float scale[3])
1871 {
1872         float obmat[4][4];
1873         float vec_lr[2][4][3];
1874         const float fac = (cam->stereo.pivot == CAM_S3D_PIVOT_CENTER) ? 2.0f : 1.0f;
1875         float origin[2][3] = {{0}};
1876         float tvec[3];
1877         const Camera *cam_lr[2];
1878         const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
1879
1880         const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
1881         const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) && (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
1882         const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME);
1883
1884         zero_v3(tvec);
1885
1886         glPushMatrix();
1887
1888         for (int i = 0; i < 2; i++) {
1889                 ob = BKE_camera_multiview_render(scene, ob, names[i]);
1890                 cam_lr[i] = ob->data;
1891
1892                 glLoadMatrixf(rv3d->viewmat);
1893                 BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat);
1894                 glMultMatrixf(obmat);
1895
1896                 copy_m3_m3(vec_lr[i], vec);
1897                 copy_v3_v3(vec_lr[i][3], vec[3]);
1898
1899                 if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) {
1900                         const float shift_x =
1901                                 ((BKE_camera_multiview_shift_x(&scene->r, ob, names[i]) - cam->shiftx) *
1902                                  (drawsize * scale[0] * fac));
1903
1904                         for (int j = 0; j < 4; j++) {
1905                                 vec_lr[i][j][0] += shift_x;
1906                         }
1907                 }
1908
1909                 if (is_stereo3d_cameras) {
1910                         /* camera frame */
1911                         drawcamera_frame(vec_lr[i], GL_LINE_LOOP);
1912
1913                         /* center point to camera frame */
1914                         drawcamera_framelines(vec_lr[i], tvec);
1915                 }
1916
1917                 /* connecting line */
1918                 mul_m4_v3(obmat, origin[i]);
1919
1920                 /* convergence plane */
1921                 if (is_stereo3d_plane || is_stereo3d_volume) {
1922                         for (int j = 0; j < 4; j++) {
1923                                 mul_m4_v3(obmat, vec_lr[i][j]);
1924                         }
1925                 }
1926         }
1927
1928
1929         /* the remaining drawing takes place in the view space */
1930         glLoadMatrixf(rv3d->viewmat);
1931
1932         if (is_stereo3d_cameras) {
1933                 /* draw connecting lines */
1934                 GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
1935                 GPU_basic_shader_line_stipple(2, 0xAAAA);
1936
1937                 glBegin(GL_LINES);
1938                 glVertex3fv(origin[0]);
1939                 glVertex3fv(origin[1]);
1940                 glEnd();
1941
1942                 GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
1943         }
1944
1945         /* draw convergence plane */
1946         if (is_stereo3d_plane) {
1947                 float axis_center[3], screen_center[3];
1948                 float world_plane[4][3];
1949                 float local_plane[4][3];
1950                 float offset;
1951
1952                 mid_v3_v3v3(axis_center, origin[0], origin[1]);
1953
1954                 for (int i = 0; i < 4; i++) {
1955                         mid_v3_v3v3(world_plane[i], vec_lr[0][i], vec_lr[1][i]);
1956                         sub_v3_v3v3(local_plane[i], world_plane[i], axis_center);
1957                 }
1958
1959                 mid_v3_v3v3(screen_center, world_plane[0], world_plane[2]);
1960                 offset = cam->stereo.convergence_distance / len_v3v3(screen_center, axis_center);
1961
1962                 for (int i = 0; i < 4; i++) {
1963                         mul_v3_fl(local_plane[i], offset);
1964                         add_v3_v3(local_plane[i], axis_center);
1965                 }
1966
1967                 glColor3f(0.0f, 0.0f, 0.0f);
1968
1969                 /* camera frame */
1970                 drawcamera_frame(local_plane, GL_LINE_LOOP);
1971
1972                 if (v3d->stereo3d_convergence_alpha > 0.0f) {
1973                         glEnable(GL_BLEND);
1974                         glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
1975
1976                         glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
1977
1978                         drawcamera_frame(local_plane, GL_QUADS);
1979
1980                         glDisable(GL_BLEND);
1981                         glDepthMask(1);  /* restore write in zbuffer */
1982                 }
1983         }
1984
1985         /* draw convergence plane */
1986         if (is_stereo3d_volume) {
1987                 float screen_center[3];
1988                 float near_plane[4][3], far_plane[4][3];
1989
1990                 for (int i = 0; i < 2; i++) {
1991                         mid_v3_v3v3(screen_center, vec_lr[i][0], vec_lr[i][2]);
1992
1993                         float offset = len_v3v3(screen_center, origin[i]);
1994
1995                         for (int j = 0; j < 4; j++) {
1996                                 sub_v3_v3v3(near_plane[j], vec_lr[i][j], origin[i]);
1997                                 mul_v3_fl(near_plane[j], cam_lr[i]->clipsta / offset);
1998                                 add_v3_v3(near_plane[j], origin[i]);
1999
2000                                 sub_v3_v3v3(far_plane[j], vec_lr[i][j], origin[i]);
2001                                 mul_v3_fl(far_plane[j], cam_lr[i]->clipend / offset);
2002                                 add_v3_v3(far_plane[j], origin[i]);
2003                         }
2004
2005                         /* camera frame */
2006                         glColor3f(0.0f, 0.0f, 0.0f);
2007
2008                         drawcamera_frame(near_plane, GL_LINE_LOOP);
2009                         drawcamera_frame(far_plane, GL_LINE_LOOP);
2010                         drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP);
2011
2012                         if (v3d->stereo3d_volume_alpha > 0.0f) {
2013                                 glEnable(GL_BLEND);
2014                                 glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
2015
2016                                 if (i == 0)
2017                                         glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
2018                                 else
2019                                         glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha);
2020
2021                                 drawcamera_frame(near_plane, GL_QUADS);
2022                                 drawcamera_frame(far_plane, GL_QUADS);
2023                                 drawcamera_volume(near_plane, far_plane, GL_QUADS);
2024
2025                                 glDisable(GL_BLEND);
2026                                 glDepthMask(1);  /* restore write in zbuffer */
2027                         }
2028                 }
2029         }
2030
2031         glPopMatrix();
2032 }
2033
2034 /* flag similar to draw_object() */
2035 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
2036                        const short dflag, const unsigned char ob_wire_col[4])
2037 {
2038         /* a standing up pyramid with (0,0,0) as top */
2039         Camera *cam;
2040         Object *ob = base->object;
2041         float tvec[3];
2042         float vec[4][3], asp[2], shift[2], scale[3];
2043         MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false);
2044
2045         const bool is_active = (ob == v3d->camera);
2046         const bool is_view = (rv3d->persp == RV3D_CAMOB && is_active);
2047         const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
2048         const bool is_stereo3d = drawcamera_is_stereo3d(scene, v3d, ob);
2049         const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
2050         const bool is_stereo3d_cameras = (ob == scene->camera) &&
2051                                          is_multiview &&
2052                                          is_stereo3d_view &&
2053                                          (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS);
2054         const bool is_selection_camera_stereo = (G.f & G_PICKSEL) &&
2055                                                 is_view && is_multiview &&
2056                                                 is_stereo3d_view;
2057
2058         /* draw data for movie clip set as active for scene */
2059         if (clip) {
2060                 draw_viewport_reconstruction(scene, base, v3d, rv3d, clip, dflag, ob_wire_col, false);
2061                 draw_viewport_reconstruction(scene, base, v3d, rv3d, clip, dflag, ob_wire_col, true);
2062         }
2063
2064 #ifdef VIEW3D_CAMERA_BORDER_HACK
2065         if (is_view && !(G.f & G_PICKSEL)) {
2066                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
2067                         view3d_camera_border_hack_col[0] = ob_wire_col[0];
2068                         view3d_camera_border_hack_col[1] = ob_wire_col[1];
2069                         view3d_camera_border_hack_col[2] = ob_wire_col[2];
2070                 }
2071                 else {
2072                         float col[4];
2073                         glGetFloatv(GL_CURRENT_COLOR, col);
2074                         rgb_float_to_uchar(view3d_camera_border_hack_col, col);
2075                 }
2076                 view3d_camera_border_hack_test = true;
2077                 return;
2078         }
2079 #endif
2080
2081         cam = ob->data;
2082
2083         /* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here */
2084         if (is_selection_camera_stereo) {
2085                 scale[0] = 1.0f;
2086                 scale[1] = 1.0f;
2087                 scale[2] = 1.0f;
2088         }
2089         else {
2090                 scale[0] = 1.0f / len_v3(ob->obmat[0]);
2091                 scale[1] = 1.0f / len_v3(ob->obmat[1]);
2092                 scale[2] = 1.0f / len_v3(ob->obmat[2]);
2093         }
2094
2095         float drawsize;
2096         BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
2097                                  asp, shift, &drawsize, vec);
2098
2099         glDisable(GL_CULL_FACE);
2100         glLineWidth(1);
2101
2102         /* camera frame */
2103         if (!is_stereo3d_cameras) {
2104                 /* make sure selection uses the same matrix for camera as the one used while viewing */
2105                 if (is_selection_camera_stereo) {
2106                         float obmat[4][4];
2107                         bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
2108
2109                         glPushMatrix();
2110                         glLoadMatrixf(rv3d->viewmat);
2111                         BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat);
2112                         glMultMatrixf(obmat);
2113
2114                         drawcamera_frame(vec, GL_LINE_LOOP);
2115                         glPopMatrix();
2116                 }
2117                 else {
2118                         drawcamera_frame(vec, GL_LINE_LOOP);
2119                 }
2120         }
2121
2122         if (is_view)
2123                 return;
2124
2125         zero_v3(tvec);
2126
2127         /* center point to camera frame */
2128         if (!is_stereo3d_cameras)
2129                 drawcamera_framelines(vec, tvec);
2130
2131         /* arrow on top */
2132         tvec[2] = vec[1][2]; /* copy the depth */
2133
2134         /* draw an outline arrow for inactive cameras and filled
2135          * for active cameras. We actually draw both outline+filled
2136          * for active cameras so the wire can be seen side-on */
2137         for (int i = 0; i < 2; i++) {
2138                 if (i == 0) glBegin(GL_LINE_LOOP);
2139                 else if (i == 1 && is_active) glBegin(GL_TRIANGLES);
2140                 else break;
2141
2142                 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
2143                 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
2144                 glVertex3fv(tvec); /* left */
2145                 
2146                 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
2147                 glVertex3fv(tvec); /* right */
2148                 
2149                 tvec[0] = shift[0];
2150                 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
2151                 glVertex3fv(tvec); /* top */
2152
2153                 glEnd();
2154         }
2155
2156         if ((dflag & DRAW_SCENESET) == 0) {
2157                 if (cam->flag & (CAM_SHOWLIMITS | CAM_SHOWMIST)) {
2158                         float nobmat[4][4];
2159
2160                         /* draw in normalized object matrix space */
2161                         copy_m4_m4(nobmat, ob->obmat);
2162                         normalize_m4(nobmat);
2163
2164                         glPushMatrix();
2165                         glLoadMatrixf(rv3d->viewmat);
2166                         glMultMatrixf(nobmat);
2167
2168                         if (cam->flag & CAM_SHOWLIMITS) {
2169                                 const unsigned char col[3] = {128, 128, 60}, col_hi[3] = {255, 255, 120};
2170
2171                                 draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col));
2172                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
2173                                 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
2174                         }
2175
2176                         if (cam->flag & CAM_SHOWMIST) {
2177                                 World *world = scene->world;
2178                                 const unsigned char col[3] = {128, 128, 128}, col_hi[3] = {255, 255, 255};
2179
2180                                 if (world) {
2181                                         draw_limit_line(world->miststa, world->miststa + world->mistdist,
2182                                                         dflag, (is_active ? col_hi : col));
2183                                 }
2184                         }
2185                         glPopMatrix();
2186                 }
2187         }
2188
2189         /* stereo cameras drawing */
2190         if (is_stereo3d) {
2191                 drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale);
2192         }
2193 }
2194
2195 /* flag similar to draw_object() */
2196 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
2197                         Object *UNUSED(ob), int UNUSED(flag))
2198 {
2199         float vec[3];
2200
2201         glEnable(GL_BLEND);
2202         glLineWidth(1);
2203
2204         for (int j = 0; j < 3; j++) {
2205                 vec[2] = 0.25f * j - 0.125f;
2206
2207                 glBegin(GL_LINE_LOOP);
2208                 for (int i = 0; i < 16; i++) {
2209                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
2210                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
2211                         glVertex3fv(vec);
2212                 }
2213                 glEnd();
2214         }
2215
2216         for (int j = 0; j < 4; j++) {
2217                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
2218                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
2219                 glBegin(GL_LINE_STRIP);
2220                 for (int i = 0; i < 3; i++) {
2221                         if (i == 1) {
2222                                 vec[0] *= 0.5f;
2223                                 vec[1] *= 0.5f;
2224                         }
2225
2226                         vec[2] = 0.25f * i - 0.125f;
2227                         glVertex3fv(vec);
2228                 }
2229                 glEnd();
2230         }
2231
2232         glDisable(GL_BLEND);
2233 }
2234
2235 static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
2236 {
2237         BPoint *bp = lt->def;
2238         const float *co = dl ? dl->verts : NULL;
2239
2240         const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
2241         UI_ThemeColor(color);
2242
2243         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
2244         glBegin(GL_POINTS);
2245
2246         for (int w = 0; w < lt->pntsw; w++) {
2247                 int wxt = (w == 0 || w == lt->pntsw - 1);
2248                 for (int v = 0; v < lt->pntsv; v++) {
2249                         int vxt = (v == 0 || v == lt->pntsv - 1);
2250                         for (int u = 0; u < lt->pntsu; u++, bp++, co += 3) {
2251                                 int uxt = (u == 0 || u == lt->pntsu - 1);
2252                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
2253                                         if (bp->hide == 0) {
2254                                                 /* check for active BPoint and ensure selected */
2255                                                 if ((bp == actbp) && (bp->f1 & SELECT)) {
2256                                                         UI_ThemeColor(TH_ACTIVE_VERT);
2257                                                         glVertex3fv(dl ? co : bp->vec);
2258                                                         UI_ThemeColor(color);
2259                                                 }
2260                                                 else if ((bp->f1 & SELECT) == sel) {
2261                                                         glVertex3fv(dl ? co : bp->vec);
2262                                                 }
2263                                         }
2264                                 }
2265                         }
2266                 }
2267         }
2268         
2269         glEnd();
2270 }
2271
2272 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
2273 {
2274         int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
2275
2276         if (actdef_wcol) {
2277                 float col[3];
2278                 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1);
2279                 
2280                 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
2281                 glColor3fv(col);
2282
2283         }
2284         
2285         if (dl) {
2286                 glVertex3fv(&dl->verts[index * 3]);
2287         }
2288         else {
2289                 glVertex3fv(lt->def[index].vec);
2290         }
2291 }
2292
2293 #ifdef SEQUENCER_DAG_WORKAROUND
2294 static void ensure_curve_cache(Scene *scene, Object *object)
2295 {
2296         bool need_recalc = object->curve_cache == NULL;
2297         /* Render thread might have freed the curve cache if the
2298          * object is not visible. If the object is also used for
2299          * particles duplication, then render thread might have
2300          * also created curve_cache with only bevel and path
2301          * filled in.
2302          *
2303          * So check for curve_cache != NULL is not fully correct
2304          * here, we also need to check whether display list is
2305          * empty or not.
2306          *
2307          * The trick below tries to optimize calls to displist
2308          * creation for cases curve is empty. Meaning, if the curve
2309          * is empty (without splines) bevel list would also be empty.
2310          * And the thing is, render thread always leaves bevel list
2311          * in a proper state. So if bevel list is here and display
2312          * list is not we need to make display list.
2313          */
2314         if (need_recalc == false) {
2315                 need_recalc = object->curve_cache->disp.first == NULL &&
2316                               object->curve_cache->bev.first != NULL;
2317         }
2318         if (need_recalc) {
2319                 switch (object->type) {
2320                         case OB_CURVE:
2321                         case OB_SURF:
2322                         case OB_FONT:
2323                                 BKE_displist_make_curveTypes(scene, object, false);
2324                                 break;
2325                         case OB_MBALL:
2326                                 BKE_displist_make_mball(G.main->eval_ctx, scene, object);
2327                                 break;
2328                         case OB_LATTICE:
2329                                 BKE_lattice_modifiers_calc(scene, object);
2330                                 break;
2331                 }
2332         }
2333 }
2334 #endif
2335
2336 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
2337 static void drawlattice(View3D *v3d, Object *ob)
2338 {
2339         Lattice *lt = ob->data;
2340         DispList *dl;
2341         int u, v, w;
2342         int actdef_wcol = 0;
2343         const bool is_edit = (lt->editlatt != NULL);
2344
2345         dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
2346         
2347         if (is_edit) {
2348                 lt = lt->editlatt->latt;
2349
2350                 UI_ThemeColor(TH_WIRE_EDIT);
2351                 
2352                 if (ob->defbase.first && lt->dvert) {
2353                         actdef_wcol = ob->actdef;
2354                 }
2355         }
2356
2357         glLineWidth(1);
2358         glBegin(GL_LINES);
2359         for (w = 0; w < lt->pntsw; w++) {
2360                 int wxt = (w == 0 || w == lt->pntsw - 1);
2361                 for (v = 0; v < lt->pntsv; v++) {
2362                         int vxt = (v == 0 || v == lt->pntsv - 1);
2363                         for (u = 0; u < lt->pntsu; u++) {
2364                                 int uxt = (u == 0 || u == lt->pntsu - 1);
2365
2366                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
2367                                         drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol);
2368                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
2369                                 }
2370                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2371                                         drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol);
2372                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
2373                                 }
2374                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
2375                                         drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol);
2376                                         drawlattice__point(lt, dl, u, v, w, actdef_wcol);
2377                                 }
2378                         }
2379                 }
2380         }
2381         glEnd();
2382
2383         if (is_edit) {
2384                 BPoint *actbp = BKE_lattice_active_point_get(lt);
2385
2386                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2387                 
2388                 lattice_draw_verts(lt, dl, actbp, 0);
2389                 lattice_draw_verts(lt, dl, actbp, 1);
2390                 
2391                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2392         }
2393 }
2394
2395 /* ***************** ******************** */
2396
2397 /* draw callback */
2398
2399 typedef struct drawDMVertSel_userData {
2400         MVert *mvert;
2401         int active;
2402         unsigned char *col[3];  /* (base, sel, act) */
2403         char sel_prev;
2404 } drawDMVertSel_userData;
2405
2406 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
2407                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2408 {
2409         drawDMVertSel_userData *data = userData;
2410         MVert *mv = &data->mvert[index];
2411
2412         if (!(mv->flag & ME_HIDE)) {
2413                 const char sel = (index == data->active) ? 2 : (mv->flag & SELECT);
2414                 if (sel != data->sel_prev) {
2415                         glColor3ubv(data->col[sel]);
2416                         data->sel_prev = sel;
2417                 }
2418
2419                 glVertex3fv(co);
2420         }
2421 }
2422
2423 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2424 {
2425         drawDMVertSel_userData data;
2426
2427         /* TODO define selected color */
2428         unsigned char base_col[3] = {0x0, 0x0, 0x0};
2429         unsigned char sel_col[3] = {0xd8, 0xb8, 0x0};
2430         unsigned char act_col[3] = {0xff, 0xff, 0xff};
2431
2432         data.mvert = me->mvert;
2433         data.active = BKE_mesh_mselect_active_get(me, ME_VSEL);
2434         data.sel_prev = 0xff;
2435
2436         data.col[0] = base_col;
2437         data.col[1] = sel_col;
2438         data.col[2] = act_col;
2439
2440         glBegin(GL_POINTS);
2441         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP);
2442         glEnd();
2443 }
2444
2445 /* ************** DRAW MESH ****************** */
2446
2447 /* First section is all the "simple" draw routines,
2448  * ones that just pass some sort of primitive to GL,
2449  * with perhaps various options to control lighting,
2450  * color, etc.
2451  *
2452  * These routines should not have user interface related
2453  * logic!!!
2454  */
2455
2456 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
2457 {
2458         float obmat[3][3];
2459
2460         copy_m3_m4(obmat, ob->obmat);
2461
2462         data->uniform_scale = is_uniform_scaled_m3(obmat);
2463
2464         if (!data->uniform_scale) {
2465                 /* inverted matrix */
2466                 invert_m3_m3(data->imat, obmat);
2467
2468                 /* transposed inverted matrix */
2469                 transpose_m3_m3(data->tmat, data->imat);
2470         }
2471 }
2472
2473 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
2474 {
2475         drawDMNormal_userData *data = userData;
2476         BMFace *efa = BM_face_at_index(data->bm, index);
2477         float n[3];
2478
2479         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2480                 if (!data->uniform_scale) {
2481                         mul_v3_m3v3(n, data->tmat, no);
2482                         normalize_v3(n);
2483                         mul_m3_v3(data->imat, n);
2484                 }
2485                 else {
2486                         copy_v3_v3(n, no);
2487                 }
2488
2489                 glVertex3fv(cent);
2490                 glVertex3f(cent[0] + n[0] * data->normalsize,
2491                            cent[1] + n[1] * data->normalsize,
2492                            cent[2] + n[2] * data->normalsize);
2493         }
2494 }
2495
2496 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2497 {
2498         drawDMNormal_userData data;
2499
2500         data.bm = em->bm;
2501         data.normalsize = scene->toolsettings->normalsize;
2502
2503         calcDrawDMNormalScale(ob, &data);
2504
2505         glBegin(GL_LINES);
2506         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2507         glEnd();
2508 }
2509
2510 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2511 {
2512         drawBMSelect_userData *data = userData;
2513         BMFace *efa = BM_face_at_index(data->bm, index);
2514         
2515         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
2516             (BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select))
2517         {
2518                 glVertex3fv(cent);
2519         }
2520 }
2521 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select)
2522 {
2523         drawBMSelect_userData data = {em->bm, select};
2524
2525         glBegin(GL_POINTS);
2526         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP);
2527         glEnd();
2528 }
2529
2530 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])
2531 {
2532         drawDMNormal_userData *data = userData;
2533         BMVert *eve = BM_vert_at_index(data->bm, index);
2534
2535         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2536                 float no[3], n[3];
2537
2538                 if (no_f) {
2539                         copy_v3_v3(no, no_f);
2540                 }
2541                 else {
2542                         normal_short_to_float_v3(no, no_s);
2543                 }
2544
2545                 if (!data->uniform_scale) {
2546                         mul_v3_m3v3(n, data->tmat, no);
2547                         normalize_v3(n);
2548                         mul_m3_v3(data->imat, n);
2549                 }
2550                 else {
2551                         copy_v3_v3(n, no);
2552                 }
2553
2554                 glVertex3fv(co);
2555                 glVertex3f(co[0] + n[0] * data->normalsize,
2556                            co[1] + n[1] * data->normalsize,
2557                            co[2] + n[2] * data->normalsize);
2558         }
2559 }
2560
2561 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2562 {
2563         drawDMNormal_userData data;
2564
2565         data.bm = em->bm;
2566         data.normalsize = scene->toolsettings->normalsize;
2567
2568         calcDrawDMNormalScale(ob, &data);
2569
2570         glBegin(GL_LINES);
2571         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2572         glEnd();
2573 }
2574
2575 /* Draw verts with color set based on selection */
2576 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2577                                    const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2578 {
2579         drawDMVerts_userData *data = userData;
2580         BMVert *eve = BM_vert_at_index(data->bm, index);
2581
2582         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2583                 /* skin nodes: draw a red circle around the root node(s) */
2584                 if (data->cd_vskin_offset != -1) {
2585                         const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
2586                         if (vs->flag & MVERT_SKIN_ROOT) {
2587                                 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2588                                 glEnd();
2589                         
2590                                 glColor4ubv(data->th_skin_root);
2591                                 drawcircball(GL_LINES, co, radius, data->imat);
2592
2593                                 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2594                                 glBegin(GL_POINTS);
2595                         }
2596                 }
2597
2598                 /* draw active in a different color - no need to stop/start point drawing for this :D */
2599                 if (eve == data->eve_act) {
2600                         glColor4ubv(data->th_editmesh_active);
2601                         glVertex3fv(co);
2602
2603                         /* back to regular vertex color */
2604                         glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2605                 }
2606                 else {
2607                         glVertex3fv(co);
2608                 }
2609         }
2610 }
2611
2612 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act,
2613                           RegionView3D *rv3d)
2614 {
2615         drawDMVerts_userData data;
2616         data.sel = sel;
2617         data.eve_act = eve_act;
2618         data.bm = em->bm;
2619
2620         /* Cache theme values */
2621         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2622         UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2623         UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2624         UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2625
2626         /* For skin root drawing */
2627         data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
2628         /* view-aligned matrix */
2629         mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2630         invert_m4(data.imat);
2631
2632         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
2633         glBegin(GL_POINTS);
2634         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP);
2635         glEnd();
2636 }
2637
2638 /* Draw edges with color set based on selection */
2639 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2640 {
2641         BMEdge *eed;
2642         drawDMEdgesSel_userData *data = userData;
2643         unsigned char *col;
2644
2645         eed = BM_edge_at_index(data->bm, index);
2646
2647         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2648                 if (eed == data->eed_act) {
2649                         glColor4ubv(data->actCol);
2650                 }
2651                 else {
2652                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2653                                 col = data->selCol;
2654                         }
2655                         else {
2656                                 col = data->baseCol;
2657                         }
2658                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
2659                         if (col[3] == 0)
2660                                 return DM_DRAW_OPTION_SKIP;
2661                         
2662                         glColor4ubv(col);
2663                 }
2664                 return DM_DRAW_OPTION_NORMAL;
2665         }
2666         else {
2667                 return DM_DRAW_OPTION_SKIP;
2668         }
2669 }
2670
2671 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2672                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2673 {
2674         drawDMEdgesSel_userData data;
2675         
2676         data.baseCol = baseCol;
2677         data.selCol = selCol;
2678         data.actCol = actCol;
2679         data.bm = em->bm;
2680         data.eed_act = eed_act;
2681         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2682 }
2683
2684 /* Draw edges */
2685 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2686 {
2687         if (BM_elem_flag_test(BM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2688                 return DM_DRAW_OPTION_SKIP;
2689         else
2690                 return DM_DRAW_OPTION_NORMAL;
2691 }
2692
2693 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
2694 {
2695         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em->bm);
2696 }
2697
2698 /* Draw edges with color interpolated based on selection */
2699 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2700 {
2701         drawDMEdgesSelInterp_userData *data = userData;
2702         if (BM_elem_flag_test(BM_edge_at_index(data->bm, index), BM_ELEM_HIDDEN))
2703                 return DM_DRAW_OPTION_SKIP;
2704         else
2705                 return DM_DRAW_OPTION_NORMAL;
2706 }
2707 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2708 {
2709         drawDMEdgesSelInterp_userData *data = userData;
2710         BMEdge *eed = BM_edge_at_index(data->bm, index);
2711         unsigned char **cols = userData;
2712         unsigned int col0_id = (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1;
2713         unsigned int col1_id = (BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1;
2714         unsigned char *col0 = cols[col0_id];
2715         unsigned char *col1 = cols[col1_id];
2716         unsigned char *col_pt;
2717
2718         if (col0_id == col1_id) {
2719                 col_pt = col0;
2720         }
2721         else if (t == 0.0f) {
2722                 col_pt = col0;
2723         }
2724         else if (t == 1.0f) {
2725                 col_pt = col1;
2726         }
2727         else {
2728                 unsigned char  col_blend[4];
2729                 interp_v4_v4v4_uchar(col_blend, col0, col1, t);
2730                 glColor4ubv(col_blend);
2731                 data->lastCol = NULL;
2732                 return;
2733         }
2734
2735         if (data->lastCol != col_pt) {
2736                 data->lastCol = col_pt;
2737                 glColor4ubv(col_pt);
2738         }
2739 }
2740
2741 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2742 {
2743         drawDMEdgesSelInterp_userData data;
2744         data.bm = em->bm;
2745         data.baseCol = baseCol;
2746         data.selCol = selCol;
2747         data.lastCol = NULL;
2748
2749         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, &data);
2750 }
2751
2752 static void bm_color_from_weight(float col[3], BMVert *vert, drawDMEdgesWeightInterp_userData *data)
2753 {
2754         MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, data->cd_dvert_offset);
2755         float weight = defvert_find_weight(dvert, data->vgroup_index);
2756
2757         if ((weight == 0.0f) &&
2758             ((data->weight_user == OB_DRAW_GROUPUSER_ACTIVE) ||
2759              ((data->weight_user == OB_DRAW_GROUPUSER_ALL) && defvert_is_weight_zero(dvert, data->defgroup_tot))))
2760         {
2761                 copy_v3_v3(col, data->alert_color);
2762         }
2763         else {
2764                 weight_to_rgb(col, weight);
2765         }
2766 }
2767
2768 static void draw_dm_edges_nop_interp__setDrawInterpOptions(void *UNUSED(userData), int UNUSED(index), float UNUSED(t))
2769 {
2770         /* pass */
2771 }
2772
2773 static void draw_dm_edges_weight_interp__setDrawInterpOptions(void *userData, int index, float t)
2774 {
2775         drawDMEdgesWeightInterp_userData *data = userData;
2776         BMEdge *eed = BM_edge_at_index(data->bm, index);
2777         float col[3];
2778
2779         if (t == 0.0f) {
2780                 bm_color_from_weight(col, eed->v1, data);
2781         }
2782         else if (t == 1.0f) {
2783                 bm_color_from_weight(col, eed->v2, data);
2784         }
2785         else {
2786                 float col_v1[3];
2787                 float col_v2[3];
2788
2789                 bm_color_from_weight(col_v1, eed->v1, data);
2790                 bm_color_from_weight(col_v2, eed->v2, data);
2791                 interp_v3_v3v3(col, col_v1, col_v2, t);
2792         }
2793
2794         glColor3fv(col);
2795 }
2796
2797 static void draw_dm_edges_weight_interp(BMEditMesh *em, DerivedMesh *dm, const char weight_user)
2798 {
2799         drawDMEdgesWeightInterp_userData data;
2800         Object *ob = em->ob;
2801
2802         data.bm = em->bm;
2803         data.cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
2804         data.defgroup_tot = BLI_listbase_count(&ob->defbase);
2805         data.vgroup_index = ob->actdef - 1;
2806         data.weight_user = weight_user;
2807         UI_GetThemeColor3fv(TH_VERTEX_UNREFERENCED, data.alert_color);
2808
2809         if ((data.vgroup_index != -1) && (data.cd_dvert_offset != -1)) {
2810                 glEnable(GL_BLEND);
2811                 dm->drawMappedEdgesInterp(
2812                         dm,
2813                         draw_dm_edges_sel_interp__setDrawOptions,
2814                         draw_dm_edges_weight_interp__setDrawInterpOptions,
2815                         &data);
2816                 glDisable(GL_BLEND);
2817         }
2818         else {
2819                 float col[3];
2820
2821                 if (data.weight_user == OB_DRAW_GROUPUSER_NONE) {
2822                         weight_to_rgb(col, 0.0f);
2823                 }
2824                 else {
2825                         copy_v3_v3(col, data.alert_color);
2826                 }
2827                 glColor3fv(col);
2828
2829                 dm->drawMappedEdgesInterp(
2830                         dm,
2831                         draw_dm_edges_sel_interp__setDrawOptions,
2832                         draw_dm_edges_nop_interp__setDrawInterpOptions,
2833                         &data);
2834         }
2835
2836 }
2837
2838 static bool draw_dm_edges_weight_check(Mesh *me, View3D *v3d)
2839 {
2840         if (me->drawflag & ME_DRAWEIGHT) {
2841                 if ((v3d->drawtype == OB_WIRE) ||
2842                     (v3d->flag2 & V3D_SOLID_MATCAP) ||
2843                     ((v3d->flag2 & V3D_OCCLUDE_WIRE) && (v3d->drawtype > OB_WIRE)))
2844                 {
2845                         return true;
2846                 }
2847         }
2848
2849         return false;
2850 }
2851
2852 /* Draw only seam edges */
2853 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2854 {
2855         BMEdge *eed = BM_edge_at_index(userData, index);
2856
2857         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2858                 return DM_DRAW_OPTION_NORMAL;
2859         else
2860                 return DM_DRAW_OPTION_SKIP;
2861 }
2862
2863 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2864 {
2865         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em->bm);
2866 }
2867
2868 /* Draw only sharp edges */
2869 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2870 {
2871         BMEdge *eed = BM_edge_at_index(userData, index);
2872
2873         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2874                 return DM_DRAW_OPTION_NORMAL;
2875         else
2876                 return DM_DRAW_OPTION_SKIP;
2877 }
2878
2879 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2880 {
2881         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em->bm);
2882 }
2883
2884 #ifdef WITH_FREESTYLE
2885
2886 static bool draw_dm_test_freestyle_edge_mark(BMesh *bm, BMEdge *eed)
2887 {
2888         FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
2889         if (!fed)
2890                 return false;
2891         return (fed->flag & FREESTYLE_EDGE_MARK) != 0;
2892 }
2893
2894 /* Draw only Freestyle feature edges */
2895 static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
2896 {
2897         BMEdge *eed = BM_edge_at_index(userData, index);
2898
2899         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && draw_dm_test_freestyle_edge_mark(userData, eed))
2900                 return DM_DRAW_OPTION_NORMAL;
2901         else
2902                 return DM_DRAW_OPTION_SKIP;
2903 }
2904
2905 static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
2906 {
2907         dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em->bm);
2908 }
2909
2910 static bool draw_dm_test_freestyle_face_mark(BMesh *bm, BMFace *efa)
2911 {
2912         FreestyleFace *ffa = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
2913         if (!ffa)
2914                 return false;
2915         return (ffa->flag & FREESTYLE_FACE_MARK) != 0;
2916 }
2917
2918 #endif
2919
2920 /* Draw loop normals. */
2921 static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int face_index,
2922                                           const float co[3], const float no[3])
2923 {
2924         if (no) {
2925                 const drawDMNormal_userData *data = userData;
2926                 const BMVert *eve = BM_vert_at_index(data->bm, vertex_index);
2927                 const BMFace *efa = BM_face_at_index(data->bm, face_index);
2928                 float vec[3];
2929
2930                 if (!(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))) {
2931                         if (!data->uniform_scale) {
2932                                 mul_v3_m3v3(vec, (float(*)[3])data->tmat, no);
2933                                 normalize_v3(vec);
2934                                 mul_m3_v3((float(*)[3])data->imat, vec);
2935                         }
2936                         else {
2937                                 copy_v3_v3(vec, no);
2938                         }
2939                         mul_v3_fl(vec, data->normalsize);
2940                         add_v3_v3(vec, co);
2941                         glVertex3fv(co);
2942                         glVertex3fv(vec);
2943                 }
2944         }
2945 }
2946
2947 static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2948 {
2949         drawDMNormal_userData data;
2950
2951         data.bm = em->bm;
2952         data.normalsize = scene->toolsettings->normalsize;
2953
2954         calcDrawDMNormalScale(ob, &data);
2955
2956         glBegin(GL_LINES);
2957         dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
2958         glEnd();
2959 }
2960
2961 /* Draw faces with color set based on selection
2962  * return 2 for the active face so it renders with stipple enabled */
2963 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2964 {
2965         drawDMFacesSel_userData *data = userData;
2966         BMFace *efa = BM_face_at_index(data->bm, index);
2967         unsigned char *col;
2968         
2969         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2970                 if (efa == data->efa_act) {
2971                         glColor4ubv(data->cols[2]);
2972                         return DM_DRAW_OPTION_STIPPLE;
2973                 }
2974                 else {
2975 #ifdef WITH_FREESTYLE
2976                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
2977 #else
2978                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2979 #endif
2980                         if (col[3] == 0)
2981                                 return DM_DRAW_OPTION_SKIP;
2982                         glColor4ubv(col);
2983                         return DM_DRAW_OPTION_NORMAL;
2984                 }
2985         }
2986         return DM_DRAW_OPTION_SKIP;
2987 }
2988
2989 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2990 {
2991
2992         drawDMFacesSel_userData *data = userData;
2993         int i;
2994         BMFace *efa;
2995         BMFace *next_efa;
2996
2997         unsigned char *col, *next_col;
2998
2999         i = data->orig_index_mp_to_orig ? data->orig_index_mp_to_orig[index] : index;
3000         efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
3001         i = data->orig_index_mp_to_orig ? data->orig_index_mp_to_orig[next_index] : next_index;
3002         next_efa = (i != ORIGINDEX_NONE) ? BM_face_at_index(data->bm, i) : NULL;
3003
3004         if (ELEM(NULL, efa, next_efa))
3005                 return 0;
3006
3007         if (efa == next_efa)
3008                 return 1;
3009
3010         if (efa == data->efa_act || next_efa == data->efa_act)
3011                 return 0;
3012
3013 #ifdef WITH_FREESTYLE
3014         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->bm, efa) ? 3 : 0];
3015         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];
3016 #else
3017         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
3018         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
3019 #endif
3020
3021         if (col[3] == 0 || next_col[3] == 0)
3022                 return 0;
3023
3024         return col == next_col;
3025 }
3026
3027 /* also draws the active face */
3028 #ifdef WITH_FREESTYLE
3029 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
3030                               unsigned char *selCol, unsigned char *actCol, unsigned char *markCol, BMFace *efa_act)
3031 #else
3032 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
3033                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
3034 #endif
3035 {
3036         drawDMFacesSel_userData data;
3037         data.dm = dm;
3038         data.cols[0] = baseCol;
3039         data.bm = em->bm;
3040         data.cols[1] = selCol;
3041         data.cols[2] = actCol;
3042 #ifdef WITH_FREESTYLE
3043         data.cols[3] = markCol;
3044 #endif
3045         data.efa_act = efa_act;
3046         /* double lookup */
3047         data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
3048
3049         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, NULL, draw_dm_faces_sel__compareDrawOptions, &data, DM_DRAW_SKIP_HIDDEN);
3050 }
3051
3052 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
3053 {
3054         drawDMLayer_userData *data = userData;
3055         BMesh *bm = data->bm;
3056         BMEdge *eed = BM_edge_at_index(bm, index);
3057         
3058         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
3059                 const float crease = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
3060                 if (crease != 0.0f) {
3061                         UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_CREASE, crease);
3062                         return DM_DRAW_OPTION_NORMAL;
3063                 }
3064         }
3065         return DM_DRAW_OPTION_SKIP;
3066 }
3067 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
3068 {
3069         drawDMLayer_userData data;
3070
3071         data.bm = em->bm;
3072         data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
3073
3074         if (data.cd_layer_offset != -1) {
3075                 glLineWidth(3.0);
3076                 dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data);
3077         }
3078 }
3079
3080 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
3081 {
3082         drawDMLayer_userData *data = userData;
3083         BMesh *bm = data->bm;
3084         BMEdge *eed = BM_edge_at_index(bm, index);
3085
3086         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
3087                 const float bweight = BM_ELEM_CD_GET_FLOAT(eed, data->cd_layer_offset);
3088                 if (bweight != 0.0f) {
3089                         UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_BEVEL, bweight);
3090                         return DM_DRAW_OPTION_NORMAL;
3091                 }
3092         }
3093         return DM_DRAW_OPTION_SKIP;
3094 }
3095 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
3096                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
3097 {
3098         drawDMLayer_userData *data = userData;
3099         BMesh *bm = data->bm;
3100         BMVert *eve = BM_vert_at_index(bm, index);
3101
3102         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
3103                 const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset);
3104                 if (bweight != 0.0f) {
3105                         UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_BEVEL, bweight);
3106                         glVertex3fv(co);
3107                 }
3108         }
3109 }
3110 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
3111 {
3112         ToolSettings *ts = scene->toolsettings;
3113
3114         if (ts->selectmode & SCE_SELECT_VERTEX) {
3115                 drawDMLayer_userData data;
3116
3117                 data.bm = em->bm;
3118                 data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT);
3119
3120                 if (data.cd_layer_offset != -1) {
3121                         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
3122                         glBegin(GL_POINTS);
3123                         dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP);
3124                         glEnd();
3125                 }
3126         }
3127         else {
3128                 drawDMLayer_userData data;
3129
3130                 data.bm = em->bm;
3131                 data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
3132
3133                 if (data.cd_layer_offset != -1) {
3134                         glLineWidth(3.0);
3135                         dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data);
3136                 }
3137         }
3138 }
3139
3140 /* Second section of routines: Combine first sets to form fancy
3141  * drawing routines (for example rendering twice to get overlays).
3142  *
3143  * Also includes routines that are basic drawing but are too
3144  * specialized to be split out (like drawing creases or measurements).
3145  */
3146
3147 /* EditMesh drawing routines */
3148
3149 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
3150                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
3151                                 RegionView3D *rv3d)
3152 {
3153         ToolSettings *ts = scene->toolsettings;
3154
3155         if (v3d->zbuf) glDepthMask(0);  /* disable write in zbuffer, zbuf select */
3156
3157         for (int sel = 0; sel < 2; sel++) {
3158                 unsigned char col[4], fcol[4];
3159
3160                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
3161                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE_EDIT, fcol);
3162
3163                 for (int pass = 0; pass < 2; pass++) {
3164                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
3165                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
3166
3167                         if (pass == 0) {
3168                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
3169                                         glDisable(GL_DEPTH_TEST);
3170                                         glEnable(GL_BLEND);
3171                                 }
3172                                 else {
3173                                         continue;
3174                                 }
3175
3176                                 size = (size > 2.1f ? size / 2.0f : size);
3177                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
3178                                 col[3] = fcol[3] = 100;
3179                         }
3180                         else {
3181                                 col[3] = fcol[3] = 255;
3182                         }
3183
3184                         if (ts->selectmode & SCE_SELECT_VERTEX) {
3185                                 glPointSize(size);
3186                                 glColor4ubv(col);
3187                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
3188                         }
3189                         
3190                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
3191                                 glPointSize(fsize);
3192                                 glColor4ubv(fcol);
3193                                 draw_dm_face_centers(em, cageDM, sel);
3194                         }
3195                         
3196                         if (pass == 0) {
3197                                 glDisable(GL_BLEND);
3198                                 glEnable(GL_DEPTH_TEST);
3199                         }
3200                 }
3201         }