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