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