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