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