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