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