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