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