e0b8a3241ea9bf07671eb2f702dde7ea9809d77f
[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[2], 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[2])
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[2], 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);
1907                  void *userData; ViewContext vc; eV3DClipTest clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1908         BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
1909
1910         if (!BM_TestHFlag(eve, BM_HIDDEN)) {
1911                 short s[2]= {IS_CLIPPED, 0};
1912
1913                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
1914                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1915                 } else {
1916                         float co2[2];
1917                         mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
1918                         project_short_noclip(data->vc.ar, co2, s);
1919                 }
1920
1921                 if (s[0]!=IS_CLIPPED)
1922                         data->func(data->userData, eve, s[0], s[1], index);
1923         }
1924 }
1925
1926 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, eV3DClipTest clipVerts)
1927 {
1928         struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index);
1929                  void *userData; ViewContext vc; eV3DClipTest clipVerts; float pmat[4][4], vmat[4][4]; } data;
1930         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1931         
1932         data.vc= *vc;
1933         data.func = func;
1934         data.userData = userData;
1935         data.clipVerts = clipVerts;
1936
1937         EDBM_init_index_arrays(vc->em, 1, 0, 0);
1938         if(clipVerts != V3D_CLIP_TEST_OFF)
1939                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1940
1941         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1942         EDBM_free_index_arrays(vc->em);
1943
1944         dm->release(dm);
1945 }
1946
1947 /*  draw callback */
1948 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1949 {
1950         MVert *mv = &((MVert *)userData)[index];
1951
1952         if(!(mv->flag & ME_HIDE)) {
1953                 const char sel= mv->flag & SELECT;
1954
1955                 // TODO define selected color
1956                 if(sel) {
1957                         glColor3f(1.0f, 1.0f, 0.0f);
1958                 }
1959                 else {
1960                         glColor3f(0.0f, 0.0f, 0.0f);
1961                 }
1962
1963                 glVertex3fv(co);
1964         }
1965 }
1966
1967 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
1968 {
1969         glBegin(GL_POINTS);
1970         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
1971         glEnd();
1972 }
1973 static int is_co_in_region(ARegion *ar, const short co[2])
1974 {
1975         return ( (co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
1976                  (co[0] >= 0)          &&
1977                  (co[0] <  ar->winx)   &&
1978                  (co[1] >= 0)          &&
1979                  (co[1] <  ar->winy));
1980 }
1981 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1982 {
1983         struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index);
1984                  void *userData; ViewContext vc; eV3DClipTest clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
1985         BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
1986
1987         if (!BM_TestHFlag(eed, BM_HIDDEN)) {
1988                 short s[2][2];
1989
1990                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
1991                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1992                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1993                 }
1994                 else {
1995                         float v1_co[3], v2_co[3];
1996
1997                         mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
1998                         mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
1999
2000                         project_short_noclip(data->vc.ar, v1_co, s[0]);
2001                         project_short_noclip(data->vc.ar, v2_co, s[1]);
2002
2003                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2004                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
2005                                      !is_co_in_region(data->vc.ar, s[1]))
2006                                 {
2007                                         return;
2008                                 }
2009                         }
2010                 }
2011
2012                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2013         }
2014 }
2015
2016 void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, eV3DClipTest clipVerts)
2017 {
2018         struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index);
2019                  void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
2020         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2021
2022         data.vc= *vc;
2023         data.func = func;
2024         data.userData = userData;
2025         data.clipVerts = clipVerts;
2026
2027         EDBM_init_index_arrays(vc->em, 0, 1, 0);
2028         if(clipVerts != V3D_CLIP_TEST_OFF)
2029                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2030
2031         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2032         EDBM_free_index_arrays(vc->em);
2033
2034         dm->release(dm);
2035 }
2036
2037 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2038 {
2039         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;
2040         BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
2041
2042         if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
2043                 float cent2[3];
2044                 short s[2];
2045
2046                 mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
2047                 project_short(data->vc.ar, cent2, s);
2048
2049                 if (s[0] != IS_CLIPPED) {
2050                         data->func(data->userData, efa, s[0], s[1], index);
2051                 }
2052         }
2053 }
2054
2055 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData)
2056 {
2057         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;
2058         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2059
2060         data.vc= *vc;
2061         data.func = func;
2062         data.userData = userData;
2063
2064         EDBM_init_index_arrays(vc->em, 0, 0, 1);
2065         //if(clipVerts)
2066         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2067
2068         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2069         EDBM_free_index_arrays(vc->em);
2070
2071         dm->release(dm);
2072 }
2073
2074 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
2075 {
2076         Curve *cu= vc->obedit->data;
2077         short s[2] = {IS_CLIPPED, 0};
2078         Nurb *nu;
2079         int i;
2080         ListBase *nurbs= curve_editnurbs(cu);
2081
2082         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2083
2084         for (nu= nurbs->first; nu; nu=nu->next) {
2085                 if(nu->type == CU_BEZIER) {
2086                         for (i=0; i<nu->pntsu; i++) {
2087                                 BezTriple *bezt = &nu->bezt[i];
2088
2089                                 if(bezt->hide==0) {
2090                                         
2091                                         if(cu->drawflag & CU_HIDE_HANDLES) {
2092                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2093                                                 if (s[0] != IS_CLIPPED)
2094                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2095                                         } else {
2096                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
2097                                                 if (s[0] != IS_CLIPPED)
2098                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2099                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2100                                                 if (s[0] != IS_CLIPPED)
2101                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2102                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
2103                                                 if (s[0] != IS_CLIPPED)
2104                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2105                                         }
2106                                 }
2107                         }
2108                 }
2109                 else {
2110                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2111                                 BPoint *bp = &nu->bp[i];
2112
2113                                 if(bp->hide==0) {
2114                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
2115                                         if (s[0] != IS_CLIPPED)
2116                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2117                                 }
2118                         }
2119                 }
2120         }
2121 }
2122
2123 /* ************** DRAW MESH ****************** */
2124
2125 /* First section is all the "simple" draw routines, 
2126  * ones that just pass some sort of primitive to GL,
2127  * with perhaps various options to control lighting,
2128  * color, etc.
2129  *
2130  * These routines should not have user interface related
2131  * logic!!!
2132  */
2133
2134 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2135 {
2136         Scene *scene= ((void **)userData)[0];
2137         BMEditMesh *em = ((void **)userData)[1];
2138         BMFace *efa = EDBM_get_face_for_index(em, index);
2139         ToolSettings *ts= scene->toolsettings;
2140
2141         if (!BM_TestHFlag(efa, BM_HIDDEN)) {
2142                 glVertex3fv(cent);
2143                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
2144                                         cent[1] + no[1]*ts->normalsize,
2145                                         cent[2] + no[2]*ts->normalsize);
2146         }
2147 }
2148 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
2149 {
2150         void *ptrs[2] = {scene, em};
2151
2152         glBegin(GL_LINES);
2153         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs);
2154         glEnd();
2155 }
2156
2157 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2158 {
2159         BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
2160         int sel = *(((int **)userData)[1]);
2161         
2162         if (efa && !BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) {
2163                 bglVertex3fv(cent);
2164         }
2165 }
2166 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
2167 {
2168         void *ptrs[2] = {em, &sel};
2169
2170         bglBegin(GL_POINTS);
2171         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
2172         bglEnd();
2173 }
2174
2175 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2176 {
2177         Scene *scene= ((void **)userData)[0];
2178         ToolSettings *ts= scene->toolsettings;
2179         BMEditMesh *em = ((void **)userData)[1];
2180         BMVert *eve = EDBM_get_vert_for_index(em, index);
2181
2182         if (!BM_TestHFlag(eve, BM_HIDDEN)) {
2183                 glVertex3fv(co);
2184
2185                 if (no_f) {
2186                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
2187                                                 co[1] + no_f[1]*ts->normalsize,
2188                                                 co[2] + no_f[2]*ts->normalsize);
2189                 } else {
2190                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
2191                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
2192                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
2193                 }
2194         }
2195 }
2196 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
2197 {
2198         void *ptrs[2] = {scene, em};
2199
2200         glBegin(GL_LINES);
2201         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs);
2202         glEnd();
2203 }
2204
2205 /* Draw verts with color set based on selection */
2206 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2207 {
2208         struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData;
2209         BMVert *eve = EDBM_get_vert_for_index(data->em, index);
2210
2211         if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) {
2212                 /* draw active larger - need to stop/start point drawing for this :/ */
2213                 if (eve==data->eve_act) {
2214                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2215                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2216                         
2217                         bglEnd();
2218                         
2219                         glPointSize(size);
2220                         bglBegin(GL_POINTS);
2221                         bglVertex3fv(co);
2222                         bglEnd();
2223                         
2224                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2225                         glPointSize(size);
2226                         bglBegin(GL_POINTS);
2227                 } else {
2228                         bglVertex3fv(co);
2229                 }
2230         }
2231 }
2232
2233 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
2234 {
2235         struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
2236         data.sel = sel;
2237         data.eve_act = eve_act;
2238         data.em = em;
2239         
2240         bglBegin(GL_POINTS);
2241         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2242         bglEnd();
2243
2244         bglBegin(GL_POINTS);
2245         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2246         bglEnd();
2247 }
2248
2249         /* Draw edges with color set based on selection */
2250 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2251 {
2252         BMEdge *eed;
2253         //unsigned char **cols = userData, *col;
2254         struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData;
2255         unsigned char *col;
2256
2257         eed = EDBM_get_edge_for_index(data->em, index);
2258
2259         if (!BM_TestHFlag(eed, BM_HIDDEN)) {
2260                 if (eed==data->eed_act) {
2261                         glColor4ubv(data->actCol);
2262                 } else {
2263                         if (BM_TestHFlag(eed, BM_SELECT)) {
2264                                 col = data->selCol;
2265                         } else {
2266                                 col = data->baseCol;
2267                         }
2268                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2269                         if (col[3]==0) return 0;
2270                         
2271                         glColor4ubv(col);
2272                 }
2273                 return 1;
2274         } else {
2275                 return 0;
2276         }
2277 }
2278 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2279                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act) 
2280 {
2281         struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data;
2282         
2283         data.baseCol = baseCol;
2284         data.selCol = selCol;
2285         data.actCol = actCol;
2286         data.em = em;
2287         data.eed_act = eed_act;
2288         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2289 }
2290
2291         /* Draw edges */
2292 static int draw_dm_edges__setDrawOptions(void *userData, int index)
2293 {
2294         return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN);
2295 }
2296 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
2297 {
2298         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
2299 }
2300
2301         /* Draw edges with color interpolated based on selection */
2302 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
2303 {
2304         return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_HIDDEN);
2305 }
2306 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2307 {
2308         BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
2309         unsigned char **cols = userData;
2310         unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1];
2311         unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1];
2312
2313         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2314                                 col0[1] + (col1[1]-col0[1])*t,
2315                                 col0[2] + (col1[2]-col0[2])*t,
2316                                 col0[3] + (col1[3]-col0[3])*t);
2317 }
2318
2319 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2320 {
2321         void *cols[3] = {em, baseCol, selCol};
2322
2323         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2324 }
2325
2326         /* Draw only seam edges */
2327 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2328 {
2329         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2330
2331         return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
2332 }
2333
2334 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2335 {
2336         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2337 }
2338
2339         /* Draw only sharp edges */
2340 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2341 {
2342         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2343
2344         return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP);
2345 }
2346 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2347 {
2348         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2349 }
2350
2351
2352         /* Draw faces with color set based on selection
2353          * return 2 for the active face so it renders with stipple enabled */
2354 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2355 {
2356         struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData;
2357         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2358         unsigned char *col;
2359         
2360         if (!efa)
2361                 return 0;
2362         
2363         if (!BM_TestHFlag(efa, BM_HIDDEN)) {
2364                 if (efa == data->efa_act) {
2365                         glColor4ubv(data->cols[2]);
2366                         return 2; /* stipple */
2367                 } else {
2368                         col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
2369                         if (col[3]==0) return 0;
2370                         glColor4ubv(col);
2371                         return 1;
2372                 }
2373         }
2374         return 0;
2375 }
2376
2377 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2378 {
2379         struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} * data = userData;
2380         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2381         BMFace *next_efa = EDBM_get_face_for_index(data->em, next_index);
2382         unsigned char *col, *next_col;
2383
2384         if(efa == next_efa)
2385                 return 1;
2386
2387         if(efa == data->efa_act || next_efa == data->efa_act)
2388                 return 0;
2389
2390         col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
2391         next_col = data->cols[BM_TestHFlag(next_efa, BM_SELECT)?1:0];
2392
2393         if(col[3]==0 || next_col[3]==0)
2394                 return 0;
2395
2396         return col == next_col;
2397 }
2398
2399 /* also draws the active face */
2400 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2401                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me) 
2402 {
2403         struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
2404
2405         data.cols[0] = baseCol;
2406         data.em = em;
2407         data.cols[1] = selCol;
2408         data.cols[2] = actCol;
2409         data.efa_act = efa_act;
2410         data.me = me;
2411
2412         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2413 }
2414
2415 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2416 {
2417         BMEditMesh *em = userData;
2418         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2419         float *crease = eed ? bm_get_cd_float(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2420         
2421         if (!crease)
2422                 return 0;
2423         
2424         if (!BM_TestHFlag(eed, BM_HIDDEN) && *crease!=0.0f) {
2425                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2426                 return 1;
2427         } else {
2428                 return 0;
2429         }
2430 }
2431 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2432 {
2433         glLineWidth(3.0);
2434         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2435         glLineWidth(1.0);
2436 }
2437
2438 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2439 {
2440         BMEditMesh *em = userData;
2441         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2442         float *bweight = bm_get_cd_float(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2443
2444         if (!bweight)
2445                 return 0;
2446         
2447         if (!BM_TestHFlag(eed, BM_HIDDEN) && *bweight!=0.0f) {
2448                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2449                 return 1;
2450         } else {
2451                 return 0;
2452         }
2453 }
2454 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2455 {
2456         BMEditMesh *em = userData;
2457         BMVert *eve = EDBM_get_vert_for_index(userData, index);
2458         float *bweight = bm_get_cd_float(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2459         
2460         if (!bweight)
2461                 return;
2462         
2463         if (!BM_TestHFlag(eve, BM_HIDDEN) && *bweight!=0.0f) {
2464                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2465                 bglVertex3fv(co);
2466         }
2467 }
2468 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2469 {
2470         ToolSettings *ts= scene->toolsettings;
2471
2472         if (ts->selectmode & SCE_SELECT_VERTEX) {
2473                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2474                 bglBegin(GL_POINTS);
2475                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2476                 bglEnd();
2477         }
2478         else {
2479                 glLineWidth(3.0);
2480                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2481                 glLineWidth(1.0);
2482         }
2483 }
2484
2485 /* Second section of routines: Combine first sets to form fancy
2486  * drawing routines (for example rendering twice to get overlays).
2487  *
2488  * Also includes routines that are basic drawing but are too
2489  * specialized to be split out (like drawing creases or measurements).
2490  */
2491
2492 /* EditMesh drawing routines*/
2493
2494 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2495                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
2496 {
2497         ToolSettings *ts= scene->toolsettings;
2498         int sel;
2499
2500         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2501
2502         for (sel=0; sel<2; sel++) {
2503                 unsigned char col[4], fcol[4];
2504                 int pass;
2505
2506                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2507                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2508
2509                 for (pass=0; pass<2; pass++) {
2510                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2511                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2512
2513                         if (pass==0) {
2514                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2515                                         glDisable(GL_DEPTH_TEST);
2516                                                 
2517                                         glEnable(GL_BLEND);
2518                                 } else {
2519                                         continue;
2520                                 }
2521
2522                                 size = (size > 2.1f ? size/2.0f:size);
2523                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2524                                 col[3] = fcol[3] = 100;
2525                         } else {
2526                                 col[3] = fcol[3] = 255;
2527                         }
2528                                 
2529                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2530                                 glPointSize(size);
2531                                 glColor4ubv(col);
2532                                 draw_dm_verts(em, cageDM, sel, eve_act);
2533                         }
2534                         
2535                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2536                                 glPointSize(fsize);
2537                                 glColor4ubv(fcol);
2538                                 draw_dm_face_centers(em, cageDM, sel);
2539                         }
2540                         
2541                         if (pass==0) {
2542                                 glDisable(GL_BLEND);
2543                                 glEnable(GL_DEPTH_TEST);
2544                         }
2545                 }
2546         }
2547
2548         if(v3d->zbuf) glDepthMask(1);
2549         glPointSize(1.0);
2550 }
2551
2552 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, 
2553                                 Mesh *me, DerivedMesh *cageDM, short sel_only, 
2554                                 BMEdge *eed_act)
2555 {
2556         ToolSettings *ts= scene->toolsettings;
2557         int pass;
2558         unsigned char wireCol[4], selCol[4], actCol[4];
2559
2560         /* since this function does transparant... */
2561         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2562         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2563         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2564         
2565         /* when sel only is used, dont render wire, only selected, this is used for
2566          * textured draw mode when the 'edges' option is disabled */
2567         if (sel_only)
2568                 wireCol[3] = 0;
2569
2570         for (pass=0; pass<2; pass++) {
2571                         /* show wires in transparant when no zbuf clipping for select */
2572                 if (pass==0) {
2573                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2574                                 glEnable(GL_BLEND);
2575                                 glDisable(GL_DEPTH_TEST);
2576                                 selCol[3] = 85;
2577                                 if (!sel_only) wireCol[3] = 85;
2578                         } else {
2579                                 continue;
2580                         }
2581                 } else {
2582                         selCol[3] = 255;
2583                         if (!sel_only) wireCol[3] = 255;
2584                 }
2585
2586                 if(ts->selectmode == SCE_SELECT_FACE) {
2587                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2588                 }       
2589                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2590                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2591                                 glShadeModel(GL_SMOOTH);
2592                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2593                                 glShadeModel(GL_FLAT);
2594                         } else {
2595                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2596                         }
2597                 }
2598                 else {
2599                         if (!sel_only) {
2600                                 glColor4ubv(wireCol);
2601                                 draw_dm_edges(em, cageDM);
2602                         }
2603                 }
2604
2605                 if (pass==0) {
2606                         glDisable(GL_BLEND);
2607                         glEnable(GL_DEPTH_TEST);
2608                 }
2609         }
2610 }       
2611
2612 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, 
2613                                   Object *ob, BMEditMesh *em, UnitSettings *unit)
2614 {
2615         Mesh *me= ob->data;
2616         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2617         char val[32]; /* Stores the measurement display text here */
2618         const char *conv_float; /* Use a float conversion matching the grid size */
2619         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2620         float area; /* area of the face */
2621         float grid= unit->system ? unit->scale_length : v3d->grid;
2622         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2623         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2624         const int do_moving= G.moving;
2625
2626         BMIter iter;
2627         int i;
2628
2629         /* make the precision of the pronted value proportionate to the gridsize */
2630
2631         if (grid < 0.01f)               conv_float= "%.6g";
2632         else if (grid < 0.1f)   conv_float= "%.5g";
2633         else if (grid < 1.0f)   conv_float= "%.4g";
2634         else if (grid < 10.0f)  conv_float= "%.3g";
2635         else                                    conv_float= "%.2g";
2636
2637         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2638                 glDisable(GL_DEPTH_TEST);
2639
2640         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2641         
2642         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2643                 BMEdge *eed;
2644
2645                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2646
2647                 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2648                 for(; eed; eed=BMIter_Step(&iter)) {
2649                         /* draw selected edges, or edges next to selected verts while draging */
2650                         if(BM_TestHFlag(eed, BM_SELECT) ||
2651                                 (do_moving && (BM_TestHFlag(eed->v1, BM_SELECT) || BM_TestHFlag(eed->v2, BM_SELECT) ))) {
2652
2653                                 copy_v3_v3(v1, eed->v1->co);
2654                                 copy_v3_v3(v2, eed->v2->co);
2655
2656                                 mid_v3_v3v3(vmid, v1, v2);
2657
2658                                 if(do_global) {
2659                                         mul_mat3_m4_v3(ob->obmat, v1);
2660                                         mul_mat3_m4_v3(ob->obmat, v2);
2661                                 }
2662                                 if(unit->system)
2663                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2664                                 else
2665                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2666
2667                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2668                         }
2669                 }
2670         }
2671
2672         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2673                 /* would be nice to use BM_face_area, but that is for 2d faces
2674                 so instead add up tessalation triangle areas */
2675                 BMFace *f;
2676                 int n;
2677
2678 #define DRAW_EM_MEASURE_STATS_FACEAREA()\
2679                 if (BM_TestHFlag(f, BM_SELECT)) {\
2680                         mul_v3_fl(vmid, 1.0/n);\
2681                         if(unit->system)\
2682                                 bUnit_AsString(val, sizeof(val), area*unit->scale_length,\
2683                                         3, unit->system, B_UNIT_LENGTH, do_split, FALSE);\
2684                         else\
2685                                 sprintf(val, conv_float, area);\
2686                         view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);\
2687                 }
2688
2689                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2690                 
2691                 f = NULL;
2692                 area = 0.0;
2693                 zero_v3(vmid);
2694                 n = 0;
2695                 for(i = 0; i < em->tottri; i++) {
2696                         BMLoop **l = em->looptris[i];
2697                         if(f && l[0]->f != f) {
2698                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2699                                 zero_v3(vmid);
2700                                 area = 0.0;
2701                                 n = 0;
2702                         }
2703
2704                         f = l[0]->f;
2705                         copy_v3_v3(v1, l[0]->v->co);
2706                         copy_v3_v3(v2, l[1]->v->co);
2707                         copy_v3_v3(v3, l[2]->v->co);
2708                         if(do_global) {
2709                                 mul_mat3_m4_v3(ob->obmat, v1);
2710                                 mul_mat3_m4_v3(ob->obmat, v2);
2711                                 mul_mat3_m4_v3(ob->obmat, v3);
2712                         }
2713                         area += area_tri_v3(v1, v2, v3);
2714                         add_v3_v3(vmid, v1);
2715                         add_v3_v3(vmid, v2);
2716                         add_v3_v3(vmid, v3);
2717                         n += 3;
2718                 }
2719
2720                 if(f){
2721                         DRAW_EM_MEASURE_STATS_FACEAREA();
2722                 }
2723 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2724         }
2725
2726         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2727                 BMFace *efa;
2728
2729                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2730
2731
2732                 for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
2733                     efa; efa=BMIter_Step(&iter)) {
2734                         BMIter liter;
2735                         BMLoop *loop;
2736
2737                         BM_Compute_Face_Center(em->bm, efa, vmid);
2738
2739                         for(loop = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
2740                             loop; loop = BMIter_Step(&liter)) {
2741
2742                                 float v1[3], v2[3], v3[3];
2743
2744                                 copy_v3_v3(v1, loop->prev->v->co);
2745                                 copy_v3_v3(v2, loop->v->co);
2746                                 copy_v3_v3(v3, loop->next->v->co);
2747
2748                                 if(do_global){
2749                                         mul_mat3_m4_v3(ob->obmat, v1);
2750                                         mul_mat3_m4_v3(ob->obmat, v2);
2751                                         mul_mat3_m4_v3(ob->obmat, v3);
2752                                 }
2753
2754                                 if(BM_TestHFlag(efa, BM_SELECT) ||
2755                                         (do_moving && BM_TestHFlag(loop->v, BM_SELECT))){
2756                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2757                                         interp_v3_v3v3(fvec, vmid, v2, 0.8f);
2758                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2759                                 }
2760                         }
2761                 }
2762         }
2763
2764         /* useful for debugging index vs shape key index */
2765 #if 0
2766         {
2767                 BMIter iter;
2768                 BMVert *eve;
2769                 int j=0;
2770
2771                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2772
2773                 if(CustomData_has_layer(&em->bm->vdata, CD_SHAPE_KEYINDEX)) {
2774                         int *keyi;
2775                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2776                                 keyi = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
2777                                 if(keyi && *keyi != ORIGINDEX_NONE) {
2778                                         sprintf(val, "%d:%d", j, *keyi);
2779                                 }
2780                                 else {
2781                                         sprintf(val, "%d", j);
2782                                 }
2783                                 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2784                                 i++;
2785                         }
2786                 }
2787                 else {
2788                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2789                                 sprintf(val, "%d", j);
2790                                 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2791                                 j++;
2792                         }
2793                 }
2794         }
2795 #endif
2796
2797         if(v3d->zbuf) {
2798                 glEnable(GL_DEPTH_TEST);
2799                 bglPolygonOffset(rv3d->dist, 0.0f);
2800         }
2801 }
2802
2803 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
2804 {
2805         BMFace *efa = EDBM_get_face_for_index(userData, index);
2806
2807         if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
2808                 GPU_enable_material(efa->mat_nr+1, NULL);
2809                 return 1;
2810         }
2811         else
2812                 return 0;
2813 }
2814
2815 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2816 {
2817         BMFace *efa = EDBM_get_face_for_index(userData, index);
2818
2819         return !BM_TestHFlag(efa, BM_HIDDEN);
2820 }
2821
2822 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
2823                           BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2824
2825 {
2826         Mesh *me = ob->data;
2827         BMFace *efa_act = BM_get_actFace(em->bm, 0); /* annoying but active faces is stored differently */
2828         BMEdge *eed_act = NULL;
2829         BMVert *eve_act = NULL;
2830         
2831         if (em->bm->selected.last) {
2832                 BMEditSelection *ese= em->bm->selected.last;
2833                 /* face is handeled above */
2834                 /*if (ese->type == BM_FACE ) {
2835                         efa_act = (BMFace *)ese->data;
2836                 } else */ if ( ese->htype == BM_EDGE ) {
2837                         eed_act = (BMEdge *)ese->data;
2838                 } else if ( ese->htype == BM_VERT ) {
2839                         eve_act = (BMVert *)ese->data;
2840                 }
2841         }
2842         
2843         EDBM_init_index_arrays(em, 1, 1, 1);
2844
2845         if(dt>OB_WIRE) {
2846                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2847                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2848                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2849
2850                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2851                                                              draw_em_fancy__setGLSLFaceOpts, em);
2852                                 GPU_disable_material();
2853
2854                                 glFrontFace(GL_CCW);
2855                         }
2856                         else {
2857                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2858                         }
2859                 }
2860                 else {
2861                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2862                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2863
2864                         glEnable(GL_LIGHTING);
2865                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2866                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material, NULL);
2867
2868                         glFrontFace(GL_CCW);
2869                         glDisable(GL_LIGHTING);
2870                 }
2871                         
2872                 // Setup for drawing wire over, disable zbuffer
2873                 // write to show selected edge wires better
2874                 UI_ThemeColor(TH_WIRE);
2875
2876                 bglPolygonOffset(rv3d->dist, 1.0);
2877                 glDepthMask(0);
2878         } 
2879         else {
2880                 if (cageDM!=finalDM) {
2881                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2882                         finalDM->drawEdges(finalDM, 1, 0);
2883                 }
2884         }
2885         
2886         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2887                 unsigned char col1[4], col2[4], col3[4];
2888                         
2889                 UI_GetThemeColor4ubv(TH_FACE, col1);
2890                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2891                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2892                 
2893                 glEnable(GL_BLEND);
2894                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2895                 
2896                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2897                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2898                         col1[3] = 0;
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         } else if (efa_act) {
2905                 /* even if draw faces is off it would be nice to draw the stipple face
2906                  * Make all other faces zero alpha except for the active
2907                  * */
2908                 unsigned char col1[4], col2[4], col3[4];
2909                 col1[3] = col2[3] = 0; /* dont draw */
2910                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2911                 
2912                 glEnable(GL_BLEND);
2913                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2914                 
2915                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2916
2917                 glDisable(GL_BLEND);
2918                 glDepthMask(1);         // restore write in zbuffer
2919                 
2920         }
2921
2922         /* here starts all fancy draw-extra over */
2923         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2924                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2925                 
2926                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2927                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2928                 
2929         } else {
2930                 if(me->drawflag & ME_DRAWSEAMS) {
2931                         UI_ThemeColor(TH_EDGE_SEAM);
2932                         glLineWidth(2);
2933         
2934                         draw_dm_edges_seams(em, cageDM);
2935         
2936                         glColor3ub(0,0,0);
2937                         glLineWidth(1);
2938                 }
2939                 
2940                 if(me->drawflag & ME_DRAWSHARP) {
2941                         UI_ThemeColor(TH_EDGE_SHARP);
2942                         glLineWidth(2);
2943         
2944                         draw_dm_edges_sharp(em, cageDM);
2945         
2946                         glColor3ub(0,0,0);
2947                         glLineWidth(1);
2948                 }
2949         
2950                 if(me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2951                         draw_dm_creases(em, cageDM);
2952                 }
2953                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2954                         draw_dm_bweights(em, scene, cageDM);
2955                 }
2956
2957                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2958         }
2959         if(em) {
2960 // XXX          retopo_matrix_update(v3d);
2961
2962                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2963
2964                 if(me->drawflag & ME_DRAWNORMALS) {
2965                         UI_ThemeColor(TH_NORMAL);
2966                         draw_dm_face_normals(em, scene, cageDM);
2967                 }
2968                 if(me->drawflag & ME_DRAW_VNORMALS) {
2969                         UI_ThemeColor(TH_VNORMAL);
2970                         draw_dm_vert_normals(em, scene, cageDM);
2971                 }
2972
2973                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2974                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2975         }
2976
2977         if(dt>OB_WIRE) {
2978                 glDepthMask(1);
2979                 bglPolygonOffset(rv3d->dist, 0.0);
2980                 GPU_disable_material();
2981         }
2982
2983         EDBM_free_index_arrays(em);
2984 }
2985
2986 /* Mesh drawing routines */
2987
2988 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2989 {
2990         
2991         if(v3d->transp==0) {    // not when we draw the transparent pass
2992                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2993                 glDepthMask(0);
2994                 
2995                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2996                    drawFacesSolid() doesn't draw the transparent faces */
2997                 if(ob->dtx & OB_DRAWTRANSP) {
2998                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2999                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3000                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3001                         GPU_disable_material();
3002                 }
3003                 else {
3004                         dm->drawEdges(dm, 0, 1);
3005                 }
3006                                         
3007                 glLineWidth(1.0);
3008                 glDepthMask(1);
3009         }
3010 }
3011
3012 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
3013 {
3014         *drawSmooth_r = 1;
3015         return 1;
3016 }
3017
3018 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
3019 {
3020         Object *ob= base->object;
3021         Mesh *me = ob->data;
3022         Material *ma= give_current_material(ob, 1);
3023         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3024         eWireDrawMode draw_wire= OBDRAW_WIRE_OFF;
3025         int /* totvert,*/ totedge, totface;
3026         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
3027         ModifierData *md = NULL;
3028         int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3029
3030         if(!dm)
3031                 return;
3032
3033         /* check to draw dynamic paint colors */
3034         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
3035         {
3036                 /* check if target has an active dpaint modifier        */
3037                 if(md && (md->mode & eModifierMode_Realtime))                                   
3038                 {
3039                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
3040                         /* if canvas is ready to preview vertex colors */
3041                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
3042                                 DM_get_face_data_layer(dm, CD_WEIGHT_MCOL)) {
3043                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
3044                         }
3045                 }
3046         }
3047
3048         /* Unwanted combination */
3049         if (draw_flags & DRAW_FACE_SELECT) {
3050                 draw_wire= OBDRAW_WIRE_OFF;
3051         }
3052         else if (ob->dtx & OB_DRAWWIRE) {
3053                 draw_wire= OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3054         }
3055         
3056         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3057         totedge = dm->getNumEdges(dm);
3058         totface = dm->getNumTessFaces(dm);
3059         
3060         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3061         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3062
3063         if(dt==OB_BOUNDBOX) {
3064                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
3065                         draw_bounding_volume(scene, ob, ob->boundtype);
3066         }
3067         else if(hasHaloMat || (totface==0 && totedge==0)) {
3068                 glPointSize(1.5);
3069                 dm->drawVerts(dm);
3070                 glPointSize(1.0);
3071         }
3072         else if(dt==OB_WIRE || totface==0) {
3073                 draw_wire= OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff  */
3074         }
3075         else if ( (draw_flags & DRAW_FACE_SELECT || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
3076                   CHECK_OB_DRAWTEXTURE(v3d, dt))
3077         {
3078                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3079                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3080                      (base->flag & SELECT) &&
3081                      !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3082                      (draw_wire == OBDRAW_WIRE_OFF))
3083                 {
3084                         draw_mesh_object_outline(v3d, ob, dm);
3085                 }
3086
3087                 if(draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
3088                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3089
3090                         dm->drawFacesGLSL(dm, GPU_enable_material);
3091 //                      if(get_ob_property(ob, "Text"))
3092 // XXX                          draw_mesh_text(ob, 1);
3093                         GPU_disable_material();
3094
3095                         glFrontFace(GL_CCW);
3096                 }
3097                 else {
3098                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3099                 }
3100
3101                 if(!(draw_flags & DRAW_FACE_SELECT)) {
3102                         if(base->flag & SELECT)
3103                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
3104                         else
3105                                 UI_ThemeColor(TH_WIRE);
3106
3107                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3108                                 dm->drawLooseEdges(dm);
3109                 }
3110         }
3111         else if(dt==OB_SOLID) {
3112                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
3113                         /* weight paint in solid mode, special case. focus on making the weights clear
3114                          * rather than the shading, this is also forced in wire view */
3115                         GPU_enable_material(0, NULL);
3116                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
3117                 
3118                         bglPolygonOffset(rv3d->dist, 1.0);
3119                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3120
3121                         glEnable(GL_BLEND);
3122                         glColor4ub(255, 255, 255, 96);
3123                         glEnable(GL_LINE_STIPPLE);
3124                         glLineStipple(1, 0xAAAA);
3125
3126                         dm->drawEdges(dm, 1, 1);
3127
3128                         bglPolygonOffset(rv3d->dist, 0.0);
3129                         glDepthMask(1);
3130                         glDisable(GL_LINE_STIPPLE);