svn merge -r38500:38600 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                 float co2[3];
1646
1647                 VECCOPY(co2, co);
1648
1649                 mul_m4_v3(data->vc.obedit->obmat, co2);
1650
1651                 if (data->clipVerts) {
1652                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1653                 } else {
1654                         project_short_noclip(data->vc.ar, co2, s);
1655                 }
1656
1657                 if (s[0]!=IS_CLIPPED)
1658                         data->func(data->userData, eve, s[0], s[1], index);
1659         }
1660 }
1661
1662 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, int clipVerts)
1663 {
1664         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;
1665         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1666         
1667         data.vc= *vc;
1668         data.func = func;
1669         data.userData = userData;
1670         data.clipVerts = clipVerts;
1671
1672         EDBM_init_index_arrays(vc->em, 1, 0, 0);
1673         if(clipVerts)
1674                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1675
1676         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1677         EDBM_free_index_arrays(vc->em);
1678
1679         dm->release(dm);
1680 }
1681
1682 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1683 {
1684         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;
1685         BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
1686         short s[2][2];
1687         float v1_co[3], v2_co[3];
1688         
1689         VECCOPY(v1_co, v0co);
1690         VECCOPY(v2_co, v1co);
1691
1692         mul_m4_v3(data->vc.obedit->obmat, v1_co);
1693         mul_m4_v3(data->vc.obedit->obmat, v2_co);
1694
1695         if (!BM_TestHFlag(eed, BM_HIDDEN)) {
1696                 if (data->clipVerts==1) {
1697                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1698                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1699                 } else {
1700                         project_short_noclip(data->vc.ar, v1_co, s[0]);
1701                         project_short_noclip(data->vc.ar, v2_co, s[1]);
1702
1703                         if (data->clipVerts==2) {
1704                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1705                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1706                                                 return;
1707                         }
1708                 }
1709
1710                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1711         }
1712 }
1713
1714 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)
1715 {
1716         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;
1717         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1718
1719         data.vc= *vc;
1720         data.func = func;
1721         data.userData = userData;
1722         data.clipVerts = clipVerts;
1723
1724         EDBM_init_index_arrays(vc->em, 0, 1, 0);
1725         if(clipVerts)
1726                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1727
1728         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1729         EDBM_free_index_arrays(vc->em);
1730
1731         dm->release(dm);
1732 }
1733
1734 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1735 {
1736         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;
1737         float cent2[3];
1738         BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
1739         short s[2];
1740
1741         VECCOPY(cent2, cent);
1742         if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
1743                 mul_m4_v3(data->vc.obedit->obmat, cent2);
1744                 project_short(data->vc.ar, cent2, s);
1745
1746                 data->func(data->userData, efa, s[0], s[1], index);
1747         }
1748 }
1749
1750 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData)
1751 {
1752         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;
1753         DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1754
1755         data.vc= *vc;
1756         data.func = func;
1757         data.userData = userData;
1758
1759         EDBM_init_index_arrays(vc->em, 0, 0, 1);
1760         //if(clipVerts)
1761         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1762
1763         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1764         EDBM_free_index_arrays(vc->em);
1765
1766         dm->release(dm);
1767 }
1768
1769 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1770 {
1771         Curve *cu= vc->obedit->data;
1772         short s[2] = {IS_CLIPPED, 0};
1773         Nurb *nu;
1774         int i;
1775         ListBase *nurbs= ED_curve_editnurbs(cu);
1776
1777         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1778
1779         for (nu= nurbs->first; nu; nu=nu->next) {
1780                 if(nu->type == CU_BEZIER) {
1781                         for (i=0; i<nu->pntsu; i++) {
1782                                 BezTriple *bezt = &nu->bezt[i];
1783
1784                                 if(bezt->hide==0) {
1785                                         
1786                                         if(cu->drawflag & CU_HIDE_HANDLES) {
1787                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1788                                                 if (s[0] != IS_CLIPPED)
1789                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1790                                         } else {
1791                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1792                                                 if (s[0] != IS_CLIPPED)
1793                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1794                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1795                                                 if (s[0] != IS_CLIPPED)
1796                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1797                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1798                                                 if (s[0] != IS_CLIPPED)
1799                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1800                                         }
1801                                 }
1802                         }
1803                 }
1804                 else {
1805                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1806                                 BPoint *bp = &nu->bp[i];
1807
1808                                 if(bp->hide==0) {
1809                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1810                                         if (s[0] != IS_CLIPPED)
1811                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1812                                 }
1813                         }
1814                 }
1815         }
1816 }
1817
1818 /* ************** DRAW MESH ****************** */
1819
1820 /* First section is all the "simple" draw routines, 
1821  * ones that just pass some sort of primitive to GL,
1822  * with perhaps various options to control lighting,
1823  * color, etc.
1824  *
1825  * These routines should not have user interface related
1826  * logic!!!
1827  */
1828
1829 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1830 {
1831         Scene *scene= ((void **)userData)[0];
1832         BMEditMesh *em = ((void **)userData)[1];
1833         BMFace *efa = EDBM_get_face_for_index(em, index);
1834         ToolSettings *ts= scene->toolsettings;
1835
1836         if (!BM_TestHFlag(efa, BM_HIDDEN)) {
1837                 glVertex3fv(cent);
1838                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1839                                         cent[1] + no[1]*ts->normalsize,
1840                                         cent[2] + no[2]*ts->normalsize);
1841         }
1842 }
1843 static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
1844 {
1845         void *ptrs[2] = {scene, em};
1846
1847         glBegin(GL_LINES);
1848         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs);
1849         glEnd();
1850 }
1851
1852 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1853 {
1854         BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
1855         int sel = *(((int **)userData)[1]);
1856         
1857         if (efa && !BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) {
1858                 bglVertex3fv(cent);
1859         }
1860 }
1861 static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
1862 {
1863         void *ptrs[2] = {em, &sel};
1864
1865         bglBegin(GL_POINTS);
1866         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
1867         bglEnd();
1868 }
1869
1870 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1871 {
1872         Scene *scene= ((void **)userData)[0];
1873         ToolSettings *ts= scene->toolsettings;
1874         BMEditMesh *em = ((void **)userData)[1];
1875         BMVert *eve = EDBM_get_vert_for_index(em, index);
1876
1877         if (!BM_TestHFlag(eve, BM_HIDDEN)) {
1878                 glVertex3fv(co);
1879
1880                 if (no_f) {
1881                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1882                                                 co[1] + no_f[1]*ts->normalsize,
1883                                                 co[2] + no_f[2]*ts->normalsize);
1884                 } else {
1885                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1886                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1887                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1888                 }
1889         }
1890 }
1891 static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
1892 {
1893         void *ptrs[2] = {scene, em};
1894
1895         glBegin(GL_LINES);
1896         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs);
1897         glEnd();
1898 }
1899
1900 /* Draw verts with color set based on selection */
1901 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1902 {
1903         struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData;
1904         BMVert *eve = EDBM_get_vert_for_index(data->em, index);
1905
1906         if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) {
1907                 /* draw active larger - need to stop/start point drawing for this :/ */
1908                 if (eve==data->eve_act) {
1909                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1910                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1911                         
1912                         bglEnd();
1913                         
1914                         glPointSize(size);
1915                         bglBegin(GL_POINTS);
1916                         bglVertex3fv(co);
1917                         bglEnd();
1918                         
1919                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1920                         glPointSize(size);
1921                         bglBegin(GL_POINTS);
1922                 } else {
1923                         bglVertex3fv(co);
1924                 }
1925         }
1926 }
1927
1928 static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
1929 {
1930         struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
1931         data.sel = sel;
1932         data.eve_act = eve_act;
1933         data.em = em;
1934         
1935         bglBegin(GL_POINTS);
1936         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1937         bglEnd();
1938
1939         bglBegin(GL_POINTS);
1940         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1941         bglEnd();
1942 }
1943
1944         /* Draw edges with color set based on selection */
1945 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1946 {
1947         BMEdge *eed;
1948         //unsigned char **cols = userData, *col;
1949         struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData;
1950         unsigned char *col;
1951
1952         eed = EDBM_get_edge_for_index(data->em, index);
1953
1954         if (!BM_TestHFlag(eed, BM_HIDDEN)) {
1955                 if (eed==data->eed_act) {
1956                         glColor4ubv(data->actCol);
1957                 } else {
1958                         if (BM_TestHFlag(eed, BM_SELECT)) {
1959                                 col = data->selCol;
1960                         } else {
1961                                 col = data->baseCol;
1962                         }
1963                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1964                         if (col[3]==0) return 0;
1965                         
1966                         glColor4ubv(col);
1967                 }
1968                 return 1;
1969         } else {
1970                 return 0;
1971         }
1972 }
1973 static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
1974                               unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act) 
1975 {
1976         struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data;
1977         
1978         data.baseCol = baseCol;
1979         data.selCol = selCol;
1980         data.actCol = actCol;
1981         data.em = em;
1982         data.eed_act = eed_act;
1983         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1984 }
1985
1986         /* Draw edges */
1987 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1988 {
1989         return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN);
1990 }
1991 static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
1992 {
1993         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
1994 }
1995
1996         /* Draw edges with color interpolated based on selection */
1997 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1998 {
1999         return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_HIDDEN);
2000 }
2001 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2002 {
2003         BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
2004         unsigned char **cols = userData;
2005         unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1];
2006         unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1];
2007
2008         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2009                                 col0[1] + (col1[1]-col0[1])*t,
2010                                 col0[2] + (col1[2]-col0[2])*t,
2011                                 col0[3] + (col1[3]-col0[3])*t);
2012 }
2013
2014 static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2015 {
2016         void *cols[3] = {em, baseCol, selCol};
2017
2018         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2019 }
2020
2021         /* Draw only seam edges */
2022 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
2023 {
2024         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2025
2026         return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
2027 }
2028
2029 static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
2030 {
2031         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
2032 }
2033
2034         /* Draw only sharp edges */
2035 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
2036 {
2037         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2038
2039         return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP);
2040 }
2041 static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
2042 {
2043         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
2044 }
2045
2046
2047         /* Draw faces with color set based on selection
2048          * return 2 for the active face so it renders with stipple enabled */
2049 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2050 {
2051         struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData;
2052         BMFace *efa = EDBM_get_face_for_index(data->em, index);
2053         unsigned char *col;
2054         
2055         if (!efa)
2056                 return 0;
2057         
2058         if (!BM_TestHFlag(efa, BM_HIDDEN)) {
2059                 if (efa == data->efa_act) {
2060                         glColor4ubv(data->cols[2]);
2061
2062                         return 2; /* stipple */
2063                 } else {
2064                         col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
2065                         if (col[3]==0) return 0;
2066
2067                         glColor4ubv(col);
2068
2069                         return 1;
2070                 }
2071         }
2072         return 0;
2073 }
2074
2075 /* also draws the active face */
2076 static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
2077                               unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me) 
2078 {
2079         struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
2080
2081         data.cols[0] = baseCol;
2082         data.em = em;
2083         data.cols[1] = selCol;
2084         data.cols[2] = actCol;
2085         data.efa_act = efa_act;
2086         data.me = me;
2087
2088         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
2089 }
2090
2091 static int draw_dm_creases__setDrawOptions(void *userData, int index)
2092 {
2093         BMEditMesh *em = userData;
2094         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2095         float *crease = eed ? bm_get_cd_float(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
2096         
2097         if (!crease)
2098                 return 0;
2099         
2100         if (!BM_TestHFlag(eed, BM_HIDDEN) && *crease!=0.0f) {
2101                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
2102                 return 1;
2103         } else {
2104                 return 0;
2105         }
2106 }
2107 static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
2108 {
2109         glLineWidth(3.0);
2110         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
2111         glLineWidth(1.0);
2112 }
2113
2114 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
2115 {
2116         BMEditMesh *em = userData;
2117         BMEdge *eed = EDBM_get_edge_for_index(userData, index);
2118         float *bweight = bm_get_cd_float(&em->bm->edata, eed->head.data, CD_BWEIGHT);
2119
2120         if (!bweight)
2121                 return 0;
2122         
2123         if (!BM_TestHFlag(eed, BM_HIDDEN) && *bweight!=0.0f) {
2124                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
2125                 return 1;
2126         } else {
2127                 return 0;
2128         }
2129 }
2130 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2131 {
2132         BMEditMesh *em = userData;
2133         BMVert *eve = EDBM_get_vert_for_index(userData, index);
2134         float *bweight = bm_get_cd_float(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
2135         
2136         if (!bweight)
2137                 return;
2138         
2139         if (!BM_TestHFlag(eve, BM_HIDDEN) && *bweight!=0.0f) {
2140                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
2141                 bglVertex3fv(co);
2142         }
2143 }
2144 static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
2145 {
2146         ToolSettings *ts= scene->toolsettings;
2147
2148         if (ts->selectmode & SCE_SELECT_VERTEX) {
2149                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2150                 bglBegin(GL_POINTS);
2151                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
2152                 bglEnd();
2153         }
2154         else {
2155                 glLineWidth(3.0);
2156                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
2157                 glLineWidth(1.0);
2158         }
2159 }
2160
2161 /* Second section of routines: Combine first sets to form fancy
2162  * drawing routines (for example rendering twice to get overlays).
2163  *
2164  * Also includes routines that are basic drawing but are too
2165  * specialized to be split out (like drawing creases or measurements).
2166  */
2167
2168 /* EditMesh drawing routines*/
2169
2170 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
2171                                 BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
2172 {
2173         ToolSettings *ts= scene->toolsettings;
2174         int sel;
2175
2176         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2177
2178         for (sel=0; sel<2; sel++) {
2179                 unsigned char col[4], fcol[4];
2180                 int pass;
2181
2182                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2183                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2184
2185                 for (pass=0; pass<2; pass++) {
2186                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2187                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2188
2189                         if (pass==0) {
2190                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2191                                         glDisable(GL_DEPTH_TEST);
2192                                                 
2193                                         glEnable(GL_BLEND);
2194                                 } else {
2195                                         continue;
2196                                 }
2197
2198                                 size = (size > 2.1f ? size/2.0f:size);
2199                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2200                                 col[3] = fcol[3] = 100;
2201                         } else {
2202                                 col[3] = fcol[3] = 255;
2203                         }
2204                                 
2205                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2206                                 glPointSize(size);
2207                                 glColor4ubv(col);
2208                                 draw_dm_verts(em, cageDM, sel, eve_act);
2209                         }
2210                         
2211                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2212                                 glPointSize(fsize);
2213                                 glColor4ubv(fcol);
2214                                 draw_dm_face_centers(em, cageDM, sel);
2215                         }
2216                         
2217                         if (pass==0) {
2218                                 glDisable(GL_BLEND);
2219                                 glEnable(GL_DEPTH_TEST);
2220                         }
2221                 }
2222         }
2223
2224         if(v3d->zbuf) glDepthMask(1);
2225         glPointSize(1.0);
2226 }
2227
2228 static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, 
2229                                 Mesh *me, DerivedMesh *cageDM, short sel_only, 
2230                                 BMEdge *eed_act)
2231 {
2232         ToolSettings *ts= scene->toolsettings;
2233         int pass;
2234         unsigned char wireCol[4], selCol[4], actCol[4];
2235
2236         /* since this function does transparant... */
2237         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2238         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2239         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2240         
2241         /* when sel only is used, dont render wire, only selected, this is used for
2242          * textured draw mode when the 'edges' option is disabled */
2243         if (sel_only)
2244                 wireCol[3] = 0;
2245
2246         for (pass=0; pass<2; pass++) {
2247                         /* show wires in transparant when no zbuf clipping for select */
2248                 if (pass==0) {
2249                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2250                                 glEnable(GL_BLEND);
2251                                 glDisable(GL_DEPTH_TEST);
2252                                 selCol[3] = 85;
2253                                 if (!sel_only) wireCol[3] = 85;
2254                         } else {
2255                                 continue;
2256                         }
2257                 } else {
2258                         selCol[3] = 255;
2259                         if (!sel_only) wireCol[3] = 255;
2260                 }
2261
2262                 if(ts->selectmode == SCE_SELECT_FACE) {
2263                         draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2264                 }       
2265                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2266                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2267                                 glShadeModel(GL_SMOOTH);
2268                                 draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
2269                                 glShadeModel(GL_FLAT);
2270                         } else {
2271                                 draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
2272                         }
2273                 }
2274                 else {
2275                         if (!sel_only) {
2276                                 glColor4ubv(wireCol);
2277                                 draw_dm_edges(em, cageDM);
2278                         }
2279                 }
2280
2281                 if (pass==0) {
2282                         glDisable(GL_BLEND);
2283                         glEnable(GL_DEPTH_TEST);
2284                 }
2285         }
2286 }       
2287
2288 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, 
2289                                   Object *ob, BMEditMesh *em, UnitSettings *unit)
2290 {
2291         Mesh *me= ob->data;
2292         float v1[3], v2[3], v3[3], vmid[3], fvec[3];
2293         char val[32]; /* Stores the measurement display text here */
2294         const char *conv_float; /* Use a float conversion matching the grid size */
2295         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2296         float area; /* area of the face */
2297         float grid= unit->system ? unit->scale_length : v3d->grid;
2298         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2299         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2300         const int do_moving= G.moving;
2301
2302         BMIter iter;
2303         int i;
2304
2305         /* make the precision of the pronted value proportionate to the gridsize */
2306
2307         if (grid < 0.01f)               conv_float= "%.6g";
2308         else if (grid < 0.1f)   conv_float= "%.5g";
2309         else if (grid < 1.0f)   conv_float= "%.4g";
2310         else if (grid < 10.0f)  conv_float= "%.3g";
2311         else                                    conv_float= "%.2g";
2312
2313         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2314                 glDisable(GL_DEPTH_TEST);
2315
2316         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2317         
2318         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2319                 BMEdge *eed;
2320
2321                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2322
2323                 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
2324                 for(; eed; eed=BMIter_Step(&iter)) {
2325                         /* draw selected edges, or edges next to selected verts while draging */
2326                         if(BM_TestHFlag(eed, BM_SELECT) ||
2327                                 (do_moving && (BM_TestHFlag(eed->v1, BM_SELECT) || BM_TestHFlag(eed->v2, BM_SELECT) ))) {
2328
2329                                 copy_v3_v3(v1, eed->v1->co);
2330                                 copy_v3_v3(v2, eed->v2->co);
2331
2332                                 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2333
2334                                 if(do_global) {
2335                                         mul_mat3_m4_v3(ob->obmat, v1);
2336                                         mul_mat3_m4_v3(ob->obmat, v2);
2337                                 }
2338                                 if(unit->system)
2339                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2340                                 else
2341                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2342
2343                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2344                         }
2345                 }
2346         }
2347
2348         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2349                 /* would be nice to use BM_face_area, but that is for 2d faces
2350                 so instead add up tessalation triangle areas */
2351                 BMFace *f;
2352                 int n;
2353
2354 #define DRAW_EM_MEASURE_STATS_FACEAREA(void)\
2355                 if (BM_TestHFlag(f, BM_SELECT)) {\
2356                         mul_v3_fl(vmid, 1.0/n);\
2357                         if(unit->system)\
2358                                 bUnit_AsString(val, sizeof(val), area*unit->scale_length,\
2359                                         3, unit->system, B_UNIT_LENGTH, do_split, FALSE);\
2360                         else\
2361                                 sprintf(val, conv_float, area);\
2362                         view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);\
2363                 }
2364
2365                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2366                 
2367                 f = NULL;
2368                 area = 0.0;
2369                 zero_v3(vmid);
2370                 n = 0;
2371                 for(i = 0; i < em->tottri; i++) {
2372                         BMLoop **l = em->looptris[i];
2373                         if(f && l[0]->f != f) {
2374                                 DRAW_EM_MEASURE_STATS_FACEAREA();
2375                                 zero_v3(vmid);
2376                                 area = 0.0;
2377                                 n = 0;
2378                         }
2379
2380                         f = l[0]->f;
2381                         copy_v3_v3(v1, l[0]->v->co);
2382                         copy_v3_v3(v2, l[1]->v->co);
2383                         copy_v3_v3(v3, l[2]->v->co);
2384                         if(do_global) {
2385                                 mul_mat3_m4_v3(ob->obmat, v1);
2386                                 mul_mat3_m4_v3(ob->obmat, v2);
2387                                 mul_mat3_m4_v3(ob->obmat, v3);
2388                         }
2389                         area += area_tri_v3(v1, v2, v3);
2390                         add_v3_v3(vmid, v1);
2391                         add_v3_v3(vmid, v2);
2392                         add_v3_v3(vmid, v3);
2393                         n += 3;
2394                 }
2395
2396                 if(f){
2397                         DRAW_EM_MEASURE_STATS_FACEAREA();
2398                 }
2399 #undef DRAW_EM_MEASURE_STATS_FACEAREA
2400         }
2401
2402         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2403                 BMFace *efa;
2404
2405                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2406
2407
2408                 for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
2409                     efa; efa=BMIter_Step(&iter)) {
2410                         BMIter liter;
2411                         BMLoop *loop;
2412
2413                         BM_Compute_Face_Center(em->bm, efa, vmid);
2414
2415                         for(loop = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
2416                             loop; loop = BMIter_Step(&liter)) {
2417
2418                                 float v1[3], v2[3], v3[3];
2419
2420                                 copy_v3_v3(v1, loop->prev->v->co);
2421                                 copy_v3_v3(v2, loop->v->co);
2422                                 copy_v3_v3(v3, loop->next->v->co);
2423
2424                                 if(do_global){
2425                                         mul_mat3_m4_v3(ob->obmat, v1);
2426                                         mul_mat3_m4_v3(ob->obmat, v2);
2427                                         mul_mat3_m4_v3(ob->obmat, v3);
2428                                 }
2429
2430                                 if(BM_TestHFlag(efa, BM_SELECT) ||
2431                                         (do_moving && BM_TestHFlag(loop->v, BM_SELECT))){
2432                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2433                                         interp_v3_v3v3(fvec, vmid, v2, 0.8f);
2434                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2435                                 }
2436                         }
2437                 }
2438         }
2439
2440         if(v3d->zbuf) {
2441                 glEnable(GL_DEPTH_TEST);
2442                 bglPolygonOffset(rv3d->dist, 0.0f);
2443         }
2444 }
2445
2446 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
2447 {
2448         BMFace *efa = EDBM_get_face_for_index(userData, index);
2449
2450         if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
2451                 GPU_enable_material(efa->mat_nr+1, NULL);
2452                 return 1;
2453         }
2454         else
2455                 return 0;
2456 }
2457
2458 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2459 {
2460         BMFace *efa = EDBM_get_face_for_index(userData, index);
2461
2462         return !BM_TestHFlag(efa, BM_HIDDEN);
2463 }
2464
2465 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
2466                           BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2467
2468 {
2469         Mesh *me = ob->data;
2470         BMFace *efa_act = EDBM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2471         BMEdge *eed_act = NULL;
2472         BMVert *eve_act = NULL;
2473         
2474         if (em->bm->selected.last) {
2475                 BMEditSelection *ese = em->bm->selected.last;
2476                 /* face is handeled above */
2477                 /*if (ese->type == EDITFACE ) {
2478                         efa_act = (EditFace *)ese->data;
2479                 } else */ if ( ese->type == EDITEDGE ) {
2480                         eed_act = (BMEdge *)ese->data;
2481                 } else if ( ese->type == EDITVERT ) {
2482                         eve_act = (BMVert *)ese->data;
2483                 }
2484         }
2485         
2486         EDBM_init_index_arrays(em, 1, 1, 1);
2487
2488         if(dt>OB_WIRE) {
2489                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2490                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2491                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2492
2493                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2494                                         draw_em_fancy__setGLSLFaceOpts, em);
2495                                 GPU_disable_material();
2496
2497                                 glFrontFace(GL_CCW);
2498                         }
2499                         else {
2500                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2501                         }
2502                 }
2503                 else {
2504                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2505                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2506
2507                         glEnable(GL_LIGHTING);
2508                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2509                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material);
2510
2511                         glFrontFace(GL_CCW);
2512                         glDisable(GL_LIGHTING);
2513                 }
2514                         
2515                 // Setup for drawing wire over, disable zbuffer
2516                 // write to show selected edge wires better
2517                 UI_ThemeColor(TH_WIRE);
2518
2519                 bglPolygonOffset(rv3d->dist, 1.0);
2520                 glDepthMask(0);
2521         } 
2522         else {
2523                 if (cageDM!=finalDM) {
2524                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2525                         finalDM->drawEdges(finalDM, 1, 0);
2526                 }
2527         }
2528         
2529         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2530                 unsigned char col1[4], col2[4], col3[4];
2531                         
2532                 UI_GetThemeColor4ubv(TH_FACE, col1);
2533                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2534                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2535                 
2536                 glEnable(GL_BLEND);
2537                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2538                 
2539                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2540                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2541                         col1[3] = 0;
2542                 
2543                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2544
2545                 glDisable(GL_BLEND);
2546                 glDepthMask(1);         // restore write in zbuffer
2547         } else if (efa_act) {
2548                 /* even if draw faces is off it would be nice to draw the stipple face
2549                  * Make all other faces zero alpha except for the active
2550                  * */
2551                 unsigned char col1[4], col2[4], col3[4];
2552                 col1[3] = col2[3] = 0; /* dont draw */
2553                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2554                 
2555                 glEnable(GL_BLEND);
2556                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2557                 
2558                 draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
2559
2560                 glDisable(GL_BLEND);
2561                 glDepthMask(1);         // restore write in zbuffer
2562                 
2563         }
2564
2565         /* here starts all fancy draw-extra over */
2566         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2567                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2568                 
2569                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2570                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
2571                 
2572         } else {
2573                 if(me->drawflag & ME_DRAWSEAMS) {
2574                         UI_ThemeColor(TH_EDGE_SEAM);
2575                         glLineWidth(2);
2576         
2577                         draw_dm_edges_seams(em, cageDM);
2578         
2579                         glColor3ub(0,0,0);
2580                         glLineWidth(1);
2581                 }
2582                 
2583                 if(me->drawflag & ME_DRAWSHARP) {
2584                         UI_ThemeColor(TH_EDGE_SHARP);
2585                         glLineWidth(2);
2586         
2587                         draw_dm_edges_sharp(em, cageDM);
2588         
2589                         glColor3ub(0,0,0);
2590                         glLineWidth(1);
2591                 }
2592         
2593                 if(me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
2594                         draw_dm_creases(em, cageDM);
2595                 }
2596                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2597                         draw_dm_bweights(em, scene, cageDM);
2598                 }
2599
2600                 draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
2601         }
2602         if(em) {
2603 // XXX          retopo_matrix_update(v3d);
2604
2605                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2606
2607                 if(me->drawflag & ME_DRAWNORMALS) {
2608                         UI_ThemeColor(TH_NORMAL);
2609                         draw_dm_face_normals(em, scene, cageDM);
2610                 }
2611                 if(me->drawflag & ME_DRAW_VNORMALS) {
2612                         UI_ThemeColor(TH_VNORMAL);
2613                         draw_dm_vert_normals(em, scene, cageDM);
2614                 }
2615
2616                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2617                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2618         }
2619
2620         if(dt>OB_WIRE) {
2621                 glDepthMask(1);
2622                 bglPolygonOffset(rv3d->dist, 0.0);
2623                 GPU_disable_material();
2624         }
2625
2626         EDBM_free_index_arrays(em);
2627 }
2628
2629 /* Mesh drawing routines */
2630
2631 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2632 {
2633         
2634         if(v3d->transp==0) {    // not when we draw the transparent pass
2635                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2636                 glDepthMask(0);
2637                 
2638                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2639                    drawFacesSolid() doesn't draw the transparent faces */
2640                 if(ob->dtx & OB_DRAWTRANSP) {
2641                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2642                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2643                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2644                         GPU_disable_material();
2645                 }
2646                 else {
2647                         dm->drawEdges(dm, 0, 1);
2648                 }
2649                                         
2650                 glLineWidth(1.0);
2651                 glDepthMask(1);
2652         }
2653 }
2654
2655 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2656 {
2657         *drawSmooth_r = 1;
2658         return 1;
2659 }
2660
2661 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2662 {
2663         Object *ob= base->object;
2664         Mesh *me = ob->data;
2665         Material *ma= give_current_material(ob, 1);
2666         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2667         const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2668         int draw_wire = 0;
2669         int /* totvert,*/ totedge, totface;
2670         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2671
2672         if(!dm)
2673                 return;
2674         
2675         if (ob->dtx&OB_DRAWWIRE) {
2676                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2677         }
2678         
2679         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2680         totedge = dm->getNumEdges(dm);
2681         totface = dm->getNumTessFaces(dm);
2682         
2683         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2684         if(dt!=OB_SHADED)
2685                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2686
2687                 // Unwanted combination.
2688         if (is_paint_sel) draw_wire = 0;
2689
2690         if(dt==OB_BOUNDBOX) {
2691                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2692                         draw_bounding_volume(scene, ob);
2693         }
2694         else if(hasHaloMat || (totface==0 && totedge==0)) {
2695                 glPointSize(1.5);
2696                 dm->drawVerts(dm);
2697                 glPointSize(1.0);
2698         }
2699         else if(dt==OB_WIRE || totface==0) {
2700                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2701         }
2702         else if(        (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2703                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2704         {
2705                 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2706                         draw_mesh_object_outline(v3d, ob, dm);
2707                 }
2708
2709                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2710                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2711
2712                         dm->drawFacesGLSL(dm, GPU_enable_material);
2713 //                      if(get_ob_property(ob, "Text"))
2714 // XXX                          draw_mesh_text(ob, 1);
2715                         GPU_disable_material();
2716
2717                         glFrontFace(GL_CCW);
2718                 }
2719                 else {
2720                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2721                 }
2722
2723                 if(!is_paint_sel) {
2724                         if(base->flag & SELECT)
2725                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2726                         else
2727                                 UI_ThemeColor(TH_WIRE);
2728
2729                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2730                                 dm->drawLooseEdges(dm);
2731                 }
2732         }
2733         else if(dt==OB_SOLID) {
2734                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2735                         /* weight paint in solid mode, special case. focus on making the weights clear
2736                          * rather than the shading, this is also forced in wire view */
2737                         GPU_enable_material(0, NULL);
2738                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2739                 
2740                         bglPolygonOffset(rv3d->dist, 1.0);
2741                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2742
2743                         glEnable(GL_BLEND);
2744                         glColor4ub(255, 255, 255, 96);
2745                         glEnable(GL_LINE_STIPPLE);
2746                         glLineStipple(1, 0xAAAA);
2747
2748                         dm->drawEdges(dm, 1, 1);
2749
2750                         bglPolygonOffset(rv3d->dist, 0.0);
2751                         glDepthMask(1);
2752                         glDisable(GL_LINE_STIPPLE);
2753
2754                         GPU_disable_material();
2755                         
2756                         /* since we already draw wire as wp guide, dont draw over the top */
2757                         draw_wire= 0;
2758                 }
2759                 else {
2760                         Paint *p;
2761
2762                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2763                                 draw_mesh_object_outline(v3d, ob, dm);
2764
2765                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2766
2767                         glEnable(GL_LIGHTING);
2768                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2769
2770                         if(ob->sculpt && (p=paint_get_active(scene))) {
2771                                 float planes[4][4];
2772                                 float (*fpl)[4] = NULL;
2773                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2774
2775                                 if(ob->sculpt->partial_redraw) {
2776                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
2777                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2778                                                 fpl = planes;
2779                                                 ob->sculpt->partial_redraw = 0;
2780                                         }
2781                                 }
2782
2783                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2784                         }
2785                         else
2786                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2787
2788                         GPU_disable_material();
2789
2790                         glFrontFace(GL_CCW);
2791                         glDisable(GL_LIGHTING);
2792
2793                         if(base->flag & SELECT) {
2794                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2795                         } else {
2796                                 UI_ThemeColor(TH_WIRE);
2797                         }
2798                         if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2799                                 dm->drawLooseEdges(dm);
2800                 }
2801         }
2802         else if(dt==OB_SHADED) {
2803                 if(ob==OBACT) {
2804                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2805                                 /* enforce default material settings */
2806                                 GPU_enable_material(0, NULL);
2807                                 
2808                                 /* but set default spec */
2809                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2810                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2811                                 glColor3ub(120, 120, 120);
2812                                 glDisable(GL_COLOR_MATERIAL);
2813                                 /* diffuse */
2814                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2815                                 glEnable(GL_LIGHTING);
2816                                 glEnable(GL_COLOR_MATERIAL);
2817
2818                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
2819                                 glDisable(GL_COLOR_MATERIAL);
2820                                 glDisable(GL_LIGHTING);
2821
2822                                 GPU_disable_material();
2823                         }
2824                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2825                                 if(me->mcol)
2826                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
2827                                 else {
2828                                         glColor3f(1.0f, 1.0f, 1.0f);
2829                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
2830                                 }
2831                         }
2832                 }
2833         }
2834         
2835         /* set default draw color back for wire or for draw-extra later on */
2836         if (dt!=OB_WIRE) {
2837                 if(base->flag & SELECT) {
2838                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2839                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2840                         else if(ob->flag & OB_FROMGROUP) 
2841                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2842                         else if(flag!=DRAW_CONSTCOLOR)
2843                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2844                         else
2845                                 glColor3ub(80,80,80);
2846                 } else {
2847                         if (ob->flag & OB_FROMGROUP) 
2848                                 UI_ThemeColor(TH_GROUP);
2849                         else {
2850                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2851                                         glColor3ub(80,80,80);
2852                                 else
2853                                         UI_ThemeColor(TH_WIRE);
2854                         }
2855                 }
2856         }
2857         if (draw_wire) {
2858
2859                 /* When using wireframe object traw in particle edit mode
2860                  * the mesh gets in the way of seeing the particles, fade the wire color
2861                  * with the background. */
2862                 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2863                         float col_wire[4], col_bg[4], col[3];
2864
2865                         UI_GetThemeColor3fv(TH_BACK, col_bg);
2866                         glGetFloatv(GL_CURRENT_COLOR, col_wire);
2867                         interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2868                         glColor3fv(col);
2869                 }
2870
2871                 /* If drawing wire and drawtype is not OB_WIRE then we are
2872                  * overlaying the wires.
2873                  *
2874                  * UPDATE bug #10290 - With this wire-only objects can draw
2875                  * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2876                  *
2877                  * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2878                  * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2879                  */
2880                 if (dt!=OB_WIRE && draw_wire==2) {
2881                         bglPolygonOffset(rv3d->dist, 1.0);
2882                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2883                 }
2884                 
2885                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2886                         dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2887
2888                 if (dt!=OB_WIRE && draw_wire==2) {
2889                         glDepthMask(1);
2890                         bglPolygonOffset(rv3d->dist, 0.0);
2891                 }
2892         }
2893
2894         dm->release(dm);
2895 }
2896
2897 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2898 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2899 {
2900         Object *ob= base->object;
2901         Object *obedit= scene->obedit;
2902         Mesh *me= ob->data;
2903         BMEditMesh *em= me->edit_btmesh;
2904         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2905         
2906         if(obedit && ob!=obedit && ob->data==obedit->data) {
2907                 if(ob_get_key(ob) || ob_get_key(obedit));
2908                 else if(ob->modifiers.first || obedit->modifiers.first);
2909                 else drawlinked= 1;
2910         }
2911         
2912         if(ob==obedit || drawlinked) {
2913                 DerivedMesh *finalDM, *cageDM;
2914                 
2915                 if (obedit!=ob)
2916                         finalDM = cageDM = editbmesh_get_derived_base(ob, em);
2917                 else
2918                         cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2919                                                                                         scene->customdata_mask);
2920
2921                 if(dt>OB_WIRE) {
2922                         // no transp in editmode, the fancy draw over goes bad then
2923                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2924                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2925                 }
2926
2927                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2928
2929                 GPU_end_object_materials();
2930
2931                 if (obedit!=ob && finalDM)
2932                         finalDM->release(finalDM);
2933         }
2934         else {
2935                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2936                 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2937                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2938                         check_alpha = check_material_alpha(base, me, glsl);
2939
2940                         if(dt==OB_SOLID || glsl) {
2941                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2942                                         (check_alpha)? &do_alpha_pass: NULL);
2943                         }
2944
2945                         draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2946
2947                         GPU_end_object_materials();
2948                         
2949                         if(me->totvert==0) retval= 1;
2950                 }
2951         }
2952         
2953         /* GPU_begin_object_materials checked if this is needed */
2954         if(do_alpha_pass) {
2955                 if(ob->dtx & OB_DRAWXRAY) {
2956                         add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
2957                 }
2958                 else {
2959                         add_view3d_after(&v3d->afterdraw_transp, base, flag);
2960                 }
2961         }
2962         else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
2963                 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
2964                 if(v3d->xray == 0 && v3d->transp == 0) {
2965                         add_view3d_after(&v3d->afterdraw_xray, base, flag);
2966                 }
2967         }
2968         
2969         return retval;
2970 }
2971
2972 /* ************** DRAW DISPLIST ****************** */
2973
2974 static int draw_index_wire= 1;
2975 static int index3_nors_incr= 1;
2976
2977 /* returns 1 when nothing was drawn */
2978 static int drawDispListwire(ListBase *dlbase)
2979 {
2980         DispList *dl;
2981         int parts, nr;
2982         float *data;
2983
2984         if(dlbase==NULL) return 1;
2985         
2986         glEnableClientState(GL_VERTEX_ARRAY);
2987         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2988
2989         for(dl= dlbase->first; dl; dl= dl->next) {
2990                 if(dl->parts==0 || dl->nr==0)
2991                         continue;
2992                 
2993                 data= dl->verts;
2994         
2995                 switch(dl->type) {
2996                 case DL_SEGM:
2997                         
2998                         glVertexPointer(3, GL_FLOAT, 0, data);
2999                         
3000                         for(parts=0; parts<dl->parts; parts++)
3001                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3002                                 
3003                         break;
3004                 case DL_POLY:
3005                         
3006                         glVertexPointer(3, GL_FLOAT, 0, data);
3007                         
3008                         for(parts=0; parts<dl->parts; parts++)
3009                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3010                         
3011                         break;
3012                 case DL_SURF:
3013                         
3014                         glVertexPointer(3, GL_FLOAT, 0, data);
3015                         
3016                         for(parts=0; parts<dl->parts; parts++) {
3017                                 if(dl->flag & DL_CYCL_U) 
3018                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3019                                 else
3020                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3021                         }
3022                         
3023                         for(nr=0; nr<dl->nr; nr++) {
3024                                 int ofs= 3*dl->nr;
3025                                 
3026                                 data= (  dl->verts )+3*nr;
3027                                 parts= dl->parts;
3028
3029                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
3030                                 else glBegin(GL_LINE_STRIP);
3031                                 
3032                                 while(parts--) {
3033                                         glVertex3fv(data);
3034                                         data+=ofs;
3035                                 }
3036                                 glEnd();
3037                                 
3038                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
3039 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
3040 //                              if(dl->flag & DL_CYCL_V) 
3041 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
3042 //                              else
3043 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
3044                         }
3045                         break;
3046                         
3047                 case DL_INDEX3:
3048                         if(draw_index_wire) {
3049                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3050                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
3051                         }
3052                         break;
3053                         
3054                 case DL_INDEX4:
3055                         if(draw_index_wire) {
3056                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
3057                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
3058                         }
3059                         break;
3060                 }
3061         }
3062         
3063         glDisableClientState(GL_VERTEX_ARRAY);
3064         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
3065         
3066         return 0;
3067 }
3068
3069 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
3070 {
3071         DispList *dl;
3072         GPUVertexAttribs gattribs;
3073         float *data, curcol[4];
3074         float *ndata;
3075         
3076         if(lb==NULL) return;
3077         
3078         /* for drawing wire */
3079         glGetFloatv(GL_CURRENT_COLOR, curcol);
3080
3081         glEnable(GL_LIGHTING);
3082         glEnableClientState(GL_VERTEX_ARRAY);
3083         
3084         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
3085         else glFrontFace(GL_CCW);
3086         
3087         if(ob->type==OB_MBALL) {        // mball always smooth shaded
3088                 glShadeModel(GL_SMOOTH);
3089         }
3090         
3091         dl= lb->first;
3092         while(dl) {
3093                 data= dl->verts;
3094                 ndata= dl->nors;
3095
3096                 switch(dl->type) {
3097                 case DL_SEGM:
3098                         if(ob->type==OB_SURF) {
3099                                 int nr;
3100
3101                                 glDisable(GL_LIGHTING);
3102                                 glColor3fv(curcol);
3103  &n