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