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