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