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