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