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