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