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