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