Fix #33530: Blender Crash when selecting "Point select mode" in Particle Mode with...
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_camera_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_constraint_types.h"  /* for drawing constraint */
35 #include "DNA_lamp_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_smoke_types.h"
42 #include "DNA_world_types.h"
43 #include "DNA_object_types.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47
48 #include "BKE_anim.h"  /* for the where_on_path function */
49 #include "BKE_armature.h"
50 #include "BKE_camera.h"
51 #include "BKE_constraint.h"  /* for the get_constraint_target function */
52 #include "BKE_curve.h"
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_deform.h"
55 #include "BKE_displist.h"
56 #include "BKE_font.h"
57 #include "BKE_global.h"
58 #include "BKE_image.h"
59 #include "BKE_key.h"
60 #include "BKE_lattice.h"
61 #include "BKE_mesh.h"
62 #include "BKE_material.h"
63 #include "BKE_mball.h"
64 #include "BKE_modifier.h"
65 #include "BKE_object.h"
66 #include "BKE_paint.h"
67 #include "BKE_particle.h"
68 #include "BKE_pointcache.h"
69 #include "BKE_scene.h"
70 #include "BKE_unit.h"
71 #include "BKE_tracking.h"
72
73 #include "BKE_tessmesh.h"
74
75 #include "IMB_imbuf.h"
76 #include "IMB_imbuf_types.h"
77
78 #include "BIF_gl.h"
79 #include "BIF_glutil.h"
80
81 #include "GPU_draw.h"
82 #include "GPU_extensions.h"
83
84 #include "ED_mesh.h"
85 #include "ED_particle.h"
86 #include "ED_screen.h"
87 #include "ED_sculpt.h"
88 #include "ED_types.h"
89
90 #include "UI_resources.h"
91
92 #include "WM_api.h"
93 #include "BLF_api.h"
94
95 #include "view3d_intern.h"  /* bad level include */
96
97 typedef enum eWireDrawMode {
98         OBDRAW_WIRE_OFF = 0,
99         OBDRAW_WIRE_ON = 1,
100         OBDRAW_WIRE_ON_DEPTH = 2
101 } eWireDrawMode;
102
103 typedef struct drawDMVerts_userData {
104         BMEditMesh *em; /* BMESH BRANCH ONLY */
105
106         int sel;
107         BMVert *eve_act;
108
109         /* cached theme values */
110         unsigned char th_editmesh_active[4];
111         unsigned char th_vertex_select[4];
112         unsigned char th_vertex[4];
113         unsigned char th_skin_root[4];
114         float th_vertex_size;
115
116         /* for skin node drawing */
117         int has_vskin;
118         float imat[4][4];
119 } drawDMVerts_userData;
120
121 typedef struct drawDMEdgesSel_userData {
122         BMEditMesh *em; /* BMESH BRANCH ONLY */
123
124         unsigned char *baseCol, *selCol, *actCol;
125         BMEdge *eed_act;
126 } drawDMEdgesSel_userData;
127
128 typedef struct drawDMFacesSel_userData {
129         unsigned char *cols[3];
130
131         DerivedMesh *dm; /* BMESH BRANCH ONLY */
132         BMEditMesh *em;  /* BMESH BRANCH ONLY */
133
134         BMFace *efa_act;
135         int *orig_index_mf_to_mpoly;
136         int *orig_index_mp_to_orig;
137 } drawDMFacesSel_userData;
138
139 typedef struct drawDMNormal_userData {
140         BMEditMesh *em;
141         int uniform_scale;
142         float normalsize;
143         float tmat[3][3];
144         float imat[3][3];
145 } drawDMNormal_userData;
146
147 typedef struct bbsObmodeMeshVerts_userData {
148         void *offset;
149         MVert *mvert;
150 } bbsObmodeMeshVerts_userData;
151
152 static void draw_bounding_volume(Scene *scene, Object *ob, char type);
153
154 static void drawcube_size(float size);
155 static void drawcircle_size(float size);
156 static void draw_empty_sphere(float size);
157 static void draw_empty_cone(float size);
158
159 static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
160 {
161         float col_wire[3], col_bg[3], col[3];
162
163         rgb_uchar_to_float(col_wire, ob_wire_col);
164
165         UI_GetThemeColor3fv(theme_id, col_bg);
166         interp_v3_v3v3(col, col_bg, col_wire, fac);
167         glColor3fv(col);
168 }
169
170 /* this condition has been made more complex since editmode can draw textures */
171 static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
172 {
173         /* texture and material draw modes */
174         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID)
175                 return TRUE;
176
177         /* textured solid */
178         if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene))
179                 return TRUE;
180         
181         return FALSE;
182 }
183
184 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
185 {
186         if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
187                 return 0;
188
189         if (G.f & G_BACKBUFSEL)
190                 return 0;
191
192         if ((vd->flag & V3D_ZBUF_SELECT) == 0)
193                 return 1;
194
195         /* if its drawing textures with zbuf sel, then don't draw dots */
196         if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
197                 return 0;
198
199         if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
200                 return 0;
201
202         return 1;
203 }
204
205 /* ************************ */
206
207 /* check for glsl drawing */
208
209 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt)
210 {
211         if (!GPU_glsl_support())
212                 return 0;
213         if (G.f & G_PICKSEL)
214                 return 0;
215         if (!check_object_draw_texture(scene, v3d, dt))
216                 return 0;
217         if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
218                 return 0;
219         if (BKE_scene_use_new_shading_nodes(scene))
220                 return 0;
221         
222         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
223 }
224
225 static int check_alpha_pass(Base *base)
226 {
227         if (base->flag & OB_FROMDUPLI)
228                 return 0;
229
230         if (G.f & G_PICKSEL)
231                 return 0;
232
233         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_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         }
1290         else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
1291                 
1292                 /* draw the line from the circle along the dist */
1293                 glBegin(GL_LINE_STRIP);
1294                 vec[2] = -circrad;
1295                 glVertex3fv(vec);
1296                 vec[2] = -la->dist;
1297                 glVertex3fv(vec);
1298                 glEnd();
1299                 
1300                 if (la->type == LA_HEMI) {
1301                         /* draw the hemisphere curves */
1302                         short axis, steps, dir;
1303                         float outdist, zdist, mul;
1304                         zero_v3(vec);
1305                         outdist = 0.14; mul = 1.4; dir = 1;
1306                         
1307                         setlinestyle(4);
1308                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1309                         for (axis = 0; axis < 4; axis++) {
1310                                 float v[3] = {0.0, 0.0, 0.0};
1311                                 zdist = 0.02;
1312                                 
1313                                 glBegin(GL_LINE_STRIP);
1314                                 
1315                                 for (steps = 0; steps < 6; steps++) {
1316                                         if (axis == 0 || axis == 1) {       /* x axis up, x axis down */
1317                                                 /* make the arcs start at the edge of the energy circle */
1318                                                 if (steps == 0) v[0] = dir * circrad;
1319                                                 else v[0] = v[0] + dir * (steps * outdist);
1320                                         }
1321                                         else if (axis == 2 || axis == 3) {      /* y axis up, y axis down */
1322                                                 /* make the arcs start at the edge of the energy circle */
1323                                                 v[1] = (steps == 0) ? (dir * circrad) : (v[1] + dir * (steps * outdist));
1324                                         }
1325
1326                                         v[2] = v[2] - steps * zdist;
1327                                         
1328                                         glVertex3fv(v);
1329                                         
1330                                         zdist = zdist * mul;
1331                                 }
1332                                 
1333                                 glEnd();
1334                                 /* flip the direction */
1335                                 dir = -dir;
1336                         }
1337                 }
1338         }
1339         else if (la->type == LA_AREA) {
1340                 setlinestyle(3);
1341                 if (la->area_shape == LA_AREA_SQUARE)
1342                         fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
1343                 else if (la->area_shape == LA_AREA_RECT)
1344                         fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
1345
1346                 glBegin(GL_LINE_STRIP);
1347                 glVertex3f(0.0, 0.0, -circrad);
1348                 glVertex3f(0.0, 0.0, -la->dist);
1349                 glEnd();
1350         }
1351         
1352         /* and back to viewspace */
1353         glLoadMatrixf(rv3d->viewmat);
1354         copy_v3_v3(vec, ob->obmat[3]);
1355
1356         setlinestyle(0);
1357         
1358         if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1359                 drawshadbuflimits(la, ob->obmat);
1360         }
1361         
1362         UI_GetThemeColor4ubv(TH_LAMP, col);
1363         glColor4ubv(col);
1364
1365         glEnable(GL_BLEND);
1366         
1367         if (vec[2] > 0) vec[2] -= circrad;
1368         else vec[2] += circrad;
1369         
1370         glBegin(GL_LINE_STRIP);
1371         glVertex3fv(vec);
1372         vec[2] = 0;
1373         glVertex3fv(vec);
1374         glEnd();
1375         
1376         glPointSize(2.0);
1377         glBegin(GL_POINTS);
1378         glVertex3fv(vec);
1379         glEnd();
1380         glPointSize(1.0);
1381         
1382         glDisable(GL_BLEND);
1383         
1384         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1385                 /* restore for drawing extra stuff */
1386                 glColor3ubv(ob_wire_col);
1387         }
1388 }
1389
1390 static void draw_limit_line(float sta, float end, unsigned int col)
1391 {
1392         glBegin(GL_LINES);
1393         glVertex3f(0.0, 0.0, -sta);
1394         glVertex3f(0.0, 0.0, -end);
1395         glEnd();
1396
1397         glPointSize(3.0);
1398         glBegin(GL_POINTS);
1399         cpack(col);
1400         glVertex3f(0.0, 0.0, -sta);
1401         glVertex3f(0.0, 0.0, -end);
1402         glEnd();
1403         glPointSize(1.0);
1404 }
1405
1406
1407 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1408 /* qdn: now also enabled for Blender to set focus point for defocus composite node */
1409 static void draw_focus_cross(float dist, float size)
1410 {
1411         glBegin(GL_LINES);
1412         glVertex3f(-size, 0.f, -dist);
1413         glVertex3f(size, 0.f, -dist);
1414         glVertex3f(0.f, -size, -dist);
1415         glVertex3f(0.f, size, -dist);
1416         glEnd();
1417 }
1418
1419 #ifdef VIEW3D_CAMERA_BORDER_HACK
1420 unsigned char view3d_camera_border_hack_col[3];
1421 short view3d_camera_border_hack_test = FALSE;
1422 #endif
1423
1424 /* ****************** draw clip data *************** */
1425
1426 static void draw_bundle_sphere(void)
1427 {
1428         static GLuint displist = 0;
1429
1430         if (displist == 0) {
1431                 GLUquadricObj *qobj;
1432
1433                 displist = glGenLists(1);
1434                 glNewList(displist, GL_COMPILE);
1435
1436                 qobj = gluNewQuadric();
1437                 gluQuadricDrawStyle(qobj, GLU_FILL);
1438                 glShadeModel(GL_SMOOTH);
1439                 gluSphere(qobj, 0.05, 8, 8);
1440                 glShadeModel(GL_FLAT);
1441                 gluDeleteQuadric(qobj);
1442
1443                 glEndList();
1444         }
1445
1446         glCallList(displist);
1447 }
1448
1449 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1450                                                 MovieClip *clip, MovieTrackingObject *tracking_object,
1451                                                 const short dflag, const unsigned char ob_wire_col[4],
1452                                                 int *global_track_index, int draw_selected)
1453 {
1454         MovieTracking *tracking = &clip->tracking;
1455         MovieTrackingTrack *track;
1456         float mat[4][4], imat[4][4];
1457         unsigned char col_unsel[4], col_sel[4];
1458         int tracknr = *global_track_index;
1459         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
1460
1461         UI_GetThemeColor4ubv(TH_TEXT, col_unsel);
1462         UI_GetThemeColor4ubv(TH_SELECT, col_sel);
1463
1464         BKE_tracking_get_camera_object_matrix(scene, base->object, mat);
1465
1466         glPushMatrix();
1467
1468         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1469                 /* current ogl matrix is translated in camera space, bundles should
1470                  * be rendered in world space, so camera matrix should be "removed"
1471                  * from current ogl matrix */
1472                 invert_m4_m4(imat, base->object->obmat);
1473
1474                 glMultMatrixf(imat);
1475                 glMultMatrixf(mat);
1476         }
1477         else {
1478                 float obmat[4][4];
1479
1480                 BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, scene->r.cfra, obmat);
1481
1482                 invert_m4_m4(imat, obmat);
1483                 glMultMatrixf(imat);
1484         }
1485
1486         for (track = tracksbase->first; track; track = track->next) {
1487                 int selected = TRACK_SELECTED(track);
1488
1489                 if (draw_selected && !selected)
1490                         continue;
1491
1492                 if ((track->flag & TRACK_HAS_BUNDLE) == 0)
1493                         continue;
1494
1495                 if (dflag & DRAW_PICKING)
1496                         glLoadName(base->selcol + (tracknr << 16));
1497
1498                 glPushMatrix();
1499                 glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1500                 glScalef(v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f, v3d->bundle_size / 0.05f);
1501
1502                 if (v3d->drawtype == OB_WIRE) {
1503                         glDisable(GL_LIGHTING);
1504
1505                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1506                                 if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
1507                                         glColor3ubv(ob_wire_col);
1508                                 }
1509                                 else {
1510                                         glColor3fv(track->color);
1511                                 }
1512                         }
1513
1514                         drawaxes(0.05f, v3d->bundle_drawtype);
1515
1516                         glEnable(GL_LIGHTING);
1517                 }
1518                 else if (v3d->drawtype > OB_WIRE) {
1519                         if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
1520                                 /* selection outline */
1521                                 if (selected) {
1522                                         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1523                                                 glColor3ubv(ob_wire_col);
1524                                         }
1525
1526                                         glLineWidth(2.f);
1527                                         glDisable(GL_LIGHTING);
1528                                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1529
1530                                         draw_bundle_sphere();
1531
1532                                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1533                                         glEnable(GL_LIGHTING);
1534                                         glLineWidth(1.f);
1535                                 }
1536
1537                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1538                                         if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1539                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1540                                 }
1541
1542                                 draw_bundle_sphere();
1543                         }
1544                         else {
1545                                 glDisable(GL_LIGHTING);
1546
1547                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1548                                         if (selected) {
1549                                                 glColor3ubv(ob_wire_col);
1550                                         }
1551                                         else {
1552                                                 if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1553                                                 else UI_ThemeColor(TH_WIRE);
1554                                         }
1555                                 }
1556
1557                                 drawaxes(0.05f, v3d->bundle_drawtype);
1558
1559                                 glEnable(GL_LIGHTING);
1560                         }
1561                 }
1562
1563                 glPopMatrix();
1564
1565                 if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
1566                         float pos[3];
1567
1568                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1569                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, selected ? col_sel : col_unsel);
1570                 }
1571
1572                 tracknr++;
1573         }
1574
1575         if ((dflag & DRAW_PICKING) == 0) {
1576                 if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA)) {
1577                         MovieTrackingReconstruction *reconstruction;
1578                         reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
1579
1580                         if (reconstruction->camnr) {
1581                                 MovieReconstructedCamera *camera = reconstruction->cameras;
1582                                 int a = 0;
1583
1584                                 glDisable(GL_LIGHTING);
1585                                 UI_ThemeColor(TH_CAMERA_PATH);
1586                                 glLineWidth(2.0f);
1587
1588                                 glBegin(GL_LINE_STRIP);
1589                                 for (a = 0; a < reconstruction->camnr; a++, camera++) {
1590                                         glVertex3fv(camera->mat[3]);
1591                                 }
1592                                 glEnd();
1593
1594                                 glLineWidth(1.0f);
1595                                 glEnable(GL_LIGHTING);
1596                         }
1597                 }
1598         }
1599
1600         glPopMatrix();
1601
1602         *global_track_index = tracknr;
1603 }
1604
1605 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
1606                                          const short dflag, const unsigned char ob_wire_col[4],
1607                                          int draw_selected)
1608 {
1609         MovieTracking *tracking = &clip->tracking;
1610         MovieTrackingObject *tracking_object;
1611         int global_track_index = 1;
1612
1613         if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0)
1614                 return;
1615
1616         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1617                 return;
1618
1619         glEnable(GL_LIGHTING);
1620         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1621         glEnable(GL_COLOR_MATERIAL);
1622         glShadeModel(GL_SMOOTH);
1623
1624         tracking_object = tracking->objects.first;
1625         while (tracking_object) {
1626                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1627                                                     dflag, ob_wire_col, &global_track_index, draw_selected);
1628
1629                 tracking_object = tracking_object->next;
1630         }
1631
1632         /* restore */
1633         glShadeModel(GL_FLAT);
1634         glDisable(GL_COLOR_MATERIAL);
1635         glDisable(GL_LIGHTING);
1636
1637         if ((dflag & DRAW_CONSTCOLOR) == 0) {
1638                 glColor3ubv(ob_wire_col);
1639         }
1640
1641         if (dflag & DRAW_PICKING)
1642                 glLoadName(base->selcol);
1643 }
1644
1645 /* flag similar to draw_object() */
1646 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
1647                        const short dflag, const unsigned char ob_wire_col[4])
1648 {
1649         /* a standing up pyramid with (0,0,0) as top */
1650         Camera *cam;
1651         Object *ob = base->object;
1652         float tvec[3];
1653         float vec[4][3], asp[2], shift[2], scale[3];
1654         int i;
1655         float drawsize;
1656         const short is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
1657         MovieClip *clip = BKE_object_movieclip_get(scene, base->object, 0);
1658
1659         /* draw data for movie clip set as active for scene */
1660         if (clip) {
1661                 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, FALSE);
1662                 draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, TRUE);
1663         }
1664
1665 #ifdef VIEW3D_CAMERA_BORDER_HACK
1666         if (is_view && !(G.f & G_PICKSEL)) {
1667                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1668                         view3d_camera_border_hack_col[0] = ob_wire_col[0];
1669                         view3d_camera_border_hack_col[1] = ob_wire_col[1];
1670                         view3d_camera_border_hack_col[2] = ob_wire_col[2];
1671                 }
1672                 else {
1673                         float col[4];
1674                         glGetFloatv(GL_CURRENT_COLOR, col);
1675                         rgb_float_to_uchar(view3d_camera_border_hack_col, col);
1676                 }
1677                 view3d_camera_border_hack_test = TRUE;
1678                 return;
1679         }
1680 #endif
1681
1682         cam = ob->data;
1683
1684         scale[0] = 1.0f / len_v3(ob->obmat[0]);
1685         scale[1] = 1.0f / len_v3(ob->obmat[1]);
1686         scale[2] = 1.0f / len_v3(ob->obmat[2]);
1687
1688         BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1689                                  asp, shift, &drawsize, vec);
1690
1691         glDisable(GL_LIGHTING);
1692         glDisable(GL_CULL_FACE);
1693
1694         /* camera frame */
1695         glBegin(GL_LINE_LOOP);
1696         glVertex3fv(vec[0]);
1697         glVertex3fv(vec[1]);
1698         glVertex3fv(vec[2]);
1699         glVertex3fv(vec[3]);
1700         glEnd();
1701
1702         if (is_view)
1703                 return;
1704
1705         zero_v3(tvec);
1706
1707         /* center point to camera frame */
1708         glBegin(GL_LINE_STRIP);
1709         glVertex3fv(vec[1]);
1710         glVertex3fv(tvec);
1711         glVertex3fv(vec[0]);
1712         glVertex3fv(vec[3]);
1713         glVertex3fv(tvec);
1714         glVertex3fv(vec[2]);
1715         glEnd();
1716
1717
1718         /* arrow on top */
1719         tvec[2] = vec[1][2]; /* copy the depth */
1720
1721
1722         /* draw an outline arrow for inactive cameras and filled
1723          * for active cameras. We actually draw both outline+filled
1724          * for active cameras so the wire can be seen side-on */
1725         for (i = 0; i < 2; i++) {
1726                 if (i == 0) glBegin(GL_LINE_LOOP);
1727                 else if (i == 1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1728                 else break;
1729
1730                 tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
1731                 tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1732                 glVertex3fv(tvec); /* left */
1733                 
1734                 tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
1735                 glVertex3fv(tvec); /* right */
1736                 
1737                 tvec[0] = shift[0];
1738                 tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1739                 glVertex3fv(tvec); /* top */
1740
1741                 glEnd();
1742         }
1743
1744         if (dflag == 0) {
1745                 if (cam->flag & (CAM_SHOWLIMITS + CAM_SHOWMIST)) {
1746                         float nobmat[4][4];
1747                         World *wrld;
1748
1749                         /* draw in normalized object matrix space */
1750                         copy_m4_m4(nobmat, ob->obmat);
1751                         normalize_m4(nobmat);
1752
1753                         glPushMatrix();
1754                         glLoadMatrixf(rv3d->viewmat);
1755                         glMultMatrixf(nobmat);
1756
1757                         if (cam->flag & CAM_SHOWLIMITS) {
1758                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1759                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
1760                                 draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
1761                         }
1762
1763                         wrld = scene->world;
1764                         if (cam->flag & CAM_SHOWMIST)
1765                                 if (wrld) draw_limit_line(wrld->miststa, wrld->miststa + wrld->mistdist, 0xFFFFFF);
1766
1767                         glPopMatrix();
1768                 }
1769         }
1770 }
1771
1772 /* flag similar to draw_object() */
1773 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1774                         Object *UNUSED(ob), int UNUSED(flag))
1775 {
1776         //Speaker *spk = ob->data;
1777
1778         float vec[3];
1779         int i, j;
1780
1781         glEnable(GL_BLEND);
1782
1783         for (j = 0; j < 3; j++) {
1784                 vec[2] = 0.25f * j - 0.125f;
1785
1786                 glBegin(GL_LINE_LOOP);
1787                 for (i = 0; i < 16; i++) {
1788                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1789                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1790                         glVertex3fv(vec);
1791                 }
1792                 glEnd();
1793         }
1794
1795         for (j = 0; j < 4; j++) {
1796                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1797                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1798                 glBegin(GL_LINE_STRIP);
1799                 for (i = 0; i < 3; i++) {
1800                         if (i == 1) {
1801                                 vec[0] *= 0.5f;
1802                                 vec[1] *= 0.5f;
1803                         }
1804
1805                         vec[2] = 0.25f * i - 0.125f;
1806                         glVertex3fv(vec);
1807                 }
1808                 glEnd();
1809         }
1810
1811         glDisable(GL_BLEND);
1812 }
1813
1814 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1815 {
1816         BPoint *bp = lt->def;
1817         float *co = dl ? dl->verts : NULL;
1818         int u, v, w;
1819
1820         UI_ThemeColor(sel ? TH_VERTEX_SELECT : TH_VERTEX);
1821         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1822         bglBegin(GL_POINTS);
1823
1824         for (w = 0; w < lt->pntsw; w++) {
1825                 int wxt = (w == 0 || w == lt->pntsw - 1);
1826                 for (v = 0; v < lt->pntsv; v++) {
1827                         int vxt = (v == 0 || v == lt->pntsv - 1);
1828                         for (u = 0; u < lt->pntsu; u++, bp++, co += 3) {
1829                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1830                                 if (!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1831                                         if (bp->hide == 0) {
1832                                                 if ((bp->f1 & SELECT) == sel) {
1833                                                         bglVertex3fv(dl ? co : bp->vec);
1834                                                 }
1835                                         }
1836                                 }
1837                         }
1838                 }
1839         }
1840         
1841         glPointSize(1.0);
1842         bglEnd();
1843 }
1844
1845 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1846 {
1847         int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
1848
1849         if (use_wcol) {
1850                 float col[3];
1851                 MDeformWeight *mdw = defvert_find_index(lt->dvert + index, use_wcol - 1);
1852                 
1853                 weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
1854                 glColor3fv(col);
1855
1856         }
1857         
1858         if (dl) {
1859                 glVertex3fv(&dl->verts[index * 3]);
1860         }
1861         else {
1862                 glVertex3fv(lt->def[index].vec);
1863         }
1864 }
1865
1866 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1867 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1868 {
1869         Lattice *lt = ob->data;
1870         DispList *dl;
1871         int u, v, w;
1872         int use_wcol = FALSE, is_edit = (lt->editlatt != NULL);
1873
1874         /* now we default make displist, this will modifiers work for non animated case */
1875         if (ob->disp.first == NULL)
1876                 BKE_lattice_modifiers_calc(scene, ob);
1877         dl = BKE_displist_find(&ob->disp, DL_VERTS);
1878         
1879         if (is_edit) {
1880                 lt = lt->editlatt->latt;
1881
1882                 cpack(0x004000);
1883                 
1884                 if (ob->defbase.first && lt->dvert) {
1885                         use_wcol = ob->actdef;
1886                         glShadeModel(GL_SMOOTH);
1887                 }
1888         }
1889         
1890         glBegin(GL_LINES);
1891         for (w = 0; w < lt->pntsw; w++) {
1892                 int wxt = (w == 0 || w == lt->pntsw - 1);
1893                 for (v = 0; v < lt->pntsv; v++) {
1894                         int vxt = (v == 0 || v == lt->pntsv - 1);
1895                         for (u = 0; u < lt->pntsu; u++) {
1896                                 int uxt = (u == 0 || u == lt->pntsu - 1);
1897
1898                                 if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1899                                         drawlattice__point(lt, dl, u, v, w - 1, use_wcol);
1900                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1901                                 }
1902                                 if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1903                                         drawlattice__point(lt, dl, u, v - 1, w, use_wcol);
1904                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1905                                 }
1906                                 if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1907                                         drawlattice__point(lt, dl, u - 1, v, w, use_wcol);
1908                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1909                                 }
1910                         }
1911                 }
1912         }
1913         glEnd();
1914         
1915         /* restoration for weight colors */
1916         if (use_wcol)
1917                 glShadeModel(GL_FLAT);
1918
1919         if (is_edit) {
1920                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1921                 
1922                 lattice_draw_verts(lt, dl, 0);
1923                 lattice_draw_verts(lt, dl, 1);
1924                 
1925                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1926         }
1927 }
1928
1929 /* ***************** ******************** */
1930
1931 /*  draw callback */
1932 static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
1933                                           const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
1934 {
1935         MVert *mv = &((MVert *)userData)[index];
1936
1937         if (!(mv->flag & ME_HIDE)) {
1938                 const char sel = mv->flag & SELECT;
1939
1940                 /* TODO define selected color */
1941                 if (sel) {
1942                         glColor3f(1.0f, 1.0f, 0.0f);
1943                 }
1944                 else {
1945                         glColor3f(0.0f, 0.0f, 0.0f);
1946                 }
1947
1948                 glVertex3fv(co);
1949         }
1950 }
1951
1952 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
1953 {
1954         glBegin(GL_POINTS);
1955         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
1956         glEnd();
1957 }
1958
1959 /* ************** DRAW MESH ****************** */
1960
1961 /* First section is all the "simple" draw routines,
1962  * ones that just pass some sort of primitive to GL,
1963  * with perhaps various options to control lighting,
1964  * color, etc.
1965  *
1966  * These routines should not have user interface related
1967  * logic!!!
1968  */
1969
1970 static void calcDrawDMNormalScale(Object *ob, drawDMNormal_userData *data)
1971 {
1972         float obmat[3][3];
1973
1974         copy_m3_m4(obmat, ob->obmat);
1975
1976         data->uniform_scale = is_uniform_scaled_m3(obmat);
1977
1978         if (!data->uniform_scale) {
1979                 /* inverted matrix */
1980                 invert_m3_m3(data->imat, obmat);
1981
1982                 /* transposed inverted matrix */
1983                 copy_m3_m3(data->tmat, data->imat);
1984                 transpose_m3(data->tmat);
1985         }
1986 }
1987
1988 static void draw_dm_face_normals__mapFunc(void *userData, int index, const float cent[3], const float no[3])
1989 {
1990         drawDMNormal_userData *data = userData;
1991         BMFace *efa = EDBM_face_at_index(data->em, index);
1992         float n[3];
1993
1994         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
1995                 if (!data->uniform_scale) {
1996                         mul_v3_m3v3(n, data->tmat, (float *) no);
1997                         normalize_v3(n);
1998                         mul_m3_v3(data->imat, n);
1999                 }
2000                 else {
2001                         copy_v3_v3(n, no);
2002                 }
2003
2004                 glVertex3fv(cent);
2005                 glVertex3f(cent[0] + n[0] * data->normalsize,
2006                            cent[1] + n[1] * data->normalsize,
2007                            cent[2] + n[2] * data->normalsize);
2008         }
2009 }
2010
2011 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2012 {
2013         drawDMNormal_userData data;
2014
2015         data.em = em;
2016         data.normalsize = scene->toolsettings->normalsize;
2017
2018         calcDrawDMNormalScale(ob, &data);
2019
2020         glBegin(GL_LINES);
2021         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data);
2022         glEnd();
2023 }
2024
2025 static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
2026 {
2027         BMFace *efa = EDBM_face_at_index(((void **)userData)[0], index);
2028         int sel = *(((int **)userData)[1]);
2029         
2030         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT) == sel) {
2031                 bglVertex3fv(cent);
2032         }
2033 }
2034 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2035 {
2036         void *ptrs[2] = {em, &sel};
2037
2038         bglBegin(GL_POINTS);
2039         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2040         bglEnd();
2041 }
2042
2043 static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
2044 {
2045         drawDMNormal_userData *data = userData;
2046         BMVert *eve = EDBM_vert_at_index(data->em, index);
2047
2048         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
2049                 float no[3], n[3];
2050
2051                 if (no_f) {
2052                         copy_v3_v3(no, no_f);
2053                 }
2054                 else {
2055                         no[0] = no_s[0] / 32767.0f;
2056                         no[1] = no_s[1] / 32767.0f;
2057                         no[2] = no_s[2] / 32767.0f;
2058                 }
2059
2060                 if (!data->uniform_scale) {
2061                         mul_v3_m3v3(n, data->tmat, (float *) no);
2062                         normalize_v3(n);
2063                         mul_m3_v3(data->imat, n);
2064                 }
2065                 else {
2066                         copy_v3_v3(n, no);
2067                 }
2068
2069                 glVertex3fv(co);
2070                 glVertex3f(co[0] + n[0] * data->normalsize,
2071                            co[1] + n[1] * data->normalsize,
2072                            co[2] + n[2] * data->normalsize);
2073         }
2074 }
2075
2076 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
2077 {
2078         drawDMNormal_userData data;
2079
2080         data.em = em;
2081         data.normalsize = scene->toolsettings->normalsize;
2082
2083         calcDrawDMNormalScale(ob, &data);
2084
2085         glBegin(GL_LINES);
2086         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data);
2087         glEnd();
2088 }
2089
2090 /* Draw verts with color set based on selection */
2091 static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
2092                                    const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2093 {
2094         drawDMVerts_userData *data = userData;
2095         BMVert *eve = EDBM_vert_at_index(data->em, index);
2096
2097         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
2098                 /* skin nodes: draw a red circle around the root
2099                  * node(s) */
2100                 if (data->has_vskin) {
2101                         const MVertSkin *vs = CustomData_bmesh_get(&data->em->bm->vdata,
2102                                                                    eve->head.data,
2103                                                                    CD_MVERT_SKIN);
2104                         if (vs->flag & MVERT_SKIN_ROOT) {
2105                                 float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
2106                                 bglEnd();
2107                         
2108                                 glColor4ubv(data->th_skin_root);
2109                                 drawcircball(GL_LINES, co, radius, data->imat);
2110
2111                                 glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2112                                 bglBegin(GL_POINTS);
2113                         }
2114                 }
2115
2116                 /* draw active larger - need to stop/start point drawing for this :/ */
2117                 if (eve == data->eve_act) {
2118                         glColor4ubv(data->th_editmesh_active);
2119                         
2120                         bglEnd();
2121                         
2122                         glPointSize(data->th_vertex_size);
2123                         bglBegin(GL_POINTS);
2124                         bglVertex3fv(co);
2125                         bglEnd();
2126
2127                         glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
2128                         glPointSize(data->th_vertex_size);
2129                         bglBegin(GL_POINTS);
2130                 }
2131                 else {
2132                         bglVertex3fv(co);
2133                 }
2134         }
2135 }
2136
2137 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act,
2138                           RegionView3D *rv3d)
2139 {
2140         drawDMVerts_userData data;
2141         data.sel = sel;
2142         data.eve_act = eve_act;
2143         data.em = em;
2144
2145         /* Cache theme values */
2146         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
2147         UI_GetThemeColor4ubv(TH_VERTEX_SELECT, data.th_vertex_select);
2148         UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
2149         UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
2150         data.th_vertex_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2151
2152         /* For skin root drawing */
2153         data.has_vskin = CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN);
2154         /* view-aligned matrix */
2155         mult_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
2156         invert_m4(data.imat);
2157
2158         bglBegin(GL_POINTS);
2159         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2160         bglEnd();
2161 }
2162
2163 /* Draw edges with color set based on selection */
2164 static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2165 {
2166         BMEdge *eed;
2167         //unsigned char **cols = userData, *col;
2168         drawDMEdgesSel_userData *data = userData;
2169         unsigned char *col;
2170
2171         eed = EDBM_edge_at_index(data->em, index);
2172
2173         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
2174                 if (eed == data->eed_act) {
2175                         glColor4ubv(data->actCol);
2176                 }
2177                 else {
2178                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2179                                 col = data->selCol;
2180                         }
2181                         else {
2182                                 col = data->baseCol;
2183                         }
2184                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2185                         if (col[3] == 0)
2186                                 return DM_DRAW_OPTION_SKIP;
2187                         
2188                         glColor4ubv(col);
2189                 }
2190                 return DM_DRAW_OPTION_NORMAL;
2191         }
2192         else {
2193                 return DM_DRAW_OPTION_SKIP;
2194         }
2195 }
2196 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2197                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
2198 {
2199         drawDMEdgesSel_userData data;
2200         
2201         data.baseCol = baseCol;
2202         data.selCol = selCol;
2203         data.actCol = actCol;
2204         data.em = em;
2205         data.eed_act = eed_act;
2206         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2207 }
2208
2209 /* Draw edges */
2210 static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index)
2211 {
2212         if (BM_elem_flag_test(EDBM_edge_at_index(userData, index), BM_ELEM_HIDDEN))
2213                 return DM_DRAW_OPTION_SKIP;
2214         else
2215                 return DM_DRAW_OPTION_NORMAL;
2216 }
2217
2218 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
2219 {
2220         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2221 }
2222
2223 /* Draw edges with color interpolated based on selection */
2224 static DMDrawOption draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2225 {
2226         if (BM_elem_flag_test(EDBM_edge_at_index(((void **)userData)[0], index), BM_ELEM_HIDDEN))
2227                 return DM_DRAW_OPTION_SKIP;
2228         else
2229                 return DM_DRAW_OPTION_NORMAL;
2230 }
2231 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2232 {
2233         BMEdge *eed = EDBM_edge_at_index(((void **)userData)[0], index);
2234         unsigned char **cols = userData;
2235         unsigned char *col0 = cols[(BM_elem_flag_test(eed->v1, BM_ELEM_SELECT)) ? 2 : 1];
2236         unsigned char *col1 = cols[(BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) ? 2 : 1];
2237
2238         glColor4ub(col0[0] + (col1[0] - col0[0]) * t,
2239                    col0[1] + (col1[1] - col0[1]) * t,
2240                    col0[2] + (col1[2] - col0[2]) * t,
2241                    col0[3] + (col1[3] - col0[3]) * t);
2242 }
2243
2244 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2245 {
2246         void *cols[3] = {em, baseCol, selCol};
2247
2248         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2249 }
2250
2251 /* Draw only seam edges */
2252 static DMDrawOption draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2253 {
2254         BMEdge *eed = EDBM_edge_at_index(userData, index);
2255
2256         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SEAM))
2257                 return DM_DRAW_OPTION_NORMAL;
2258         else
2259                 return DM_DRAW_OPTION_SKIP;
2260 }
2261
2262 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2263 {
2264         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2265 }
2266
2267 /* Draw only sharp edges */
2268 static DMDrawOption draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2269 {
2270         BMEdge *eed = EDBM_edge_at_index(userData, index);
2271
2272         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && !BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
2273                 return DM_DRAW_OPTION_NORMAL;
2274         else
2275                 return DM_DRAW_OPTION_SKIP;
2276 }
2277
2278 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2279 {
2280         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2281 }
2282
2283
2284 /* Draw faces with color set based on selection
2285  * return 2 for the active face so it renders with stipple enabled */
2286 static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
2287 {
2288         drawDMFacesSel_userData *data = userData;
2289         BMFace *efa = EDBM_face_at_index(data->em, index);
2290         unsigned char *col;
2291         
2292         if (!efa)
2293                 return DM_DRAW_OPTION_SKIP;
2294         
2295         if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2296                 if (efa == data->efa_act) {
2297                         glColor4ubv(data->cols[2]);
2298                         return DM_DRAW_OPTION_STIPPLE;
2299                 }
2300                 else {
2301                         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2302                         if (col[3] == 0)
2303                                 return DM_DRAW_OPTION_SKIP;
2304                         glColor4ubv(col);
2305                         return DM_DRAW_OPTION_NORMAL;
2306                 }
2307         }
2308         return DM_DRAW_OPTION_SKIP;
2309 }
2310
2311 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2312 {
2313
2314         drawDMFacesSel_userData *data = userData;
2315         BMFace *efa;
2316         BMFace *next_efa;
2317
2318         unsigned char *col, *next_col;
2319
2320         if (!data->orig_index_mf_to_mpoly)
2321                 return 0;
2322
2323         efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index));
2324         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));
2325
2326         if (efa == next_efa)
2327                 return 1;
2328
2329         if (efa == data->efa_act || next_efa == data->efa_act)
2330                 return 0;
2331
2332         col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
2333         next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
2334
2335         if (col[3] == 0 || next_col[3] == 0)
2336                 return 0;
2337
2338         return col == next_col;
2339 }
2340
2341 /* also draws the active face */
2342 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
2343                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
2344 {
2345         drawDMFacesSel_userData data;
2346         data.dm = dm;
2347         data.cols[0] = baseCol;
2348         data.em = em;
2349         data.cols[1] = selCol;
2350         data.cols[2] = actCol;
2351         data.efa_act = efa_act;
2352         /* double lookup */
2353         data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
2354         data.orig_index_mp_to_orig  = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
2355         if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == FALSE) {
2356                 data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL;
2357         }
2358
2359         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2360 }
2361
2362 static DMDrawOption draw_dm_creases__setDrawOptions(void *userData, int index)
2363 {
2364         BMEditMesh *em = userData;
2365         BMEdge *eed = EDBM_edge_at_index(userData, index);
2366         float *crease = eed ? (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2367         
2368         if (!crease)
2369                 return DM_DRAW_OPTION_SKIP;
2370         
2371         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *crease != 0.0f) {
2372                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2373                 return DM_DRAW_OPTION_NORMAL;
2374         }
2375         else {
2376                 return DM_DRAW_OPTION_SKIP;
2377         }
2378 }
2379 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2380 {
2381         glLineWidth(3.0);
2382         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2383         glLineWidth(1.0);
2384 }
2385
2386 static DMDrawOption draw_dm_bweights__setDrawOptions(void *userData, int index)
2387 {
2388         BMEditMesh *em = userData;
2389         BMEdge *eed = EDBM_edge_at_index(userData, index);
2390         float *bweight = (float *)CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2391
2392         if (!bweight)
2393                 return DM_DRAW_OPTION_SKIP;
2394         
2395         if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2396                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2397                 return DM_DRAW_OPTION_NORMAL;
2398         }
2399         else {
2400                 return DM_DRAW_OPTION_SKIP;
2401         }
2402 }
2403 static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[3],
2404                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2405 {
2406         BMEditMesh *em = userData;
2407         BMVert *eve = EDBM_vert_at_index(userData, index);
2408         float *bweight = (float *)CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2409         
2410         if (!bweight)
2411                 return;
2412         
2413         if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && *bweight != 0.0f) {
2414                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2415                 bglVertex3fv(co);
2416         }
2417 }
2418 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2419 {
2420         ToolSettings *ts = scene->toolsettings;
2421
2422         if (ts->selectmode & SCE_SELECT_VERTEX) {
2423                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2424                 bglBegin(GL_POINTS);
2425                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2426                 bglEnd();
2427         }
2428         else {
2429                 glLineWidth(3.0);
2430                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2431                 glLineWidth(1.0);
2432         }
2433 }
2434
2435 /* Second section of routines: Combine first sets to form fancy
2436  * drawing routines (for example rendering twice to get overlays).
2437  *
2438  * Also includes routines that are basic drawing but are too
2439  * specialized to be split out (like drawing creases or measurements).
2440  */
2441
2442 /* EditMesh drawing routines*/
2443
2444 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2445                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act,
2446                                 RegionView3D *rv3d)
2447 {
2448         ToolSettings *ts = scene->toolsettings;
2449         int sel;
2450
2451         if (v3d->zbuf) glDepthMask(0);  /* disable write in zbuffer, zbuf select */
2452
2453         for (sel = 0; sel < 2; sel++) {
2454                 unsigned char col[4], fcol[4];
2455                 int pass;
2456
2457                 UI_GetThemeColor3ubv(sel ? TH_VERTEX_SELECT : TH_VERTEX, col);
2458                 UI_GetThemeColor3ubv(sel ? TH_FACE_DOT : TH_WIRE, fcol);
2459
2460                 for (pass = 0; pass < 2; pass++) {
2461                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2462                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2463
2464                         if (pass == 0) {
2465                                 if (v3d->zbuf && !(v3d->flag & V3D_ZBUF_SELECT)) {
2466                                         glDisable(GL_DEPTH_TEST);
2467
2468                                         glEnable(GL_BLEND);
2469                                 }
2470                                 else {
2471                                         continue;
2472                                 }
2473
2474                                 size = (size > 2.1f ? size / 2.0f : size);
2475                                 fsize = (fsize > 2.1f ? fsize / 2.0f : fsize);
2476                                 col[3] = fcol[3] = 100;
2477                         }
2478                         else {
2479                                 col[3] = fcol[3] = 255;
2480                         }
2481
2482                         if (ts->selectmode & SCE_SELECT_VERTEX) {
2483                                 glPointSize(size);
2484                                 glColor4ubv(col);
2485                                 draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
2486                         }
2487                         
2488                         if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2489                                 glPointSize(fsize);
2490                                 glColor4ubv(fcol);
2491                                 draw_dm_face_centers(em, cageDM, sel);
2492                         }
2493                         
2494                         if (pass == 0) {
2495                                 glDisable(GL_BLEND);
2496                                 glEnable(GL_DEPTH_TEST);
2497                         }
2498                 }
2499         }
2500
2501         if (v3d->zbuf) glDepthMask(1);
2502         glPointSize(1.0);
2503 }
2504
2505 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
2506                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2507                                 BMEdge *eed_act)
2508 {
2509         ToolSettings *ts = scene->toolsettings;
2510         int pass;
2511         unsigned char wireCol[4], selCol[4], actCol[4];
2512
2513         /* since this function does transparent... */
2514         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2515         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2516         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2517         
2518         /* when sel only is used, don't render wire, only selected, this is used for
2519          * textured draw mode when the 'edges' option is disabled */
2520         if (sel_only)
2521                 wireCol[3] = 0;
2522
2523         for (pass = 0; pass < 2; pass++) {
2524                 /* show wires in transparent when no zbuf clipping for select */
2525                 if (pass == 0) {
2526                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT) == 0) {
2527                                 glEnable(GL_BLEND);
2528                                 glDisable(GL_DEPTH_TEST);
2529                                 selCol[3] = 85;
2530                                 if (!sel_only) wireCol[3] = 85;
2531                         }
2532                         else {
2533                                 continue;
2534                         }
2535                 }
2536                 else {
2537                         selCol[3] = 255;
2538                         if (!sel_only) wireCol[3] = 255;
2539                 }
2540
2541                 if (ts->selectmode == SCE_SELECT_FACE) {
2542                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2543                 }
2544                 else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) {
2545                         if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2546                                 glShadeModel(GL_SMOOTH);
2547                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2548                                 glShadeModel(GL_FLAT);
2549                         }
2550                         else {
2551                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2552                         }
2553                 }
2554                 else {
2555                         if (!sel_only) {
2556                                 glColor4ubv(wireCol);
2557                                 draw_dm_edges(em, cageDM);
2558                         }
2559                 }
2560
2561                 if (pass == 0) {
2562                         glDisable(GL_BLEND);
2563                         glEnable(GL_DEPTH_TEST);
2564                 }
2565         }
2566 }
2567
2568 static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit)
2569 {
2570         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2571         Mesh *me = ob->data;
2572         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2573         char numstr[32]; /* Stores the measurement display text here */
2574         const char *conv_float; /* Use a float conversion matching the grid size */
2575         unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
2576         float area; /* area of the face */
2577         float grid = unit->system ? unit->scale_length : v3d->grid;
2578         const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
2579         const int do_global = v3d->flag & V3D_GLOBAL_STATS;
2580         const int do_moving = G.moving;
2581
2582         BMIter iter;
2583         int i;
2584
2585         /* make the precision of the display value proportionate to the gridsize */
2586
2587         if (grid < 0.01f) conv_float = "%.6g";
2588         else if (grid < 0.1f) conv_float = "%.5g";
2589         else if (grid < 1.0f) conv_float = "%.4g";
2590         else if (grid < 10.0f) conv_float = "%.3g";
2591         else conv_float = "%.2g";
2592         
2593         if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2594                 BMEdge *eed;
2595
2596                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2597
2598                 eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2599                 for (; eed; eed = BM_iter_step(&iter)) {
2600                         /* draw selected edges, or edges next to selected verts while draging */
2601                         if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
2602                             (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
2603                                            BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
2604                         {
2605
2606                                 copy_v3_v3(v1, eed->v1->co);
2607                                 copy_v3_v3(v2, eed->v2->co);
2608
2609                                 mid_v3_v3v3(vmid, v1, v2);
2610
2611                                 if (do_global) {
2612                                         mul_mat3_m4_v3(ob->obmat, v1);
2613                                         mul_mat3_m4_v3(ob->obmat, v2);
2614                                 }
2615
2616                                 if (unit->system) {
2617                                         bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
2618                                                        unit->system, B_UNIT_LENGTH, do_split, FALSE);
2619                                 }
2620                                 else {
2621                                         sprintf(numstr, conv_float, len_v3v3(v1, v2));
2622                                 }
2623
2624                                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
2625                         }
2626                 }
2627         }
2628
2629         if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2630                 /* would be nice to use BM_face_calc_area, but that is for 2d faces
2631                  * so instead add up tessellation triangle areas */
2632                 BMFace *f;
2633                 int n;
2634
2635 #define DRAW_EM_MEASURE_STATS_FACEAREA()                                      \
2636         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {                               \
2637                 mul_v3_fl(vmid, 1.0f / (float)n);                                     \
2638                 if (unit->system)                                                     \
2639                         bUnit_AsString(numstr, sizeof(numstr),                            \
2640                                        (double)(area * unit->scale_length),               \
2641                                        3, unit->system, B_UNIT_LENGTH, do_split, FALSE);  \
2642                 else                                                                  \
2643                         BLI_snprintf(numstr, sizeof(numstr), conv_float, area);           \
2644                 view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);          \
2645         } (void)0
2646
2647                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2648                 
2649                 f = NULL;
2650                 area = 0.0;
2651                 zero_v3(vmid);
2652                 n = 0;
2653                 for (i = 0; i < em->tottri; i++) {
2654                         BMLoop **l = em->looptris[i];
2655                         if (f && l[0]->f != f) {
2656                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2657                                 zero_v3(vmid);
2658                                 area = 0.0;
2659                                 n = 0;
2660                         }
2661
2662                         f = l[0]->f;
2663                         copy_v3_v3(v1, l[0]->v->co);
2664                         copy_v3_v3(v2, l[1]->v->co);
2665                         copy_v3_v3(v3, l[2]->v->co);
2666                         add_v3_v3(vmid, v1);
2667                         add_v3_v3(vmid, v2);
2668                         add_v3_v3(vmid, v3);
2669                         n += 3;
2670                         if (do_global) {
2671                                 mul_mat3_m4_v3(ob->obmat, v1);
2672                                 mul_mat3_m4_v3(ob->obmat, v2);
2673                                 mul_mat3_m4_v3(ob->obmat, v3);
2674                         }
2675                         area += area_tri_v3(v1, v2, v3);
2676                 }
2677
2678                 if (f) {
2679                         DRAW_EM_MEASURE_STATS_FACEAREA();
2680                 }
2681 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2682         }
2683
2684         if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
2685                 BMFace *efa;
2686                 int is_rad = unit->system_rotation == USER_UNIT_ROT_RADIANS;
2687
2688                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2689
2690
2691                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
2692                         const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
2693
2694                         if (is_face_sel || do_moving) {
2695                                 BMIter liter;
2696                                 BMLoop *loop;
2697                                 int is_first = TRUE;
2698
2699                                 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
2700                                         if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
2701                                                 float angle;
2702
2703                                                 /* lazy init center calc */
2704                                                 if (is_first) {
2705                                                         BM_face_calc_center_bounds(efa, vmid);
2706                                                         /* Avoid triple matrix multiply every vertex for 'global' */
2707                                                         if (do_global) {
2708                                                                 copy_v3_v3(v1, loop->prev->v->co);
2709                                                                 copy_v3_v3(v2, loop->v->co);
2710                                                                 mul_mat3_m4_v3(ob->obmat, v1);
2711                                                                 mul_mat3_m4_v3(ob->obmat, v2);
2712                                                         }
2713                                                         is_first = FALSE;
2714                                                 }
2715
2716                                                 if (do_global) {
2717                                                         copy_v3_v3(v3, loop->next->v->co);
2718
2719                                                         mul_mat3_m4_v3(ob->obmat, v3);
2720
2721                                                         angle = angle_v3v3v3(v1, v2, v3);
2722                                                         copy_v3_v3(v1, v2);
2723                                                         copy_v3_v3(v2, v3);
2724                                                 }
2725                                                 else {
2726                                                         angle = angle_v3v3v3(loop->prev->v->co, loop->v->co, loop->next->v->co);
2727                                                 }
2728
2729                                                 BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
2730                                                 interp_v3_v3v3(fvec, vmid, loop->v->co, 0.8f);
2731                                                 view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
2732                                         }
2733                                 }
2734                         }
2735                 }
2736         }
2737 }
2738
2739 static void draw_em_indices(BMEditMesh *em)
2740 {
2741         const short txt_flag = V3D_CACHE_TEXT_ASCII | V3D_CACHE_TEXT_LOCALCLIP;
2742         BMEdge *e;
2743         BMFace *f;
2744         BMVert *v;
2745         int i;
2746         char numstr[32];
2747         float pos[3];
2748         unsigned char col[4];
2749
2750         BMIter iter;
2751         BMesh *bm = em->bm;
2752
2753         /* For now, reuse appropriate theme colors from stats text colors */
2754         i = 0;
2755         if (em->selectmode & SCE_SELECT_VERTEX) {
2756                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2757                 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
2758                         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
2759                                 sprintf(numstr, "%d", i);
2760                                 view3d_cached_text_draw_add(v->co, numstr, 0, txt_flag, col);
2761                         }
2762                         i++;
2763                 }
2764         }
2765
2766         if (em->selectmode & SCE_SELECT_EDGE) {
2767                 i = 0;
2768                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2769                 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2770                         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
2771                                 sprintf(numstr, "%d", i);
2772                                 mid_v3_v3v3(pos, e->v1->co, e->v2->co);
2773                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2774                         }
2775                         i++;
2776                 }
2777         }
2778
2779         if (em->selectmode & SCE_SELECT_FACE) {
2780                 i = 0;
2781                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2782                 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
2783                         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
2784                                 BM_face_calc_center_mean(f, pos);
2785                                 sprintf(numstr, "%d", i);
2786                                 view3d_cached_text_draw_add(pos, numstr, 0, txt_flag, col);
2787                         }
2788                         i++;
2789                 }
2790         }
2791 }
2792
2793 static DMDrawOption draw_em_fancy__setFaceOpts(void *userData, int index)
2794 {
2795         BMFace *efa = EDBM_face_at_index(userData, index);
2796
2797         if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
2798                 GPU_enable_material(efa->mat_nr + 1, NULL);
2799                 return DM_DRAW_OPTION_NORMAL;
2800         }
2801         else
2802                 return DM_DRAW_OPTION_SKIP;
2803 }
2804
2805 static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2806 {
2807         BMFace *efa = EDBM_face_at_index(userData, index);
2808
2809         if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
2810                 return DM_DRAW_OPTION_SKIP;
2811         else
2812                 return DM_DRAW_OPTION_NORMAL;
2813 }
2814
2815 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2816                           Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt)
2817
2818 {
2819         Mesh *me = ob->data;
2820         BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE); /* annoying but active faces is stored differently */
2821         BMEdge *eed_act = NULL;
2822         BMVert *eve_act = NULL;
2823         
2824         if (em->bm->selected.last) {
2825                 BMEditSelection *ese = em->bm->selected.last;
2826                 /* face is handeled above */
2827 #if 0
2828                 if (ese->type == BM_FACE) {
2829                         efa_act = (BMFace *)ese->data;
2830                 }
2831                 else
2832 #endif
2833                 if (ese->htype == BM_EDGE) {
2834                         eed_act = (BMEdge *)ese->ele;
2835                 }
2836                 else if (ese->htype == BM_VERT) {
2837                         eve_act = (BMVert *)ese->ele;
2838                 }
2839         }
2840         
2841         EDBM_index_arrays_ensure(em, BM_VERT | BM_EDGE | BM_FACE);
2842
2843         if (dt > OB_WIRE) {
2844                 if (check_object_draw_texture(scene, v3d, dt)) {
2845                         if (draw_glsl_material(scene, ob, v3d, dt)) {
2846                                 glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
2847
2848                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2849                                                              draw_em_fancy__setGLSLFaceOpts, em);
2850                                 GPU_disable_material();
2851
2852                                 glFrontFace(GL_CCW);
2853                         }
2854                         else {
2855                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2856                         }
2857                 }
2858                 else {
2859                         /* 3 floats for position,
2860                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
2861                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
2862
2863                         glEnable(GL_LIGHTING);
2864                         glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
2865                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
2866
2867                         glFrontFace(GL_CCW);
2868                         glDisable(GL_LIGHTING);
2869                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
2870                 }
2871
2872                 /* Setup for drawing wire over, disable zbuffer
2873                  * write to show selected edge wires better */
2874                 UI_ThemeColor(TH_WIRE);
2875
2876                 bglPolygonOffset(rv3d->dist, 1.0);
2877                 glDepthMask(0);
2878         }
2879         else {
2880                 if (cageDM != finalDM) {
2881                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2882                         finalDM->drawEdges(finalDM, 1, 0);
2883                 }
2884         }
2885         
2886         if (me->drawflag & ME_DRAWFACES) {  /* transp faces */
2887                 unsigned char col1[4], col2[4], col3[4];
2888
2889                 UI_GetThemeColor4ubv(TH_FACE, col1);
2890                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2891                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2892
2893                 glEnable(GL_BLEND);
2894                 glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
2895
2896                 /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */
2897                 if (check_object_draw_texture(scene, v3d, dt))
2898                         col1[3] = 0;
2899
2900                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
2901
2902                 glDisable(GL_BLEND);
2903                 glDepthMask(1);  /* restore write in zbuffer */
2904         }
2905         else if (efa_act) {
2906                 /* even if draw faces is off it would be nice to draw the stipple face
2907                  * Make all other faces zero alpha except for the active
2908                  * */
2909                 unsigned char col1[4], col2[4], col3[4];
2910                 col1[3] = col2[3] = 0; /* don't draw */
2911                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2912
2913                 glEnable(GL_BLEND);
2914                 glDepthMask(0);  /* disable write in zbuffer, needed for nice transp */
2915
2916                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
2917
2918                 glDisable(GL_BLEND);
2919                 glDepthMask(1);  /* restore write in zbuffer */
2920
2921         }
2922
2923         /* here starts all fancy draw-extra over */
2924         if ((me->drawflag & ME_DRAWEDGES) == 0 && check_object_draw_texture(scene, v3d, dt)) {
2925                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, don't draw any edges */
2926                 
2927                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2928                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2929                 
2930         }
2931         else {
2932                 if (me->drawflag & ME_DRAWSEAMS) {
2933                         UI_ThemeColor(TH_EDGE_SEAM);
2934                         glLineWidth(2);
2935
2936                         draw_dm_edges_seams(em, cageDM);
2937
2938                         glColor3ub(0, 0, 0);
2939                         glLineWidth(1);
2940                 }
2941                 
2942                 if (me->drawflag & ME_DRAWSHARP) {
2943                         UI_ThemeColor(TH_EDGE_SHARP);
2944                         glLineWidth(2);
2945
2946                         draw_dm_edges_sharp(em, cageDM);
2947
2948                         glColor3ub(0, 0, 0);
2949                         glLineWidth(1);
2950                 }
2951
2952                 if (me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2953                         draw_dm_creases(em, cageDM);
2954                 }
2955                 if (me->drawflag & ME_DRAWBWEIGHTS) {
2956                         draw_dm_bweights(em, scene, cageDM);
2957                 }
2958
2959                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2960         }
2961
2962         {
2963                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d);
2964
2965                 if (me->drawflag & ME_DRAWNORMALS) {
2966                         UI_ThemeColor(TH_NORMAL);
2967                         draw_dm_face_normals(em, scene, ob, cageDM);
2968                 }
2969                 if (me->drawflag & ME_DRAW_VNORMALS) {
2970                         UI_ThemeColor(TH_VNORMAL);
2971                         draw_dm_vert_normals(em, scene, ob, cageDM);
2972                 }
2973
2974                 if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_FACEAREA | ME_DRAWEXTRA_FACEANG)) &&
2975                     !(v3d->flag2 & V3D_RENDER_OVERRIDE))
2976                 {
2977                         draw_em_measure_stats(v3d, ob, em, &scene->unit);
2978                 }
2979
2980                 if ((G.debug & G_DEBUG) && (me->drawflag & ME_DRAWEXTRA_INDICES) &&
2981                     !(v3d->flag2 & V3D_RENDER_OVERRIDE))
2982                 {
2983                         draw_em_indices(em);
2984                 }
2985         }
2986
2987         if (dt > OB_WIRE) {
2988                 glDepthMask(1);
2989                 bglPolygonOffset(rv3d->dist, 0.0);
2990                 GPU_disable_material();
2991         }
2992 }
2993
2994 /* Mesh drawing routines */
2995
2996 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2997 {
2998         if ((v3d->transp == FALSE) &&  /* not when we draw the transparent pass */
2999             (ob->mode & OB_MODE_ALL_PAINT) == FALSE) /* not when painting (its distracting) - campbell */
3000         {
3001                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
3002                 glDepthMask(0);
3003
3004                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
3005                  * drawFacesSolid() doesn't draw the transparent faces */
3006                 if (ob->dtx & OB_DRAWTRANSP) {
3007                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
3008                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3009                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3010                         GPU_disable_material();
3011                 }
3012                 else {
3013                         dm->drawEdges(dm, 0, 1);
3014                 }
3015
3016                 glLineWidth(1.0);
3017                 glDepthMask(1);
3018         }
3019 }
3020
3021 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
3022                             const short dt, const unsigned char ob_wire_col[4], const short dflag)
3023 {
3024         Object *ob = base->object;
3025         Mesh *me = ob->data;
3026         Material *ma = give_current_material(ob, 1);
3027         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3028         eWireDrawMode draw_wire = OBDRAW_WIRE_OFF;
3029         int /* totvert,*/ totedge, totface;
3030         DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
3031         const short is_obact = (ob == OBACT);
3032         int draw_flags = (is_obact && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3033
3034         if (!dm)
3035                 return;
3036
3037         /* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
3038          * Note: Last "preview-active" modifier in stack will win! */
3039         if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob))
3040                 draw_flags |= DRAW_MODIFIERS_PREVIEW;
3041
3042         /* Unwanted combination */
3043         if (draw_flags & DRAW_FACE_SELECT) {
3044                 draw_wire = OBDRAW_WIRE_OFF;
3045         }
3046         else if (ob->dtx & OB_DRAWWIRE) {
3047                 draw_wire = OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3048         }
3049         
3050         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3051         totedge = dm->getNumEdges(dm);
3052         totface = dm->getNumTessFaces(dm);
3053         
3054         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3055         glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
3056
3057         if (dt == OB_BOUNDBOX) {
3058                 if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
3059                         draw_bounding_volume(scene, ob, ob->boundtype);
3060         }
3061         else if (hasHaloMat || (totface == 0 && totedge == 0)) {
3062                 glPointSize(1.5);
3063                 dm->drawVerts(dm);
3064                 glPointSize(1.0);
3065         }
3066         else if (dt == OB_WIRE || totface == 0) {
3067                 draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff  */
3068         }
3069         else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
3070                  check_object_draw_texture(scene, v3d, dt))
3071         {
3072                 if ((v3d->flag & V3D_SELECT_OUTLINE) &&
3073                     ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
3074                     (base->flag & SELECT) &&
3075                     !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3076                     (draw_wire == OBDRAW_WIRE_OFF))
3077                 {
3078                         draw_mesh_object_outline(v3d, ob, dm);
3079                 }
3080
3081                 if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
3082                         glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
3083
3084                         dm->drawFacesGLSL(dm, GPU_enable_material);
3085 //                      if (BKE_bproperty_object_get(ob, "Text"))
3086 // XXX                          draw_mesh_text(ob, 1);
3087                         GPU_disable_material();
3088
3089                         glFrontFace(GL_CCW);
3090                 }
3091                 else {
3092                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3093                 }
3094
3095                 if (!(draw_flags & DRAW_FACE_SELECT)) {
3096                         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
3097                                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
3098                                         glColor3ubv(ob_wire_col);
3099                                 }
3100                                 dm->drawLooseEdges(dm);
3101                         }
3102                 }
3103         }
3104         else if (dt == OB_SOLID) {
3105                 if (draw_flags & DRAW_MODIFIERS_PREVIEW) {
3106                         /* for object selection draws no shade */
3107                         if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
3108                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3109                         }
3110                         else {
3111                                 const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f};
3112
3113                                 /* draw outline */
3114                                 if ((v3d->flag & V3D_SELECT_OUTLINE) &&
3115                                     ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
3116                                     (base->flag & SELECT) &&
3117                                     (draw_wire == OBDRAW_WIRE_OFF) &&
3118                                     (ob->sculpt == NULL))
3119                                 {
3120                                         draw_mesh_object_outline(v3d, ob, dm);
3121                                 }
3122
3123                                 /* materials arent compatible with vertex colors */
3124                                 GPU_end_object_materials();
3125
3126                                 GPU_enable_material(0, NULL);
3127                                 
3128