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