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