svn merge ^/trunk/blender -r42303:42329
[blender-staging.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full recode and added functions
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawobject.c
27  *  \ingroup spview3d
28  */
29
30
31 #include <string.h>
32 #include <math.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_camera_types.h"
37 #include "DNA_curve_types.h"
38 #include "DNA_constraint_types.h" // for drawing constraint
39 #include "DNA_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 { DerivedMesh *dm; 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 { DerivedMesh *dm; unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} * data = userData;
2380         int *orig_index= DM_get_tessface_data_layer(data->dm, CD_ORIGINDEX);
2381         BMFace *efa;
2382         BMFace *next_efa;
2383
2384         unsigned char *col, *next_col;
2385
2386         if(!orig_index)
2387                 return 0;
2388
2389         efa= EDBM_get_face_for_index(data->em, orig_index[index]);
2390         next_efa= EDBM_get_face_for_index(data->em, orig_index[next_index]);
2391
2392         if(efa == next_efa)
2393                 return 1;
2394
2395         if(efa == data->efa_act || next_efa == data->efa_act)
2396                 return 0;
2397
2398         col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
2399         next_col = data->cols[BM_TestHFlag(next_efa, BM_SELECT)?1:0];
2400
2401         if(col[3]==0 || next_col[3]==0)
2402                 return 0;
2403
2404         return col == next_col;
2405 }
2406
2407 /* also draws the active face */
2408 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2409                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me) 
2410 {
2411         struct { DerivedMesh *dm; unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
2412         data.dm= dm;
2413         data.cols[0] = baseCol;
2414         data.em = em;
2415         data.cols[1] = selCol;
2416         data.cols[2] = actCol;
2417         data.efa_act = efa_act;
2418         data.me = me;
2419
2420         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2421 }
2422
2423 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2424 {
2425         BMEditMesh *em = userData;
2426         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2427         float *crease = eed ? bm_get_cd_float(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2428         
2429         if (!crease)
2430                 return 0;
2431         
2432         if (!BM_TestHFlag(eed, BM_HIDDEN) && *crease!=0.0f) {
2433                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2434                 return 1;
2435         } else {
2436                 return 0;
2437         }
2438 }
2439 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2440 {
2441         glLineWidth(3.0);
2442         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2443         glLineWidth(1.0);
2444 }
2445
2446 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2447 {
2448         BMEditMesh *em = userData;
2449         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2450         float *bweight = bm_get_cd_float(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2451
2452         if (!bweight)
2453                 return 0;
2454         
2455         if (!BM_TestHFlag(eed, BM_HIDDEN) && *bweight!=0.0f) {
2456                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2457                 return 1;
2458         } else {
2459                 return 0;
2460         }
2461 }
2462 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2463 {
2464         BMEditMesh *em = userData;
2465         BMVert *eve = EDBM_get_vert_for_index(userData, index);
2466         float *bweight = bm_get_cd_float(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2467         
2468         if (!bweight)
2469                 return;
2470         
2471         if (!BM_TestHFlag(eve, BM_HIDDEN) && *bweight!=0.0f) {
2472                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2473                 bglVertex3fv(co);
2474         }
2475 }
2476 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2477 {
2478         ToolSettings *ts= scene->toolsettings;
2479
2480         if (ts->selectmode & SCE_SELECT_VERTEX) {
2481                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2482                 bglBegin(GL_POINTS);
2483                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2484                 bglEnd();
2485         }
2486         else {
2487                 glLineWidth(3.0);
2488                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2489                 glLineWidth(1.0);
2490         }
2491 }
2492
2493 /* Second section of routines: Combine first sets to form fancy
2494  * drawing routines (for example rendering twice to get overlays).
2495  *
2496  * Also includes routines that are basic drawing but are too
2497  * specialized to be split out (like drawing creases or measurements).
2498  */
2499
2500 /* EditMesh drawing routines*/
2501
2502 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2503                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
2504 {
2505         ToolSettings *ts= scene->toolsettings;
2506         int sel;
2507
2508         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2509
2510         for (sel=0; sel<2; sel++) {
2511                 unsigned char col[4], fcol[4];
2512                 int pass;
2513
2514                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2515                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2516
2517                 for (pass=0; pass<2; pass++) {
2518                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2519                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2520
2521                         if (pass==0) {
2522                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2523                                         glDisable(GL_DEPTH_TEST);
2524                                                 
2525                                         glEnable(GL_BLEND);
2526                                 } else {
2527                                         continue;
2528                                 }
2529
2530                                 size = (size > 2.1f ? size/2.0f:size);
2531                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2532                                 col[3] = fcol[3] = 100;
2533                         } else {
2534                                 col[3] = fcol[3] = 255;
2535                         }
2536                                 
2537                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2538                                 glPointSize(size);
2539                                 glColor4ubv(col);
2540                                 draw_dm_verts(em, cageDM, sel, eve_act);
2541                         }
2542                         
2543                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2544                                 glPointSize(fsize);
2545                                 glColor4ubv(fcol);
2546                                 draw_dm_face_centers(em, cageDM, sel);
2547                         }
2548                         
2549                         if (pass==0) {
2550                                 glDisable(GL_BLEND);
2551                                 glEnable(GL_DEPTH_TEST);
2552                         }
2553                 }
2554         }
2555
2556         if(v3d->zbuf) glDepthMask(1);
2557         glPointSize(1.0);
2558 }
2559
2560 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, 
2561                                 Mesh *me, DerivedMesh *cageDM, short sel_only, 
2562                                 BMEdge *eed_act)
2563 {
2564         ToolSettings *ts= scene->toolsettings;
2565         int pass;
2566         unsigned char wireCol[4], selCol[4], actCol[4];
2567
2568         /* since this function does transparant... */
2569         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2570         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2571         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2572         
2573         /* when sel only is used, dont render wire, only selected, this is used for
2574          * textured draw mode when the 'edges' option is disabled */
2575         if (sel_only)
2576                 wireCol[3] = 0;
2577
2578         for (pass=0; pass<2; pass++) {
2579                         /* show wires in transparant when no zbuf clipping for select */
2580                 if (pass==0) {
2581                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2582                                 glEnable(GL_BLEND);
2583                                 glDisable(GL_DEPTH_TEST);
2584                                 selCol[3] = 85;
2585                                 if (!sel_only) wireCol[3] = 85;
2586                         } else {
2587                                 continue;
2588                         }
2589                 } else {
2590                         selCol[3] = 255;
2591                         if (!sel_only) wireCol[3] = 255;
2592                 }
2593
2594                 if(ts->selectmode == SCE_SELECT_FACE) {
2595                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2596                 }       
2597                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2598                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2599                                 glShadeModel(GL_SMOOTH);
2600                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2601                                 glShadeModel(GL_FLAT);
2602                         } else {
2603                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2604                         }
2605                 }
2606                 else {
2607                         if (!sel_only) {
2608                                 glColor4ubv(wireCol);
2609                                 draw_dm_edges(em, cageDM);
2610                         }
2611                 }
2612
2613                 if (pass==0) {
2614                         glDisable(GL_BLEND);
2615                         glEnable(GL_DEPTH_TEST);
2616                 }
2617         }
2618 }       
2619
2620 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, 
2621                                   Object *ob, BMEditMesh *em, UnitSettings *unit)
2622 {
2623         Mesh *me= ob->data;
2624         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2625         char val[32]; /* Stores the measurement display text here */
2626         const char *conv_float; /* Use a float conversion matching the grid size */
2627         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2628         float area; /* area of the face */
2629         float grid= unit->system ? unit->scale_length : v3d->grid;
2630         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2631         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2632         const int do_moving= G.moving;
2633
2634         BMIter iter;
2635         int i;
2636
2637         /* make the precision of the pronted value proportionate to the gridsize */
2638
2639         if (grid < 0.01f)               conv_float= "%.6g";
2640         else if (grid < 0.1f)   conv_float= "%.5g";
2641         else if (grid < 1.0f)   conv_float= "%.4g";
2642         else if (grid < 10.0f)  conv_float= "%.3g";
2643         else                                    conv_float= "%.2g";
2644
2645         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2646                 glDisable(GL_DEPTH_TEST);
2647
2648         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2649         
2650         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2651                 BMEdge *eed;
2652
2653                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2654
2655                 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2656                 for(; eed; eed=BMIter_Step(&iter)) {
2657                         /* draw selected edges, or edges next to selected verts while draging */
2658                         if(BM_TestHFlag(eed, BM_SELECT) ||
2659                                 (do_moving && (BM_TestHFlag(eed->v1, BM_SELECT) || BM_TestHFlag(eed->v2, BM_SELECT) ))) {
2660
2661                                 copy_v3_v3(v1, eed->v1->co);
2662                                 copy_v3_v3(v2, eed->v2->co);
2663
2664                                 mid_v3_v3v3(vmid, v1, v2);
2665
2666                                 if(do_global) {
2667                                         mul_mat3_m4_v3(ob->obmat, v1);
2668                                         mul_mat3_m4_v3(ob->obmat, v2);
2669                                 }
2670                                 if(unit->system)
2671                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2672                                 else
2673                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2674
2675                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2676                         }
2677                 }
2678         }
2679
2680         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2681                 /* would be nice to use BM_face_area, but that is for 2d faces
2682                 so instead add up tessalation triangle areas */
2683                 BMFace *f;
2684                 int n;
2685
2686 #define DRAW_EM_MEASURE_STATS_FACEAREA()\
2687                 if (BM_TestHFlag(f, BM_SELECT)) {\
2688                         mul_v3_fl(vmid, 1.0/n);\
2689                         if(unit->system)\
2690                                 bUnit_AsString(val, sizeof(val), area*unit->scale_length,\
2691                                         3, unit->system, B_UNIT_LENGTH, do_split, FALSE);\
2692                         else\
2693                                 sprintf(val, conv_float, area);\
2694                         view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);\
2695                 }
2696
2697                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2698                 
2699                 f = NULL;
2700                 area = 0.0;
2701                 zero_v3(vmid);
2702                 n = 0;
2703                 for(i = 0; i < em->tottri; i++) {
2704                         BMLoop **l = em->looptris[i];
2705                         if(f && l[0]->f != f) {
2706                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2707                                 zero_v3(vmid);
2708                                 area = 0.0;
2709                                 n = 0;
2710                         }
2711
2712                         f = l[0]->f;
2713                         copy_v3_v3(v1, l[0]->v->co);
2714                         copy_v3_v3(v2, l[1]->v->co);
2715                         copy_v3_v3(v3, l[2]->v->co);
2716                         if(do_global) {
2717                                 mul_mat3_m4_v3(ob->obmat, v1);
2718                                 mul_mat3_m4_v3(ob->obmat, v2);
2719                                 mul_mat3_m4_v3(ob->obmat, v3);
2720                         }
2721                         area += area_tri_v3(v1, v2, v3);
2722                         add_v3_v3(vmid, v1);
2723                         add_v3_v3(vmid, v2);
2724                         add_v3_v3(vmid, v3);
2725                         n += 3;
2726                 }
2727
2728                 if(f){
2729                         DRAW_EM_MEASURE_STATS_FACEAREA();
2730                 }
2731 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2732         }
2733
2734         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2735                 BMFace *efa;
2736
2737                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2738
2739
2740                 for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
2741                     efa; efa=BMIter_Step(&iter)) {
2742                         BMIter liter;
2743                         BMLoop *loop;
2744
2745                         BM_Compute_Face_CenterBounds(em->bm, efa, vmid);
2746
2747                         for(loop = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
2748                             loop; loop = BMIter_Step(&liter)) {
2749
2750                                 float v1[3], v2[3], v3[3];
2751
2752                                 copy_v3_v3(v1, loop->prev->v->co);
2753                                 copy_v3_v3(v2, loop->v->co);
2754                                 copy_v3_v3(v3, loop->next->v->co);
2755
2756                                 if(do_global){
2757                                         mul_mat3_m4_v3(ob->obmat, v1);
2758                                         mul_mat3_m4_v3(ob->obmat, v2);
2759                                         mul_mat3_m4_v3(ob->obmat, v3);
2760                                 }
2761
2762                                 if(BM_TestHFlag(efa, BM_SELECT) ||
2763                                         (do_moving && BM_TestHFlag(loop->v, BM_SELECT))){
2764                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2765                                         interp_v3_v3v3(fvec, vmid, v2, 0.8f);
2766                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2767                                 }
2768                         }
2769                 }
2770         }
2771
2772         /* useful for debugging index vs shape key index */
2773 #if 0
2774         {
2775                 BMIter iter;
2776                 BMVert *eve;
2777                 int j=0;
2778
2779                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2780
2781                 if(CustomData_has_layer(&em->bm->vdata, CD_SHAPE_KEYINDEX)) {
2782                         int *keyi;
2783                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2784                                 keyi = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
2785                                 if(keyi && *keyi != ORIGINDEX_NONE) {
2786                                         sprintf(val, "%d:%d", j, *keyi);
2787                                 }
2788                                 else {
2789                                         sprintf(val, "%d", j);
2790                                 }
2791                                 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2792                                 i++;
2793                         }
2794                 }
2795                 else {
2796                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2797                                 sprintf(val, "%d", j);
2798                                 view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2799                                 j++;
2800                         }
2801                 }
2802         }
2803 #endif
2804
2805         if(v3d->zbuf) {
2806                 glEnable(GL_DEPTH_TEST);
2807                 bglPolygonOffset(rv3d->dist, 0.0f);
2808         }
2809 }
2810
2811 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
2812 {
2813         BMFace *efa = EDBM_get_face_for_index(userData, index);
2814
2815         if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
2816                 GPU_enable_material(efa->mat_nr+1, NULL);
2817                 return 1;
2818         }
2819         else
2820                 return 0;
2821 }
2822
2823 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2824 {
2825         BMFace *efa = EDBM_get_face_for_index(userData, index);
2826
2827         return !BM_TestHFlag(efa, BM_HIDDEN);
2828 }
2829
2830 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
2831                           BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2832
2833 {
2834         Mesh *me = ob->data;
2835         BMFace *efa_act = BM_get_actFace(em->bm, 0); /* annoying but active faces is stored differently */
2836         BMEdge *eed_act = NULL;
2837         BMVert *eve_act = NULL;
2838         
2839         if (em->bm->selected.last) {
2840                 BMEditSelection *ese= em->bm->selected.last;
2841                 /* face is handeled above */
2842                 /*if (ese->type == BM_FACE ) {
2843                         efa_act = (BMFace *)ese->data;
2844                 } else */ if ( ese->htype == BM_EDGE ) {
2845                         eed_act = (BMEdge *)ese->data;
2846                 } else if ( ese->htype == BM_VERT ) {
2847                         eve_act = (BMVert *)ese->data;
2848                 }
2849         }
2850         
2851         EDBM_init_index_arrays(em, 1, 1, 1);
2852
2853         if(dt>OB_WIRE) {
2854                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2855                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2856                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2857
2858                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2859                                                              draw_em_fancy__setGLSLFaceOpts, em);
2860                                 GPU_disable_material();
2861
2862                                 glFrontFace(GL_CCW);
2863                         }
2864                         else {
2865                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2866                         }
2867                 }
2868                 else {
2869                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2870                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2871
2872                         glEnable(GL_LIGHTING);
2873                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2874                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, me->edit_btmesh, 0);
2875
2876                         glFrontFace(GL_CCW);
2877                         glDisable(GL_LIGHTING);
2878                 }
2879                         
2880                 // Setup for drawing wire over, disable zbuffer
2881                 // write to show selected edge wires better
2882                 UI_ThemeColor(TH_WIRE);
2883
2884                 bglPolygonOffset(rv3d->dist, 1.0);
2885                 glDepthMask(0);
2886         } 
2887         else {
2888                 if (cageDM!=finalDM) {
2889                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2890                         finalDM->drawEdges(finalDM, 1, 0);
2891                 }
2892         }
2893         
2894         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2895                 unsigned char col1[4], col2[4], col3[4];
2896                         
2897                 UI_GetThemeColor4ubv(TH_FACE, col1);
2898                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2899                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2900                 
2901                 glEnable(GL_BLEND);
2902                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2903                 
2904                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2905                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2906                         col1[3] = 0;
2907                 
2908                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2909
2910                 glDisable(GL_BLEND);
2911                 glDepthMask(1);         // restore write in zbuffer
2912         } else if (efa_act) {
2913                 /* even if draw faces is off it would be nice to draw the stipple face
2914                  * Make all other faces zero alpha except for the active
2915                  * */
2916                 unsigned char col1[4], col2[4], col3[4];
2917                 col1[3] = col2[3] = 0; /* dont draw */
2918                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2919                 
2920                 glEnable(GL_BLEND);
2921                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2922                 
2923                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2924
2925                 glDisable(GL_BLEND);
2926                 glDepthMask(1);         // restore write in zbuffer
2927                 
2928         }
2929
2930         /* here starts all fancy draw-extra over */
2931         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2932                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2933                 
2934                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2935                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2936                 
2937         } else {
2938                 if(me->drawflag & ME_DRAWSEAMS) {
2939                         UI_ThemeColor(TH_EDGE_SEAM);
2940                         glLineWidth(2);
2941         
2942                         draw_dm_edges_seams(em, cageDM);
2943         
2944                         glColor3ub(0,0,0);
2945                         glLineWidth(1);
2946                 }
2947                 
2948                 if(me->drawflag & ME_DRAWSHARP) {
2949                         UI_ThemeColor(TH_EDGE_SHARP);
2950                         glLineWidth(2);
2951         
2952                         draw_dm_edges_sharp(em, cageDM);
2953         
2954                         glColor3ub(0,0,0);
2955                         glLineWidth(1);
2956                 }
2957         
2958                 if(me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2959                         draw_dm_creases(em, cageDM);
2960                 }
2961                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2962                         draw_dm_bweights(em, scene, cageDM);
2963                 }
2964
2965                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2966         }
2967         if(em) {
2968 // XXX          retopo_matrix_update(v3d);
2969
2970                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2971
2972                 if(me->drawflag & ME_DRAWNORMALS) {
2973                         UI_ThemeColor(TH_NORMAL);
2974                         draw_dm_face_normals(em, scene, cageDM);
2975                 }
2976                 if(me->drawflag & ME_DRAW_VNORMALS) {
2977                         UI_ThemeColor(TH_VNORMAL);
2978                         draw_dm_vert_normals(em, scene, cageDM);
2979                 }
2980
2981                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2982                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2983         }
2984
2985         if(dt>OB_WIRE) {
2986                 glDepthMask(1);
2987                 bglPolygonOffset(rv3d->dist, 0.0);
2988                 GPU_disable_material();
2989         }
2990
2991         EDBM_free_index_arrays(em);
2992 }
2993
2994 /* Mesh drawing routines */
2995
2996 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2997 {
2998         
2999         if(v3d->transp==0) {    // not when we draw the transparent pass
3000                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
3001                 glDepthMask(0);
3002                 
3003                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
3004                    drawFacesSolid() doesn't draw the transparent faces */
3005                 if(ob->dtx & OB_DRAWTRANSP) {
3006                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
3007                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3008                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3009                         GPU_disable_material();
3010                 }
3011                 else {
3012                         dm->drawEdges(dm, 0, 1);
3013                 }
3014                                         
3015                 glLineWidth(1.0);
3016                 glDepthMask(1);
3017         }
3018 }
3019
3020 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
3021 {
3022         *drawSmooth_r = 1;
3023         return 1;
3024 }
3025
3026 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
3027 {
3028         Object *ob= base->object;
3029         Mesh *me = ob->data;
3030         Material *ma= give_current_material(ob, 1);
3031         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3032         eWireDrawMode draw_wire= OBDRAW_WIRE_OFF;
3033         int /* totvert,*/ totedge, totface;
3034         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
3035         ModifierData *md = NULL;
3036         int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3037
3038         if(!dm)
3039                 return;
3040
3041         /* check to draw dynamic paint colors */
3042         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
3043         {
3044                 /* check if target has an active dpaint modifier        */
3045                 if(md && (md->mode & eModifierMode_Realtime))                                   
3046                 {
3047                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
3048                         /* if canvas is ready to preview vertex colors */
3049                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
3050                                 DM_get_poly_data_layer(dm, CD_WEIGHT_MCOL)) {
3051                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
3052                         }
3053                 }
3054         }
3055
3056         /* Unwanted combination */
3057         if (draw_flags & DRAW_FACE_SELECT) {
3058                 draw_wire= OBDRAW_WIRE_OFF;
3059         }
3060         else if (ob->dtx & OB_DRAWWIRE) {
3061                 draw_wire= OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3062         }
3063         
3064         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3065         totedge = dm->getNumEdges(dm);
3066         totface = dm->getNumTessFaces(dm);
3067         
3068         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3069         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL