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