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