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