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