Fix for r51837.
[blender-staging.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_camera_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_constraint_types.h"  /* for drawing constraint */
35 #include "DNA_lamp_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_smoke_types.h"
42 #include "DNA_world_types.h"
43 #include "DNA_object_types.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47
48 #include "BKE_anim.h"  /* for the where_on_path function */
49 #include "BKE_armature.h"
50 #include "BKE_camera.h"
51 #include "BKE_constraint.h"  /* for the get_constraint_target function */
52 #include "BKE_curve.h"
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_deform.h"
55 #include "BKE_displist.h"
56 #include "BKE_font.h"
57 #include "BKE_global.h"
58 #include "BKE_image.h"
59 #include "BKE_key.h"
60 #include "BKE_lattice.h"
61 #include "BKE_mesh.h"
62 #include "BKE_material.h"
63 #include "BKE_mball.h"
64 #include "BKE_modifier.h"
65 #include "BKE_object.h"
66 #include "BKE_paint.h"
67 #include "BKE_particle.h"
68 #include "BKE_pointcache.h"
69 #include "BKE_scene.h"
70 #include "BKE_unit.h"
71 #include "BKE_tracking.h"
72
73 #include "BKE_tessmesh.h"
74
75 #include "IMB_imbuf.h"
76 #include "IMB_imbuf_types.h"
77
78 #include "BIF_gl.h"
79 #include "BIF_glutil.h"
80
81 #include "GPU_draw.h"
82 #include "GPU_extensions.h"
83
84 #include "ED_mesh.h"
85 #include "ED_particle.h"
86 #include "ED_screen.h"
87 #include "ED_sculpt.h"
88 #include "ED_types.h"
89
90 #include "UI_resources.h"
91
92 #include "WM_api.h"
93 #include "BLF_api.h"
94
95 #include "view3d_intern.h"  /* bad level include */
96
97 typedef enum eWireDrawMode {
98         OBDRAW_WIRE_OFF = 0,
99         OBDRAW_WIRE_ON = 1,
100         OBDRAW_WIRE_ON_DEPTH = 2
101 } eWireDrawMode;
102
103 typedef struct drawDMVerts_userData {
104         BMEditMesh *em; /* BMESH BRANCH ONLY */
105
106         int sel;
107         BMVert *eve_act;
108
109         /* cached theme values */
110         unsigned char th_editmesh_active[4];
111         unsigned char th_vertex_select[4];
112         unsigned char th_vertex[4];
113         unsigned char th_skin_root[4];
114         float th_vertex_size;
115
116         /* for skin node drawing */
117         int has_vskin;
118         float imat[4][4];
119 } drawDMVerts_userData;
120
121 typedef struct drawDMEdgesSel_userData {
122         BMEditMesh *em; /* BMESH BRANCH ONLY */
123
124         unsigned char *baseCol, *selCol, *actCol;
125         BMEdge *eed_act;
126 } drawDMEdgesSel_userData;
127
128 typedef struct drawDMFacesSel_userData {
129         unsigned char *cols[3];
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
2279 /* Draw faces with color set based on selection
2280  * return 2 for the active face so it renders with stipple enabled */
2281 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2282 {
2283         drawDMFacesSel_userData *data = userData;
2284         BMFace *efa = EDBM_face_at_index(data->em, index);
2285         unsigned char *col;
2286         
2287         if (!efa)
2288                 return DM_DRAW_OPTION_SKIP;
2289         
2290         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2291                 if (efa == data->efa_act) {
2292                         glColor4ubv(data->cols[2]);
2293                         return DM_DRAW_OPTION_STIPPLE;
2294                 }
2295                 else {
2296                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2297                         if (col[3] == 0)
2298                                 return DM_DRAW_OPTION_SKIP;
2299                         glColor4ubv(col);
2300                         return DM_DRAW_OPTION_NORMAL;
2301                 }
2302         }
2303         return DM_DRAW_OPTION_SKIP;
2304 }
2305
2306 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2307 {
2308
2309         drawDMFacesSel_userData *data = userData;
2310         BMFace *efa;
2311         BMFace *next_efa;
2312
2313         unsigned char *col, *next_col;
2314
2315         if (!data->orig_index_mf_to_mpoly)
2316                 return 0;
2317
2318         efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index));
2319         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));
2320
2321         if (efa == next_efa)
2322                 return 1;
2323
2324         if (efa == data->efa_act || next_efa == data->efa_act)
2325                 return 0;
2326
2327         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2328         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
2329
2330         if (col[3] == 0 || next_col[3] == 0)
2331                 return 0;
2332
2333         return col == next_col;
2334 }
2335
2336 /* also draws the active face */
2337 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2338                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2339 {
2340         drawDMFacesSel_userData data;
2341         data.dm = dm;
2342         data.cols[0] = baseCol;
2343         data.em = em;
2344         data.cols[1] = selCol;
2345         data.cols[2] = actCol;
2346         data.efa_act = efa_act;
2347         /* double lookup */
2348         data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2349         data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
2350         if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == FALSE) {
2351                 data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
2352         }
2353
2354         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2355 }
2356
2357 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2358 {
2359         BMEditMesh *em = userData;
2360         BMEdge *eed = EDBM_edge_at_index(userData, index);
2361         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2362         
2363         if (!crease)
2364                 return DM_DRAW_OPTION_SKIP;
2365         
2366         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease != 0.0f) {
2367                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2368                 return DM_DRAW_OPTION_NORMAL;
2369         }
2370         else {
2371                 return DM_DRAW_OPTION_SKIP;
2372         }
2373 }
2374 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2375 {
2376         glLineWidth(3.0);
2377         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2378         glLineWidth(1.0);
2379 }
2380
2381 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2382 {
2383         BMEditMesh *em = userData;
2384         BMEdge *eed = EDBM_edge_at_index(userData, index);
2385         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2386
2387         if (!bweight)
2388                 return DM_DRAW_OPTION_SKIP;
2389         
2390         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2391                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2392                 return DM_DRAW_OPTION_NORMAL;
2393         }
2394         else {
2395                 return DM_DRAW_OPTION_SKIP;
2396         }
2397 }
2398 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2399                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2400 {
2401         BMEditMesh *em = userData;
2402         BMVert *eve = EDBM_vert_at_index(userData, index);
2403         float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2404         
2405         if (!bweight)
2406                 return;
2407         
2408         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2409                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2410                 bglVertex3fv(co);
2411         }
2412 }
2413 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2414 {
2415         ToolSettings *ts = scene->toolsettings;
2416
2417         if (ts->selectmode & SCE_SELECT_VERTEX) {
2418                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2419                 bglBegin(GL_POINTS);
2420                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2421                 bglEnd();
2422         }
2423         else {
2424                 glLineWidth(3.0);
2425                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2426                 glLineWidth(1.0);
2427         }
2428 }
2429
2430 /* Second section of routines: Combine first sets to form fancy
2431  * drawing routines (for example rendering twice to get overlays).
2432  *
2433  * Also includes routines that are basic drawing but are too
2434  * specialized to be split out (like drawing creases or measurements).
2435  */
2436
2437 /* EditMesh drawing routines*/
2438
2439 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2440                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2441                                 RegionView3D *rv3d)
2442 {
2443         ToolSettings *ts = scene->toolsettings;
2444         int sel;
2445
2446         if (v3d->zbuf) glDepthMask(0);  /* disable write in zbuffer, zbuf select */
2447
2448         for (sel = 0; sel < 2; sel++) {
2449                 unsigned char col[4], fcol[4];
2450                 int pass;
2451
2452                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2453                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE, fcol);
2454
2455                 for (pass = 0; pass < 2; pass++) {
2456                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2457                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2458
2459                         if (pass == 0) {
2460                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2461                                         glDisable(GL_DEPTH_TEST);
2462
2463                                         glEnable(GL_BLEND);
2464                                 }
2465                                 else {
2466                                         continue;
2467                                 }
2468
2469                                 size = (size > 2.1f ? size / 2.0f : size);
2470                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2471                                 col[3] = fcol[3] = 100;
2472                         }
2473                         else {
2474                                 col[3] = fcol[3] = 255;
2475                         }
2476
2477                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2478                                 glPointSize(size);
2479                                 glColor4ubv(col);
2480                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2481                         }
2482                         
2483                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2484                                 glPointSize(fsize);
2485                                 glColor4ubv(fcol);
2486                                 draw_dm_face_centers(em, cageDM, sel);
2487                         }
2488                         
2489                         if (pass == 0) {
2490                                 glDisable(GL_BLEND);
2491                                 glEnable(GL_DEPTH_TEST);
2492                         }
2493                 }
2494         }
2495
2496         if (v3d->zbuf) glDepthMask(1);
2497         glPointSize(1.0);
2498 }
2499
2500 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2501                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2502                                 BMEdge *eed_act)
2503 {
2504         ToolSettings *ts = scene->toolsettings;
2505         int pass;
2506         unsigned char wireCol[4], selCol[4], actCol[4];
2507
2508         /* since this function does transparent... */
2509         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2510         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2511         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2512         
2513         /* when sel only is used, don't render wire, only selected, this is used for
2514          * textured draw mode when the 'edges' option is disabled */
2515         if (sel_only)
2516                 wireCol[3] = 0;
2517
2518         for (pass = 0; pass < 2; pass++) {
2519                 /* show wires in transparent when no zbuf clipping for select */
2520                 if (pass == 0) {
2521                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2522                                 glEnable(GL_BLEND);
2523                                 glDisable(GL_DEPTH_TEST);
2524                                 selCol[3] = 85;
2525                                 if (!sel_only) wireCol[3] = 85;
2526                         }
2527                         else {
2528                                 continue;
2529                         }
2530                 }
2531                 else {
2532                         selCol[3] = 255;
2533                         if (!sel_only) wireCol[3] = 255;
2534                 }
2535
2536                 if (ts->selectmode == SCE_SELECT_FACE) {
2537                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2538                 }
2539                 else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
2540                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2541                                 glShadeModel(GL_SMOOTH);
2542                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2543                                 glShadeModel(GL_FLAT);
2544                         }
2545                         else {
2546                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2547                         }
2548                 }
2549                 else {
2550                         if (!sel_only) {
2551                                 glColor4ubv(wireCol);
2552                                 draw_dm_edges(em, cageDM);
2553                         }
2554                 }
2555
2556                 if (pass == 0) {
2557                         glDisable(GL_BLEND);
2558                         glEnable(GL_DEPTH_TEST);
2559                 }
2560         }
2561 }
2562
2563 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2564 {
2565         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2566         Mesh *me = ob->data;
2567         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2568         char numstr[32]; /* Stores the measurement display text here */
2569         const char *conv_float; /* Use a float conversion matching the grid size */
2570         unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2571         float area; /* area of the face */
2572         float grid = unit->system ? unit->scale_length : v3d->grid;
2573         const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
2574         const int do_global = v3d->flag & V3D_GLOBAL_STATS;
2575         const int do_moving = G.moving;
2576
2577         BMIter iter;
2578         int i;
2579
2580         /* make the precision of the pronted value proportionate to the gridsize */
2581
2582         if (grid < 0.01f) conv_float = "%.6g";
2583         else if (grid < 0.1f) conv_float = "%.5g";
2584         else if (grid < 1.0f) conv_float = "%.4g";
2585         else if (grid < 10.0f) conv_float = "%.3g";
2586         else conv_float = "%.2g";
2587         
2588         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2589                 BMEdge *eed;
2590
2591                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2592
2593                 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2594                 for (; eed; eed = BM_iter_step(&iter)) {
2595                         /* draw selected edges, or edges next to selected verts while draging */
2596                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2597                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2598                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2599                         {
2600
2601                                 copy_v3_v3(v1, eed->v1->co);
2602                                 copy_v3_v3(v2, eed->v2->co);
2603
2604                                 mid_v3_v3v3(vmid, v1, v2);
2605
2606                                 if (do_global) {
2607                                         mul_mat3_m4_v3(ob->obmat, v1);
2608                                         mul_mat3_m4_v3(ob->obmat, v2);
2609                                 }
2610
2611                                 if (unit->system) {
2612                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2613                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2614                                 }
2615                                 else {
2616                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2617                                 }
2618
2619                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2620                         }
2621                 }
2622         }
2623
2624         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2625                 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2626                  * so instead add up tessellation triangle areas */
2627                 BMFace *f;
2628                 int n;
2629
2630 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                      \
2631         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                               \
2632                 mul_v3_fl(vmid, 1.0f / (float)n);                                     \
2633                 if (unit->system)                                                     \
2634                         bUnit_AsString(numstr, sizeof(numstr),                            \
2635                                        (double)(area * unit->scale_length),               \
2636                                        3, unit->system, B_UNIT_LENGTH, do_split, FALSE);  \
2637                 else                                                                  \
2638                         BLI_snprintf(numstr, sizeof(numstr), conv_float, area);           \
2639                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);          \
2640         } (void)0
2641
2642                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2643                 
2644                 f = NULL;
2645                 area = 0.0;
2646                 zero_v3(vmid);
2647                 n = 0;
2648                 for (i = 0; i < em->tottri; i++) {
2649                         BMLoop **l = em->looptris[i];
2650                         if (f && l[0]->f != f) {
2651                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2652                                 zero_v3(vmid);
2653                                 area = 0.0;
2654                                 n = 0;
2655                         }
2656
2657                         f = l[0]->f;
2658                         copy_v3_v3(v1, l[0]->v->co);
2659                         copy_v3_v3(v2, l[1]->v->co);
2660                         copy_v3_v3(v3, l[2]->v->co);
2661                         add_v3_v3(vmid, v1);
2662                         add_v3_v3(vmid, v2);
2663                         add_v3_v3(vmid, v3);
2664                         n += 3;
2665                         if (do_global) {
2666                                 mul_mat3_m4_v3(ob->obmat, v1);
2667                                 mul_mat3_m4_v3(ob->obmat, v2);
2668                                 mul_mat3_m4_v3(ob->obmat, v3);
2669                         }
2670                         area += area_tri_v3(v1, v2, v3);
2671                 }
2672
2673                 if (f) {
2674                         DRAW_EM_MEASURE_STATS_FACEAREA();
2675                 }
2676 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2677         }
2678
2679         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2680                 BMFace *efa;
2681                 int is_rad = unit->system_rotation == USER_UNIT_ROT_RADIANS;
2682
2683                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2684
2685
2686                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2687                         const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
2688
2689                         if (is_face_sel || do_moving) {
2690                                 BMIter liter;
2691                                 BMLoop *loop;
2692                                 int is_first = TRUE;
2693
2694                                 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
2695                                         if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
2696                                                 float angle;
2697
2698                                                 /* lazy init center calc */
2699                                                 if (is_first) {
2700                                                         BM_face_calc_center_bounds(efa, vmid);
2701                                                         /* Avoid triple matrix multiply every vertex for 'global' */
2702                                                         if (do_global) {
2703                                                                 copy_v3_v3(v1, loop->prev->v->co);
2704                                                                 copy_v3_v3(v2, loop->v->co);
2705                                                                 mul_mat3_m4_v3(ob->obmat, v1);
2706                                                                 mul_mat3_m4_v3(ob->obmat, v2);
2707                                                         }
2708                                                         is_first = FALSE;
2709                                                 }
2710
2711                                                 if (do_global) {
2712                                                         copy_v3_v3(v3, loop->next->v->co);
2713
2714                                                         mul_mat3_m4_v3(ob->obmat, v3);
2715
2716                                                         angle = angle_v3v3v3(v1, v2, v3);
2717                                                         copy_v3_v3(v1, v2);
2718                                                         copy_v3_v3(v2, v3);
2719                                                 }
2720                                                 else {
2721                                                         angle = angle_v3v3v3(loop->prev->v->co, loop->v->co, loop->next->v->co);
2722                                                 }
2723
2724                                                 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
2725                                                 interp_v3_v3v3(fvec, vmid, loop->v->co, 0.8f);
2726                                                 view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
2727                                         }
2728                                 }
2729                         }
2730                 }
2731         }
2732 }
2733
2734 static void draw_em_indices(BMEditMesh *em)
2735 {
2736         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2737         BMEdge *e;
2738         BMFace *f;
2739         BMVert *v;
2740         int i;
2741         char numstr[32];
2742         float pos[3];
2743         unsigned char col[4];
2744
2745         BMIter iter;
2746         BMesh *bm = em->bm;
2747
2748         /* For now, reuse appropriate theme colors from stats text colors */
2749         i = 0;
2750         if (em->selectmode & SCE_SELECT_VERTEX) {
2751                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2752                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
2753                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
2754                                 sprintf(numstr, "%d", i);
2755                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
2756                         }
2757                         i++;
2758                 }
2759         }
2760
2761         if (em->selectmode & SCE_SELECT_EDGE) {
2762                 i = 0;
2763                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2764                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2765                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
2766                                 sprintf(numstr, "%d", i);
2767                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
2768                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2769                         }
2770                         i++;
2771                 }
2772         }
2773
2774         if (em->selectmode & SCE_SELECT_FACE) {
2775                 i = 0;
2776                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2777                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
2778                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2779                                 BM_face_calc_center_mean(f, pos);
2780                                 sprintf(numstr, "%d", i);
2781                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2782                         }
2783                         i++;
2784                 }
2785         }
2786 }
2787
2788 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
2789 {
2790         BMFace *efa = EDBM_face_at_index(userData, index);
2791
2792         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2793                 GPU_enable_material(efa->mat_nr + 1, NULL);
2794                 return DM_DRAW_OPTION_NORMAL;
2795         }
2796         else
2797                 return DM_DRAW_OPTION_SKIP;
2798 }
2799
2800 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2801 {
2802         BMFace *efa = EDBM_face_at_index(userData, index);
2803
2804         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
2805                 return DM_DRAW_OPTION_SKIP;
2806         else
2807                 return DM_DRAW_OPTION_NORMAL;
2808 }
2809
2810 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2811                           Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt)
2812
2813 {
2814         Mesh *me = ob->data;
2815         BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE); /* annoying but active faces is stored differently */
2816         BMEdge *eed_act = NULL;
2817         BMVert *eve_act = NULL;
2818         
2819         if (em->bm->selected.last) {
2820                 BMEditSelection *ese = em->bm->selected.last;
2821                 /* face is handeled above */
2822 #if 0
2823                 if (ese->type == BM_FACE) {
2824                         efa_act = (BMFace *)ese->data;
2825                 }
2826                 else
2827 #endif
2828                 if (ese->htype == BM_EDGE) {
2829                         eed_act = (BMEdge *)ese->ele;
2830                 }
2831                 else if (ese->htype == BM_VERT) {
2832                         eve_act = (BMVert *)ese->ele;
2833                 }
2834         }
2835         
2836         EDBM_index_arrays_init(em, 1, 1, 1);
2837
2838         if (dt > OB_WIRE) {
2839                 if (check_object_draw_texture(scene, v3d, dt)) {
2840                         if (draw_glsl_material(scene, ob, v3d, dt)) {
2841                                 glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
2842
2843                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2844                                                              draw_em_fancy__setGLSLFaceOpts, em);
2845                                 GPU_disable_material();
2846
2847                                 glFrontFace(GL_CCW);
2848                         }
2849                         else {
2850                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2851                         }
2852                 }
2853                 else {
2854                         /* 3 floats for position,
2855                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
2856                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
2857
2858                         glEnable(GL_LIGHTING);
2859                         glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
2860                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
2861
2862                         glFrontFace(GL_CCW);
2863                         glDisable(GL_LIGHTING);
2864                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
2865                 }
2866
2867                 /* Setup for drawing wire over, disable zbuffer
2868                  * write to show selected edge wires better */
2869                 UI_ThemeColor(TH_WIRE);
2870
2871                 bglPolygonOffset(rv3d->dist, 1.0);
2872                 glDepthMask(0);
2873         }
2874         else {
2875                 if (cageDM != finalDM) {
2876                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2877                         finalDM->drawEdges(finalDM, 1, 0);
2878                 }
2879         }
2880         
2881         if (me->drawflag & ME_DRAWFACES) {  /* transp faces */
2882                 unsigned char col1[4], col2[4], col3[4];
2883
2884                 UI_GetThemeColor4ubv(TH_FACE, col1);
2885                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2886                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2887
2888                 glEnable(GL_BLEND);
2889                 glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
2890
2891                 /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */
2892                 if (check_object_draw_texture(scene, v3d, dt))
2893                         col1[3] = 0;
2894
2895                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
2896
2897                 glDisable(GL_BLEND);
2898                 glDepthMask(1);  /* restore write in zbuffer */
2899         }
2900         else if (efa_act) {
2901                 /* even if draw faces is off it would be nice to draw the stipple face
2902                  * Make all other faces zero alpha except for the active
2903                  * */
2904                 unsigned char col1[4], col2[4], col3[4];
2905                 col1[3] = col2[3] = 0; /* don't draw */
2906                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2907
2908                 glEnable(GL_BLEND);
2909                 glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
2910
2911                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
2912
2913                 glDisable(GL_BLEND);
2914                 glDepthMask(1);  /* restore write in zbuffer */
2915
2916         }
2917
2918         /* here starts all fancy draw-extra over */
2919         if ((me->drawflag & ME_DRAWEDGES) == 0 && check_object_draw_texture(scene, v3d, dt)) {
2920                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, don't draw any edges */
2921                 
2922                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2923                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2924                 
2925         }
2926         else {
2927                 if (me->drawflag & ME_DRAWSEAMS) {
2928                         UI_ThemeColor(TH_EDGE_SEAM);
2929                         glLineWidth(2);
2930
2931                         draw_dm_edges_seams(em, cageDM);
2932
2933                         glColor3ub(0, 0, 0);
2934                         glLineWidth(1);
2935                 }
2936                 
2937                 if (me->drawflag & ME_DRAWSHARP) {
2938                         UI_ThemeColor(TH_EDGE_SHARP);
2939                         glLineWidth(2);
2940
2941                         draw_dm_edges_sharp(em, cageDM);
2942
2943                         glColor3ub(0, 0, 0);
2944                         glLineWidth(1);
2945                 }
2946
2947                 if (me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2948                         draw_dm_creases(em, cageDM);
2949                 }
2950                 if (me->drawflag & ME_DRAWBWEIGHTS) {
2951                         draw_dm_bweights(em, scene, cageDM);
2952                 }
2953
2954                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2955         }
2956
2957         {
2958                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d);
2959
2960                 if (me->drawflag & ME_DRAWNORMALS) {
2961                         UI_ThemeColor(TH_NORMAL);
2962                         draw_dm_face_normals(em, scene, ob, cageDM);
2963                 }
2964                 if (me->drawflag & ME_DRAW_VNORMALS) {
2965                         UI_ThemeColor(TH_VNORMAL);
2966                         draw_dm_vert_normals(em, scene, ob, cageDM);
2967                 }
2968
2969                 if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_FACEAREA | ME_DRAWEXTRA_FACEANG)) &&
2970                     !(v3d->flag2 & V3D_RENDER_OVERRIDE))
2971                 {
2972                         draw_em_measure_stats(v3d, ob, em, &scene->unit);
2973                 }
2974
2975                 if ((G.debug & G_DEBUG) && (me->drawflag & ME_DRAWEXTRA_INDICES) &&
2976                     !(v3d->flag2 & V3D_RENDER_OVERRIDE))
2977                 {
2978                         draw_em_indices(em);
2979                 }
2980         }
2981
2982         if (dt > OB_WIRE) {
2983                 glDepthMask(1);
2984                 bglPolygonOffset(rv3d->dist, 0.0);
2985                 GPU_disable_material();
2986         }
2987
2988         EDBM_index_arrays_free(em);
2989 }
2990
2991 /* Mesh drawing routines */
2992
2993 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2994 {
2995         if ((v3d->transp == FALSE) &&  /* not when we draw the transparent pass */
2996             (ob->mode & OB_MODE_ALL_PAINT) == FALSE) /* not when painting (its distracting) - campbell */
2997         {
2998                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2999                 glDepthMask(0);
3000
3001                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
3002                  * drawFacesSolid() doesn't draw the transparent faces */
3003                 if (ob->dtx & OB_DRAWTRANSP) {
3004                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3005                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3006                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3007                         GPU_disable_material();
3008                 }
3009                 else {
3010                         dm->drawEdges(dm, 0, 1);
3011                 }
3012
3013                 glLineWidth(1.0);
3014                 glDepthMask(1);
3015         }
3016 }
3017
3018 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
3019                             const short dt, const unsigned char ob_wire_col[4], const short dflag)
3020 {
3021         Object *ob = base->object;
3022         Mesh *me = ob->data;
3023         Material *ma = give_current_material(ob, 1);
3024         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3025         eWireDrawMode draw_wire = OBDRAW_WIRE_OFF;
3026         int /* totvert,*/ totedge, totface;
3027         DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
3028         const short is_obact = (ob == OBACT);
3029         int draw_flags = (is_obact && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3030
3031         if (!dm)
3032                 return;
3033
3034         /* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
3035          * Note: Last "preview-active" modifier in stack will win! */
3036         if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob))
3037                 draw_flags |= DRAW_MODIFIERS_PREVIEW;
3038
3039         /* Unwanted combination */
3040         if (draw_flags & DRAW_FACE_SELECT) {
3041                 draw_wire = OBDRAW_WIRE_OFF;
3042         }
3043         else if (ob->dtx & OB_DRAWWIRE) {
3044                 draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3045         }
3046         
3047         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3048         totedge = dm->getNumEdges(dm);
3049         totface = dm->getNumTessFaces(dm);
3050         
3051         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3052         glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
3053
3054         if (dt == OB_BOUNDBOX) {
3055                 if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
3056                         draw_bounding_volume(scene, ob, ob->boundtype);
3057         }
3058         else if (hasHaloMat || (totface == 0 && totedge == 0)) {
3059                 glPointSize(1.5);
3060                 dm->drawVerts(dm);
3061                 glPointSize(1.0);
3062         }
3063         else if (dt == OB_WIRE || totface == 0) {
3064                 draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff &