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