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