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