Fixed issue with multiple textures and editmode when VBOs are enabled
[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[2], 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[2])
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[2], 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);
1904                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } *data = userData;
1905
1906         EditVert *eve = EM_get_vert_for_index(index);
1907
1908         if (eve->h==0) {
1909                 short s[2]= {IS_CLIPPED, 0};
1910
1911                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
1912                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1913                 } else {
1914                         view3d_project_short_noclip(data->vc.ar, co, s);
1915                 }
1916
1917                 if (s[0]!=IS_CLIPPED)
1918                         data->func(data->userData, eve, s[0], s[1], index);
1919         }
1920 }
1921
1922 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, eV3DClipTest clipVerts)
1923 {
1924         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index);
1925                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } data;
1926
1927         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1928         
1929         data.vc= *vc;
1930         data.func = func;
1931         data.userData = userData;
1932         data.clipVerts = clipVerts;
1933
1934         if(clipVerts != V3D_CLIP_TEST_OFF)
1935                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1936
1937         EM_init_index_arrays(vc->em, 1, 0, 0);
1938         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1939         EM_free_index_arrays();
1940
1941         dm->release(dm);
1942 }
1943
1944 /*  draw callback */
1945 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1946 {
1947         MVert *mv = &((MVert *)userData)[index];
1948
1949         if(!(mv->flag & ME_HIDE)) {
1950                 const char sel= mv->flag & SELECT;
1951
1952                 // TODO define selected color
1953                 if(sel) {
1954                         glColor3f(1.0f, 1.0f, 0.0f);
1955                 }
1956                 else {
1957                         glColor3f(0.0f, 0.0f, 0.0f);
1958                 }
1959
1960                 glVertex3fv(co);
1961         }
1962 }
1963
1964 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
1965 {
1966         glBegin(GL_POINTS);
1967         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
1968         glEnd();
1969 }
1970 static int is_co_in_region(ARegion *ar, const short co[2])
1971 {
1972         return ( (co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
1973                  (co[0] >= 0)          &&
1974                  (co[0] <  ar->winx)   &&
1975                  (co[1] >= 0)          &&
1976                  (co[1] <  ar->winy));
1977 }
1978 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1979 {
1980         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
1981                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } *data = userData;
1982         EditEdge *eed = EM_get_edge_for_index(index);
1983         short s[2][2];
1984
1985         if (eed->h==0) {
1986                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
1987                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1988                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1989                 }
1990                 else {
1991                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1992                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1993
1994                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
1995                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
1996                                      !is_co_in_region(data->vc.ar, s[1]))
1997                                 {
1998                                         return;
1999                                 }
2000                         }
2001                 }
2002
2003                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2004         }
2005 }
2006
2007 void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, eV3DClipTest clipVerts)
2008 {
2009         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
2010                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } data;
2011         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2012
2013         data.vc= *vc;
2014         data.func = func;
2015         data.userData = userData;
2016         data.clipVerts = clipVerts;
2017
2018         if(clipVerts != V3D_CLIP_TEST_OFF)
2019                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2020
2021         EM_init_index_arrays(vc->em, 0, 1, 0);
2022         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2023         EM_free_index_arrays();
2024
2025         dm->release(dm);
2026 }
2027
2028 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2029 {
2030         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
2031         EditFace *efa = EM_get_face_for_index(index);
2032         short s[2];
2033
2034         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
2035                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
2036
2037                 if (s[0] != IS_CLIPPED) {
2038                         data->func(data->userData, efa, s[0], s[1], index);
2039                 }
2040         }
2041 }
2042
2043 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
2044 {
2045         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
2046         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2047
2048         data.vc= *vc;
2049         data.func = func;
2050         data.userData = userData;
2051
2052         //if(clipVerts)
2053         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2054
2055         EM_init_index_arrays(vc->em, 0, 0, 1);
2056         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2057         EM_free_index_arrays();
2058
2059         dm->release(dm);
2060 }
2061
2062 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
2063 {
2064         Curve *cu= vc->obedit->data;
2065         short s[2] = {IS_CLIPPED, 0};
2066         Nurb *nu;
2067         int i;
2068         ListBase *nurbs= curve_editnurbs(cu);
2069
2070         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2071
2072         for (nu= nurbs->first; nu; nu=nu->next) {
2073                 if(nu->type == CU_BEZIER) {
2074                         for (i=0; i<nu->pntsu; i++) {
2075                                 BezTriple *bezt = &nu->bezt[i];
2076
2077                                 if(bezt->hide==0) {
2078                                         
2079                                         if(cu->drawflag & CU_HIDE_HANDLES) {
2080                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2081                                                 if (s[0] != IS_CLIPPED)
2082                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2083                                         } else {
2084                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
2085                                                 if (s[0] != IS_CLIPPED)
2086                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2087                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2088                                                 if (s[0] != IS_CLIPPED)
2089                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2090                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
2091                                                 if (s[0] != IS_CLIPPED)
2092                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2093                                         }
2094                                 }
2095                         }
2096                 }
2097                 else {
2098                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2099                                 BPoint *bp = &nu->bp[i];
2100
2101                                 if(bp->hide==0) {
2102                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
2103                                         if (s[0] != IS_CLIPPED)
2104                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2105                                 }
2106                         }
2107                 }
2108         }
2109 }
2110
2111 /* ************** DRAW MESH ****************** */
2112
2113 /* First section is all the "simple" draw routines, 
2114  * ones that just pass some sort of primitive to GL,
2115  * with perhaps various options to control lighting,
2116  * color, etc.
2117  *
2118  * These routines should not have user interface related
2119  * logic!!!
2120  */
2121
2122 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2123 {
2124         ToolSettings *ts= ((Scene *)userData)->toolsettings;
2125         EditFace *efa = EM_get_face_for_index(index);
2126
2127         if (efa->h==0 && efa->fgonf!=EM_FGON) {
2128                 glVertex3fv(cent);
2129                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
2130                                         cent[1] + no[1]*ts->normalsize,
2131                                         cent[2] + no[2]*ts->normalsize);
2132         }
2133 }
2134 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
2135 {
2136         glBegin(GL_LINES);
2137         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
2138         glEnd();
2139 }
2140
2141 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2142 {
2143         EditFace *efa = EM_get_face_for_index(index);
2144         int sel = *((int*) userData);
2145
2146         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
2147                 bglVertex3fv(cent);
2148         }
2149 }
2150 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
2151 {
2152         bglBegin(GL_POINTS);
2153         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
2154         bglEnd();
2155 }
2156
2157 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2158 {
2159         Scene *scene= (Scene *)userData;
2160         ToolSettings *ts= scene->toolsettings;
2161         EditVert *eve = EM_get_vert_for_index(index);
2162
2163         if (eve->h==0) {
2164                 glVertex3fv(co);
2165
2166                 if (no_f) {
2167                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
2168                                                 co[1] + no_f[1]*ts->normalsize,
2169                                                 co[2] + no_f[2]*ts->normalsize);
2170                 } else {
2171                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
2172                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
2173                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
2174                 }
2175         }
2176 }
2177 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
2178 {
2179         glBegin(GL_LINES);
2180         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
2181         glEnd();
2182 }
2183
2184         /* Draw verts with color set based on selection */
2185 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2186 {
2187         struct { int sel; EditVert *eve_act; } * data = userData;
2188         EditVert *eve = EM_get_vert_for_index(index);
2189
2190         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
2191                 /* draw active larger - need to stop/start point drawing for this :/ */
2192                 if (eve==data->eve_act) {
2193                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2194                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2195                         
2196                         bglEnd();
2197                         
2198                         glPointSize(size);
2199                         bglBegin(GL_POINTS);
2200                         bglVertex3fv(co);
2201                         bglEnd();
2202                         
2203                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2204                         glPointSize(size);
2205                         bglBegin(GL_POINTS);
2206                 } else {
2207                         bglVertex3fv(co);
2208                 }
2209         }
2210 }
2211
2212 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
2213 {
2214         struct { int sel; EditVert *eve_act; } data;
2215         data.sel = sel;
2216         data.eve_act = eve_act;
2217
2218         bglBegin(GL_POINTS);
2219         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2220         bglEnd();
2221 }
2222
2223         /* Draw edges with color set based on selection */
2224 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2225 {
2226         EditEdge *eed = EM_get_edge_for_index(index);
2227         //unsigned char **cols = userData, *col;
2228         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
2229         unsigned char *col;
2230
2231         if (eed->h==0) {
2232                 if (eed==data->eed_act) {
2233                         glColor4ubv(data->actCol);
2234                 } else {
2235                         if (eed->f&SELECT) {
2236                                 col = data->selCol;
2237                         } else {
2238                                 col = data->baseCol;
2239                         }
2240                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2241                         if (col[3]==0) return 0;
2242                         
2243                         glColor4ubv(col);
2244                 }
2245                 return 1;
2246         } else {
2247                 return 0;
2248         }
2249 }
2250 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
2251 {
2252         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
2253         
2254         data.baseCol = baseCol;
2255         data.selCol = selCol;
2256         data.actCol = actCol;
2257         data.eed_act = eed_act;
2258         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2259 }
2260
2261         /* Draw edges */
2262 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2263 {
2264         return EM_get_edge_for_index(index)->h==0;
2265 }
2266 static void draw_dm_edges(DerivedMesh *dm) 
2267 {
2268         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2269 }
2270
2271         /* Draw edges with color interpolated based on selection */
2272 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2273 {
2274         return EM_get_edge_for_index(index)->h==0;
2275 }
2276 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2277 {
2278         EditEdge *eed = EM_get_edge_for_index(index);
2279         unsigned char **cols = userData;
2280         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2281         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2282
2283         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2284                                 col0[1] + (col1[1]-col0[1])*t,
2285                                 col0[2] + (col1[2]-col0[2])*t,
2286                                 col0[3] + (col1[3]-col0[3])*t);
2287 }
2288
2289 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2290 {
2291         unsigned char *cols[2];
2292         cols[0]= baseCol;
2293         cols[1]= selCol;
2294         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2295 }
2296
2297         /* Draw only seam edges */
2298 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2299 {
2300         EditEdge *eed = EM_get_edge_for_index(index);
2301
2302         return (eed->h==0 && eed->seam);
2303 }
2304 static void draw_dm_edges_seams(DerivedMesh *dm)
2305 {
2306         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2307 }
2308
2309         /* Draw only sharp edges */
2310 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2311 {
2312         EditEdge *eed = EM_get_edge_for_index(index);
2313
2314         return (eed->h==0 && eed->sharp);
2315 }
2316 static void draw_dm_edges_sharp(DerivedMesh *dm)
2317 {
2318         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2319 }
2320
2321
2322         /* Draw faces with color set based on selection
2323          * return 2 for the active face so it renders with stipple enabled */
2324 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2325 {
2326         struct { DerivedMesh *dm; unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2327         EditFace *efa = EM_get_face_for_index(index);
2328         unsigned char *col;
2329         
2330         if (efa->h==0) {
2331                 if (efa == data->efa_act) {
2332                         glColor4ubv(data->cols[2]);
2333                         return 2; /* stipple */
2334                 } else {
2335                         col = data->cols[(efa->f&SELECT)?1:0];
2336                         if (col[3]==0) return 0;
2337                         glColor4ubv(col);
2338                         return 1;
2339                 }
2340         }
2341         return 0;
2342 }
2343
2344 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2345 {
2346         struct { DerivedMesh *dm; unsigned char *cols[3]; EditFace *efa_act; } *data = userData;
2347         int *orig_index= DM_get_face_data_layer(data->dm, CD_ORIGINDEX);
2348         EditFace *efa;
2349         EditFace *next_efa;
2350         unsigned char *col, *next_col;
2351
2352         if(!orig_index)
2353                 return 0;
2354
2355         efa= EM_get_face_for_index(orig_index[index]);
2356         next_efa= EM_get_face_for_index(orig_index[next_index]);
2357
2358         if(efa == next_efa)
2359                 return 1;
2360
2361         if(efa == data->efa_act || next_efa == data->efa_act)
2362                 return 0;
2363
2364         col = data->cols[(efa->f&SELECT)?1:0];
2365         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2366
2367         if(col[3]==0 || next_col[3]==0)
2368                 return 0;
2369
2370         return col == next_col;
2371 }
2372
2373 /* also draws the active face */
2374 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2375 {
2376         struct { DerivedMesh *dm; unsigned char *cols[3]; EditFace *efa_act; } data;
2377         data.dm= dm;
2378         data.cols[0] = baseCol;
2379         data.cols[1] = selCol;
2380         data.cols[2] = actCol;
2381         data.efa_act = efa_act;
2382
2383         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2384 }
2385
2386 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2387 {
2388         EditEdge *eed = EM_get_edge_for_index(index);
2389
2390         if (eed->h==0 && eed->crease != 0.0f) {
2391                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2392                 return 1;
2393         } else {
2394                 return 0;
2395         }
2396 }
2397 static void draw_dm_creases(DerivedMesh *dm)
2398 {
2399         glLineWidth(3.0);
2400         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2401         glLineWidth(1.0);
2402 }
2403
2404 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2405 {
2406         EditEdge *eed = EM_get_edge_for_index(index);
2407
2408         if (eed->h==0 && eed->bweight != 0.0f) {
2409                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2410                 return 1;
2411         } else {
2412                 return 0;
2413         }
2414 }
2415 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2416 {
2417         EditVert *eve = EM_get_vert_for_index(index);
2418
2419         if (eve->h==0 && eve->bweight != 0.0f) {
2420                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2421                 bglVertex3fv(co);
2422         }
2423 }
2424 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2425 {
2426         ToolSettings *ts= scene->toolsettings;
2427
2428         if (ts->selectmode & SCE_SELECT_VERTEX) {
2429                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2430                 bglBegin(GL_POINTS);
2431                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2432                 bglEnd();
2433         }
2434         else {
2435                 glLineWidth(3.0);
2436                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2437                 glLineWidth(1.0);
2438         }
2439 }
2440
2441 /* Second section of routines: Combine first sets to form fancy
2442  * drawing routines (for example rendering twice to get overlays).
2443  *
2444  * Also includes routines that are basic drawing but are too
2445  * specialized to be split out (like drawing creases or measurements).
2446  */
2447
2448 /* EditMesh drawing routines*/
2449
2450 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2451 {
2452         ToolSettings *ts= scene->toolsettings;
2453         int sel;
2454
2455         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2456
2457         for (sel=0; sel<2; sel++) {
2458                 unsigned char col[4], fcol[4];
2459                 int pass;
2460
2461                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2462                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2463
2464                 for (pass=0; pass<2; pass++) {
2465                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2466                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2467
2468                         if (pass==0) {
2469                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2470                                         glDisable(GL_DEPTH_TEST);
2471                                                 
2472                                         glEnable(GL_BLEND);
2473                                 } else {
2474                                         continue;
2475                                 }
2476
2477                                 size = (size > 2.1f ? size/2.0f:size);
2478                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2479                                 col[3] = fcol[3] = 100;
2480                         } else {
2481                                 col[3] = fcol[3] = 255;
2482                         }
2483                                 
2484                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2485                                 glPointSize(size);
2486                                 glColor4ubv(col);
2487                                 draw_dm_verts(cageDM, sel, eve_act);
2488                         }
2489                         
2490                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2491                                 glPointSize(fsize);
2492                                 glColor4ubv(fcol);
2493                                 draw_dm_face_centers(cageDM, sel);
2494                         }
2495                         
2496                         if (pass==0) {
2497                                 glDisable(GL_BLEND);
2498                                 glEnable(GL_DEPTH_TEST);
2499                         }
2500                 }
2501         }
2502
2503         if(v3d->zbuf) glDepthMask(1);
2504         glPointSize(1.0);
2505 }
2506
2507 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2508 {
2509         ToolSettings *ts= scene->toolsettings;
2510         int pass;
2511         unsigned char wireCol[4], selCol[4], actCol[4];
2512
2513         /* since this function does transparant... */
2514         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2515         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2516         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2517         
2518         /* when sel only is used, dont render wire, only selected, this is used for
2519          * textured draw mode when the 'edges' option is disabled */
2520         if (sel_only)
2521                 wireCol[3] = 0;
2522
2523         for (pass=0; pass<2; pass++) {
2524                         /* show wires in transparant when no zbuf clipping for select */
2525                 if (pass==0) {
2526                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2527                                 glEnable(GL_BLEND);
2528                                 glDisable(GL_DEPTH_TEST);
2529                                 selCol[3] = 85;
2530                                 if (!sel_only) wireCol[3] = 85;
2531                         } else {
2532                                 continue;
2533                         }
2534                 } else {
2535                         selCol[3] = 255;
2536                         if (!sel_only) wireCol[3] = 255;
2537                 }
2538
2539                 if(ts->selectmode == SCE_SELECT_FACE) {
2540                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2541                 }       
2542                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2543                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2544                                 glShadeModel(GL_SMOOTH);
2545                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2546                                 glShadeModel(GL_FLAT);
2547                         } else {
2548                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2549                         }
2550                 }
2551                 else {
2552                         if (!sel_only) {
2553                                 glColor4ubv(wireCol);
2554                                 draw_dm_edges(cageDM);
2555                         }
2556                 }
2557
2558                 if (pass==0) {
2559                         glDisable(GL_BLEND);
2560                         glEnable(GL_DEPTH_TEST);
2561                 }
2562         }
2563 }       
2564
2565 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2566 {
2567         Mesh *me= ob->data;
2568         EditEdge *eed;
2569         EditFace *efa;
2570         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2571         float fvec[3];
2572         char val[32]; /* Stores the measurement display text here */
2573         const char *conv_float; /* Use a float conversion matching the grid size */
2574         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2575         float area; /* area of the face */
2576         float grid= unit->system ? unit->scale_length : v3d->grid;
2577         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2578         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2579         const int do_moving= G.moving;
2580
2581         /* make the precision of the pronted value proportionate to the gridsize */
2582
2583         if (grid < 0.01f)               conv_float= "%.6g";
2584         else if (grid < 0.1f)   conv_float= "%.5g";
2585         else if (grid < 1.0f)   conv_float= "%.4g";
2586         else if (grid < 10.0f)  conv_float= "%.3g";
2587         else                                    conv_float= "%.2g";
2588
2589         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2590                 glDisable(GL_DEPTH_TEST);
2591
2592         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2593         
2594         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2595                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2596
2597                 for(eed= em->edges.first; eed; eed= eed->next) {
2598                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2599                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2600                                 copy_v3_v3(v1, eed->v1->co);
2601                                 copy_v3_v3(v2, eed->v2->co);
2602
2603                                 mid_v3_v3v3(vmid, v1, v2);
2604
2605                                 if(do_global) {
2606                                         mul_mat3_m4_v3(ob->obmat, v1);
2607                                         mul_mat3_m4_v3(ob->obmat, v2);
2608                                 }
2609                                 if(unit->system)
2610                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2611                                 else
2612                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2613
2614                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2615                         }
2616                 }
2617         }
2618
2619         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2620 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2621                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2622                 
2623                 for(efa= em->faces.first; efa; efa= efa->next) {
2624                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2625                                 copy_v3_v3(v1, efa->v1->co);
2626                                 copy_v3_v3(v2, efa->v2->co);
2627                                 copy_v3_v3(v3, efa->v3->co);
2628                                 if (efa->v4) {
2629                                         copy_v3_v3(v4, efa->v4->co);
2630                                 }
2631                                 if(do_global) {
2632                                         mul_mat3_m4_v3(ob->obmat, v1);
2633                                         mul_mat3_m4_v3(ob->obmat, v2);
2634                                         mul_mat3_m4_v3(ob->obmat, v3);
2635                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2636                                 }
2637                                 
2638                                 if (efa->v4)
2639                                         area=  area_quad_v3(v1, v2, v3, v4);
2640                                 else
2641                                         area = area_tri_v3(v1, v2, v3);
2642
2643                                 if(unit->system)
2644                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2645                                 else
2646                                         sprintf(val, conv_float, area);
2647
2648                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2649                         }
2650                 }
2651         }
2652
2653         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2654                 EditEdge *e1, *e2, *e3, *e4;
2655                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2656                 for(efa= em->faces.first; efa; efa= efa->next) {
2657                         copy_v3_v3(v1, efa->v1->co);
2658                         copy_v3_v3(v2, efa->v2->co);
2659                         copy_v3_v3(v3, efa->v3->co);
2660                         if(efa->v4) {
2661                                 copy_v3_v3(v4, efa->v4->co); 
2662                         }
2663                         else {
2664                                 copy_v3_v3(v4, v3);
2665                         }
2666                         if(do_global) {
2667                                 mul_mat3_m4_v3(ob->obmat, v1);
2668                                 mul_mat3_m4_v3(ob->obmat, v2);
2669                                 mul_mat3_m4_v3(ob->obmat, v3);
2670                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2671                         }
2672                         
2673                         e1= efa->e1;
2674                         e2= efa->e2;
2675                         e3= efa->e3;
2676                         if(efa->e4) e4= efa->e4; else e4= e3;
2677                         
2678                         /* Calculate the angles */
2679                                 
2680                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2681                                 /* Vec 1 */
2682                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2683                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2684                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2685                         }
2686                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2687                                 /* Vec 2 */
2688                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2689                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2690                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2691                         }
2692                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2693                                 /* Vec 3 */
2694                                 if(efa->v4) 
2695                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2696                                 else
2697                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2698                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2699                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2700                         }
2701                                 /* Vec 4 */
2702                         if(efa->v4) {
2703                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2704                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2705                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2706                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2707                                 }
2708                         }
2709                 }
2710         }
2711
2712         /* useful for debugging index vs shape key index */
2713 #if 0
2714         {
2715                 EditVert *eve;
2716                 int j;
2717                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2718                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2719                         sprintf(val, "%d:%d", j, eve->keyindex);
2720                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2721                 }
2722         }
2723 #endif
2724
2725         if(v3d->zbuf) {
2726                 glEnable(GL_DEPTH_TEST);
2727                 bglPolygonOffset(rv3d->dist, 0.0f);
2728         }
2729 }
2730
2731 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2732 {
2733         EditFace *efa = EM_get_face_for_index(index);
2734
2735         if (efa->h==0) {
2736                 GPU_enable_material(efa->mat_nr+1, NULL);
2737                 return 1;
2738         }
2739         else
2740                 return 0;
2741 }
2742
2743 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2744 {
2745         EditFace *efa = EM_get_face_for_index(index);
2746
2747         return (efa->h==0);
2748 }
2749
2750 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2751 {
2752         Mesh *me = ob->data;
2753         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2754         EditEdge *eed_act = NULL;
2755         EditVert *eve_act = NULL;
2756         
2757         if (em->selected.last) {
2758                 EditSelection *ese = em->selected.last;
2759                 /* face is handeled above */
2760                 /*if (ese->type == EDITFACE ) {
2761                         efa_act = (EditFace *)ese->data;
2762                 } else */ if ( ese->type == EDITEDGE ) {
2763                         eed_act = (EditEdge *)ese->data;
2764                 } else if ( ese->type == EDITVERT ) {
2765                         eve_act = (EditVert *)ese->data;
2766                 }
2767         }
2768         
2769         EM_init_index_arrays(em, 1, 1, 1);
2770
2771         if(dt>OB_WIRE) {
2772                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2773                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2774                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2775                                 
2776                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2777                                                              draw_em_fancy__setGLSLFaceOpts, NULL);
2778                                 GPU_disable_material();
2779                                 
2780                                 glFrontFace(GL_CCW);
2781                         }
2782                         else {
2783                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2784                         }
2785                 }
2786                 else {
2787                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2788                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2789                         
2790                         glEnable(GL_LIGHTING);
2791                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2792                         
2793                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, NULL, 0);
2794                         
2795                         glFrontFace(GL_CCW);
2796                         glDisable(GL_LIGHTING);
2797                 }
2798                         
2799                 // Setup for drawing wire over, disable zbuffer
2800                 // write to show selected edge wires better
2801                 UI_ThemeColor(TH_WIRE);
2802
2803                 bglPolygonOffset(rv3d->dist, 1.0);
2804                 glDepthMask(0);
2805         } 
2806         else {
2807                 if (cageDM!=finalDM) {
2808                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2809                         finalDM->drawEdges(finalDM, 1, 0);
2810                 }
2811         }
2812         
2813         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2814                 unsigned char col1[4], col2[4], col3[4];
2815                         
2816                 UI_GetThemeColor4ubv(TH_FACE, col1);
2817                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2818                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2819                 
2820                 glEnable(GL_BLEND);
2821                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2822                 
2823                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2824                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2825                         col1[3] = 0;
2826                 
2827                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2828
2829                 glDisable(GL_BLEND);
2830                 glDepthMask(1);         // restore write in zbuffer
2831         } else if (efa_act) {
2832                 /* even if draw faces is off it would be nice to draw the stipple face
2833                  * Make all other faces zero alpha except for the active
2834                  * */
2835                 unsigned char col1[4], col2[4], col3[4];
2836                 col1[3] = col2[3] = 0; /* dont draw */
2837                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2838                 
2839                 glEnable(GL_BLEND);
2840                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2841                 
2842                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2843
2844                 glDisable(GL_BLEND);
2845                 glDepthMask(1);         // restore write in zbuffer
2846                 
2847         }
2848
2849         /* here starts all fancy draw-extra over */
2850         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2851                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2852                 
2853                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2854                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2855                 
2856         } else {
2857                 if(me->drawflag & ME_DRAWSEAMS) {
2858                         UI_ThemeColor(TH_EDGE_SEAM);
2859                         glLineWidth(2);
2860         
2861                         draw_dm_edges_seams(cageDM);
2862         
2863                         glColor3ub(0,0,0);
2864                         glLineWidth(1);
2865                 }
2866                 
2867                 if(me->drawflag & ME_DRAWSHARP) {
2868                         UI_ThemeColor(TH_EDGE_SHARP);
2869                         glLineWidth(2);
2870         
2871                         draw_dm_edges_sharp(cageDM);
2872         
2873                         glColor3ub(0,0,0);
2874                         glLineWidth(1);
2875                 }
2876         
2877                 if(me->drawflag & ME_DRAWCREASES) {
2878                         draw_dm_creases(cageDM);
2879                 }
2880                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2881                         draw_dm_bweights(scene, cageDM);
2882                 }
2883         
2884                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2885         }
2886         if(em) {
2887 // XXX          retopo_matrix_update(v3d);
2888
2889                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2890
2891                 if(me->drawflag & ME_DRAWNORMALS) {
2892                         UI_ThemeColor(TH_NORMAL);
2893                         draw_dm_face_normals(scene, cageDM);
2894                 }
2895                 if(me->drawflag & ME_DRAW_VNORMALS) {
2896                         UI_ThemeColor(TH_VNORMAL);
2897                         draw_dm_vert_normals(scene, cageDM);
2898                 }
2899
2900                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2901                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2902         }
2903
2904         if(dt>OB_WIRE) {
2905                 glDepthMask(1);
2906                 bglPolygonOffset(rv3d->dist, 0.0);
2907                 GPU_disable_material();
2908         }
2909
2910         EM_free_index_arrays();
2911 }
2912
2913 /* Mesh drawing routines */
2914
2915 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2916 {
2917         
2918         if(v3d->transp==0) {    // not when we draw the transparent pass
2919                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2920                 glDepthMask(0);
2921                 
2922                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2923                    drawFacesSolid() doesn't draw the transparent faces */
2924                 if(ob->dtx & OB_DRAWTRANSP) {
2925                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2926                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2927                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2928                         GPU_disable_material();
2929                 }
2930                 else {
2931                         dm->drawEdges(dm, 0, 1);
2932                 }
2933                                         
2934                 glLineWidth(1.0);
2935                 glDepthMask(1);
2936         }
2937 }
2938
2939 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2940 {
2941         *drawSmooth_r = 1;
2942         return 1;
2943 }
2944
2945 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2946 {
2947         Object *ob= base->object;
2948         Mesh *me = ob->data;
2949         Material *ma= give_current_material(ob, 1);
2950         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2951         eWireDrawMode draw_wire= OBDRAW_WIRE_OFF;
2952         int /* totvert,*/ totedge, totface;
2953         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2954         ModifierData *md = NULL;
2955         int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
2956
2957         if(!dm)
2958                 return;
2959
2960         /* check to draw dynamic paint colors */
2961         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
2962         {
2963                 /* check if target has an active dpaint modifier        */
2964                 if(md && (md->mode & eModifierMode_Realtime))                                   
2965                 {
2966                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2967                         /* if canvas is ready to preview vertex colors */
2968                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
2969                                 DM_get_face_data_layer(dm, CD_WEIGHT_MCOL)) {
2970                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
2971                         }
2972                 }
2973         }
2974
2975         /* Unwanted combination */
2976         if (draw_flags & DRAW_FACE_SELECT) {
2977                 draw_wire= OBDRAW_WIRE_OFF;
2978         }
2979         else if (ob->dtx & OB_DRAWWIRE) {
2980                 draw_wire= OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
2981         }
2982         
2983         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2984         totedge = dm->getNumEdges(dm);
2985         totface = dm->getNumFaces(dm);
2986         
2987         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2988         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2989
2990         if(dt==OB_BOUNDBOX) {
2991                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2992                         draw_bounding_volume(scene, ob, ob->boundtype);
2993         }
2994         else if(hasHaloMat || (totface==0 && totedge==0)) {
2995                 glPointSize(1.5);
2996                 dm->drawVerts(dm);
2997                 glPointSize(1.0);
2998         }
2999         else if(dt==OB_WIRE || totface==0) {
3000                 draw_wire= OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff  */
3001         }
3002         else if ( (draw_flags & DRAW_FACE_SELECT || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
3003                   CHECK_OB_DRAWTEXTURE(v3d, dt))
3004         {
3005                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3006                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3007                      (base->flag & SELECT) &&
3008                      !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3009                      (draw_wire == OBDRAW_WIRE_OFF))
3010                 {
3011                         draw_mesh_object_outline(v3d, ob, dm);
3012                 }
3013
3014                 if(draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
3015                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3016
3017                         dm->drawFacesGLSL(dm, GPU_enable_material);
3018 //                      if(get_ob_property(ob, "Text"))
3019 // XXX                          draw_mesh_text(ob, 1);
3020                         GPU_disable_material();
3021
3022                         glFrontFace(GL_CCW);
3023                 }
3024                 else {
3025                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3026                 }
3027
3028                 if(!(draw_flags & DRAW_FACE_SELECT)) {
3029                         if(base->flag & SELECT)
3030                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
3031                         else
3032                                 UI_ThemeColor(TH_WIRE);
3033
3034                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3035                                 dm->drawLooseEdges(dm);
3036                 }
3037         }
3038         else if(dt==OB_SOLID) {
3039                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
3040                         /* weight paint in solid mode, special case. focus on making the weights clear
3041                          * rather than the shading, this is also forced in wire view */
3042                         GPU_enable_material(0, NULL);
3043                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, GPU_enable_material, NULL, me->mface, 1);
3044                 
3045                         bglPolygonOffset(rv3d->dist, 1.0);
3046                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3047
3048                         glEnable(GL_BLEND);
3049                         glColor4ub(255, 255, 255, 96);
3050                         glEnable(GL_LINE_STIPPLE);
3051                         glLineStipple(1, 0xAAAA);
3052
3053                         dm->drawEdges(dm, 1, 1);
3054
3055                         bglPolygonOffset(rv3d->dist, 0.0);
3056                         glDepthMask(1);
3057                         glDisable(GL_LINE_STIPPLE);
3058
3059                         GPU_disable_material();
3060                         
3061                         /* since we already draw wire as wp guide, dont draw over the top */
3062                         draw_wire= OBDRAW_WIRE_OFF;
3063                 }
3064                 else if (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW) {
3065                         /* for object selection draws no shade */
3066                         if (flag & (DRAW_PICKING|DRAW_CONSTCOLOR)) {
3067                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3068                         }
3069                         else {
3070                                 /* draw outline */
3071                                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3072                                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3073                                      (base->flag & SELECT) &&
3074                                      (draw_wire == OBDRAW_WIRE_OFF) &&
3075                                      (ob->sculpt == NULL))
3076                                 {
3077                                         draw_mesh_object_outline(v3d, ob, dm);
3078                                 }
3079
3080                                 /* materials arent compatible with vertex colors */
3081                                 GPU_end_object_materials();
3082
3083                                 GPU_enable_material(0, NULL);
3084                                 
3085                                 /* set default spec */
3086                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
3087                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
3088                                 glColor3ub(120, 120, 120);
3089                                 glDisable(GL_COLOR_MATERIAL);
3090                                 /* diffuse */
3091                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
3092                                 glEnable(GL_LIGHTING);
3093                                 glEnable(GL_COLOR_MATERIAL);
3094
3095                                 dm->drawMappedFaces(dm, NULL, GPU_enable_material, NULL, NULL, 1);
3096                                 glDisable(GL_COLOR_MATERIAL);
3097                                 glDisable(GL_LIGHTING);
3098
3099                                 GPU_disable_material();
3100                         }
3101                 }
3102                 else {
3103                         Paint *p;
3104
3105                         if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3106                              ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3107                              (base->flag & SELECT) &&
3108                              (draw_wire == OBDRAW_WIRE_OFF) &&
3109                              (ob->sculpt == NULL))
3110                         {
3111                                 draw_mesh_object_outline(v3d, ob, dm);