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