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