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