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