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