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