Slight refactor of VBO code to deal with multiple textures.
[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 { 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 { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2347         EditFace *efa = EM_get_face_for_index(index);
2348         EditFace *next_efa = EM_get_face_for_index(next_index);
2349         unsigned char *col, *next_col;
2350
2351         if(efa == next_efa)
2352                 return 1;
2353
2354         if(efa == data->efa_act || next_efa == data->efa_act)
2355                 return 0;
2356
2357         col = data->cols[(efa->f&SELECT)?1:0];
2358         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2359
2360         if(col[3]==0 || next_col[3]==0)
2361                 return 0;
2362
2363         return col == next_col;
2364 }
2365
2366 /* also draws the active face */
2367 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2368 {
2369         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2370         data.cols[0] = baseCol;
2371         data.cols[1] = selCol;
2372         data.cols[2] = actCol;
2373         data.efa_act = efa_act;
2374
2375         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2376 }
2377
2378 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2379 {
2380         EditEdge *eed = EM_get_edge_for_index(index);
2381
2382         if (eed->h==0 && eed->crease != 0.0f) {
2383                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2384                 return 1;
2385         } else {
2386                 return 0;
2387         }
2388 }
2389 static void draw_dm_creases(DerivedMesh *dm)
2390 {
2391         glLineWidth(3.0);
2392         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2393         glLineWidth(1.0);
2394 }
2395
2396 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2397 {
2398         EditEdge *eed = EM_get_edge_for_index(index);
2399
2400         if (eed->h==0 && eed->bweight != 0.0f) {
2401                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2402                 return 1;
2403         } else {
2404                 return 0;
2405         }
2406 }
2407 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2408 {
2409         EditVert *eve = EM_get_vert_for_index(index);
2410
2411         if (eve->h==0 && eve->bweight != 0.0f) {
2412                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2413                 bglVertex3fv(co);
2414         }
2415 }
2416 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2417 {
2418         ToolSettings *ts= scene->toolsettings;
2419
2420         if (ts->selectmode & SCE_SELECT_VERTEX) {
2421                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2422                 bglBegin(GL_POINTS);
2423                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2424                 bglEnd();
2425         }
2426         else {
2427                 glLineWidth(3.0);
2428                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2429                 glLineWidth(1.0);
2430         }
2431 }
2432
2433 /* Second section of routines: Combine first sets to form fancy
2434  * drawing routines (for example rendering twice to get overlays).
2435  *
2436  * Also includes routines that are basic drawing but are too
2437  * specialized to be split out (like drawing creases or measurements).
2438  */
2439
2440 /* EditMesh drawing routines*/
2441
2442 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2443 {
2444         ToolSettings *ts= scene->toolsettings;
2445         int sel;
2446
2447         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2448
2449         for (sel=0; sel<2; sel++) {
2450                 unsigned char col[4], fcol[4];
2451                 int pass;
2452
2453                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2454                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2455
2456                 for (pass=0; pass<2; pass++) {
2457                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2458                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2459
2460                         if (pass==0) {
2461                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2462                                         glDisable(GL_DEPTH_TEST);
2463                                                 
2464                                         glEnable(GL_BLEND);
2465                                 } else {
2466                                         continue;
2467                                 }
2468
2469                                 size = (size > 2.1f ? size/2.0f:size);
2470                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2471                                 col[3] = fcol[3] = 100;
2472                         } else {
2473                                 col[3] = fcol[3] = 255;
2474                         }
2475                                 
2476                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2477                                 glPointSize(size);
2478                                 glColor4ubv(col);
2479                                 draw_dm_verts(cageDM, sel, eve_act);
2480                         }
2481                         
2482                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2483                                 glPointSize(fsize);
2484                                 glColor4ubv(fcol);
2485                                 draw_dm_face_centers(cageDM, sel);
2486                         }
2487                         
2488                         if (pass==0) {
2489                                 glDisable(GL_BLEND);
2490                                 glEnable(GL_DEPTH_TEST);
2491                         }
2492                 }
2493         }
2494
2495         if(v3d->zbuf) glDepthMask(1);
2496         glPointSize(1.0);
2497 }
2498
2499 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2500 {
2501         ToolSettings *ts= scene->toolsettings;
2502         int pass;
2503         unsigned char wireCol[4], selCol[4], actCol[4];
2504
2505         /* since this function does transparant... */
2506         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2507         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2508         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2509         
2510         /* when sel only is used, dont render wire, only selected, this is used for
2511          * textured draw mode when the 'edges' option is disabled */
2512         if (sel_only)
2513                 wireCol[3] = 0;
2514
2515         for (pass=0; pass<2; pass++) {
2516                         /* show wires in transparant when no zbuf clipping for select */
2517                 if (pass==0) {
2518                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2519                                 glEnable(GL_BLEND);
2520                                 glDisable(GL_DEPTH_TEST);
2521                                 selCol[3] = 85;
2522                                 if (!sel_only) wireCol[3] = 85;
2523                         } else {
2524                                 continue;
2525                         }
2526                 } else {
2527                         selCol[3] = 255;
2528                         if (!sel_only) wireCol[3] = 255;
2529                 }
2530
2531                 if(ts->selectmode == SCE_SELECT_FACE) {
2532                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2533                 }       
2534                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2535                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2536                                 glShadeModel(GL_SMOOTH);
2537                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2538                                 glShadeModel(GL_FLAT);
2539                         } else {
2540                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2541                         }
2542                 }
2543                 else {
2544                         if (!sel_only) {
2545                                 glColor4ubv(wireCol);
2546                                 draw_dm_edges(cageDM);
2547                         }
2548                 }
2549
2550                 if (pass==0) {
2551                         glDisable(GL_BLEND);
2552                         glEnable(GL_DEPTH_TEST);
2553                 }
2554         }
2555 }       
2556
2557 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2558 {
2559         Mesh *me= ob->data;
2560         EditEdge *eed;
2561         EditFace *efa;
2562         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2563         float fvec[3];
2564         char val[32]; /* Stores the measurement display text here */
2565         const char *conv_float; /* Use a float conversion matching the grid size */
2566         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2567         float area; /* area of the face */
2568         float grid= unit->system ? unit->scale_length : v3d->grid;
2569         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2570         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2571         const int do_moving= G.moving;
2572
2573         /* make the precision of the pronted value proportionate to the gridsize */
2574
2575         if (grid < 0.01f)               conv_float= "%.6g";
2576         else if (grid < 0.1f)   conv_float= "%.5g";
2577         else if (grid < 1.0f)   conv_float= "%.4g";
2578         else if (grid < 10.0f)  conv_float= "%.3g";
2579         else                                    conv_float= "%.2g";
2580
2581         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2582                 glDisable(GL_DEPTH_TEST);
2583
2584         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2585         
2586         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2587                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2588
2589                 for(eed= em->edges.first; eed; eed= eed->next) {
2590                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2591                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2592                                 copy_v3_v3(v1, eed->v1->co);
2593                                 copy_v3_v3(v2, eed->v2->co);
2594
2595                                 mid_v3_v3v3(vmid, v1, v2);
2596
2597                                 if(do_global) {
2598                                         mul_mat3_m4_v3(ob->obmat, v1);
2599                                         mul_mat3_m4_v3(ob->obmat, v2);
2600                                 }
2601                                 if(unit->system)
2602                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2603                                 else
2604                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2605
2606                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2607                         }
2608                 }
2609         }
2610
2611         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2612 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2613                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2614                 
2615                 for(efa= em->faces.first; efa; efa= efa->next) {
2616                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2617                                 copy_v3_v3(v1, efa->v1->co);
2618                                 copy_v3_v3(v2, efa->v2->co);
2619                                 copy_v3_v3(v3, efa->v3->co);
2620                                 if (efa->v4) {
2621                                         copy_v3_v3(v4, efa->v4->co);
2622                                 }
2623                                 if(do_global) {
2624                                         mul_mat3_m4_v3(ob->obmat, v1);
2625                                         mul_mat3_m4_v3(ob->obmat, v2);
2626                                         mul_mat3_m4_v3(ob->obmat, v3);
2627                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2628                                 }
2629                                 
2630                                 if (efa->v4)
2631                                         area=  area_quad_v3(v1, v2, v3, v4);
2632                                 else
2633                                         area = area_tri_v3(v1, v2, v3);
2634
2635                                 if(unit->system)
2636                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2637                                 else
2638                                         sprintf(val, conv_float, area);
2639
2640                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2641                         }
2642                 }
2643         }
2644
2645         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2646                 EditEdge *e1, *e2, *e3, *e4;
2647                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2648                 for(efa= em->faces.first; efa; efa= efa->next) {
2649                         copy_v3_v3(v1, efa->v1->co);
2650                         copy_v3_v3(v2, efa->v2->co);
2651                         copy_v3_v3(v3, efa->v3->co);
2652                         if(efa->v4) {
2653                                 copy_v3_v3(v4, efa->v4->co); 
2654                         }
2655                         else {
2656                                 copy_v3_v3(v4, v3);
2657                         }
2658                         if(do_global) {
2659                                 mul_mat3_m4_v3(ob->obmat, v1);
2660                                 mul_mat3_m4_v3(ob->obmat, v2);
2661                                 mul_mat3_m4_v3(ob->obmat, v3);
2662                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2663                         }
2664                         
2665                         e1= efa->e1;
2666                         e2= efa->e2;
2667                         e3= efa->e3;
2668                         if(efa->e4) e4= efa->e4; else e4= e3;
2669                         
2670                         /* Calculate the angles */
2671                                 
2672                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2673                                 /* Vec 1 */
2674                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2675                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2676                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2677                         }
2678                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2679                                 /* Vec 2 */
2680                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2681                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2682                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2683                         }
2684                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2685                                 /* Vec 3 */
2686                                 if(efa->v4) 
2687                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2688                                 else
2689                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2690                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2691                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2692                         }
2693                                 /* Vec 4 */
2694                         if(efa->v4) {
2695                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2696                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2697                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2698                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2699                                 }
2700                         }
2701                 }
2702         }
2703
2704         /* useful for debugging index vs shape key index */
2705 #if 0
2706         {
2707                 EditVert *eve;
2708                 int j;
2709                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2710                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2711                         sprintf(val, "%d:%d", j, eve->keyindex);
2712                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2713                 }
2714         }
2715 #endif
2716
2717         if(v3d->zbuf) {
2718                 glEnable(GL_DEPTH_TEST);
2719                 bglPolygonOffset(rv3d->dist, 0.0f);
2720         }
2721 }
2722
2723 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2724 {
2725         EditFace *efa = EM_get_face_for_index(index);
2726
2727         if (efa->h==0) {
2728                 GPU_enable_material(efa->mat_nr+1, NULL);
2729                 return 1;
2730         }
2731         else
2732                 return 0;
2733 }
2734
2735 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2736 {
2737         EditFace *efa = EM_get_face_for_index(index);
2738
2739         return (efa->h==0);
2740 }
2741
2742 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2743 {
2744         Mesh *me = ob->data;
2745         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2746         EditEdge *eed_act = NULL;
2747         EditVert *eve_act = NULL;
2748         
2749         if (em->selected.last) {
2750                 EditSelection *ese = em->selected.last;
2751                 /* face is handeled above */
2752                 /*if (ese->type == EDITFACE ) {
2753                         efa_act = (EditFace *)ese->data;
2754                 } else */ if ( ese->type == EDITEDGE ) {
2755                         eed_act = (EditEdge *)ese->data;
2756                 } else if ( ese->type == EDITVERT ) {
2757                         eve_act = (EditVert *)ese->data;
2758                 }
2759         }
2760         
2761         EM_init_index_arrays(em, 1, 1, 1);
2762
2763         if(dt>OB_WIRE) {
2764                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2765                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2766                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2767                                 
2768                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2769                                                              draw_em_fancy__setGLSLFaceOpts, NULL);
2770                                 GPU_disable_material();
2771                                 
2772                                 glFrontFace(GL_CCW);
2773                         }
2774                         else {
2775                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2776                         }
2777                 }
2778                 else {
2779                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2780                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2781                         
2782                         glEnable(GL_LIGHTING);
2783                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2784                         
2785                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, NULL, 0);
2786                         
2787                         glFrontFace(GL_CCW);
2788                         glDisable(GL_LIGHTING);
2789                 }
2790                         
2791                 // Setup for drawing wire over, disable zbuffer
2792                 // write to show selected edge wires better
2793                 UI_ThemeColor(TH_WIRE);
2794
2795                 bglPolygonOffset(rv3d->dist, 1.0);
2796                 glDepthMask(0);
2797         } 
2798         else {
2799                 if (cageDM!=finalDM) {
2800                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2801                         finalDM->drawEdges(finalDM, 1, 0);
2802                 }
2803         }
2804         
2805         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2806                 unsigned char col1[4], col2[4], col3[4];
2807                         
2808                 UI_GetThemeColor4ubv(TH_FACE, col1);
2809                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2810                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2811                 
2812                 glEnable(GL_BLEND);
2813                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2814                 
2815                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2816                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2817                         col1[3] = 0;
2818                 
2819                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2820
2821                 glDisable(GL_BLEND);
2822                 glDepthMask(1);         // restore write in zbuffer
2823         } else if (efa_act) {
2824                 /* even if draw faces is off it would be nice to draw the stipple face
2825                  * Make all other faces zero alpha except for the active
2826                  * */
2827                 unsigned char col1[4], col2[4], col3[4];
2828                 col1[3] = col2[3] = 0; /* dont draw */
2829                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2830                 
2831                 glEnable(GL_BLEND);
2832                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2833                 
2834                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2835
2836                 glDisable(GL_BLEND);
2837                 glDepthMask(1);         // restore write in zbuffer
2838                 
2839         }
2840
2841         /* here starts all fancy draw-extra over */
2842         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2843                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2844                 
2845                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2846                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2847                 
2848         } else {
2849                 if(me->drawflag & ME_DRAWSEAMS) {
2850                         UI_ThemeColor(TH_EDGE_SEAM);
2851                         glLineWidth(2);
2852         
2853                         draw_dm_edges_seams(cageDM);
2854         
2855                         glColor3ub(0,0,0);
2856                         glLineWidth(1);
2857                 }
2858                 
2859                 if(me->drawflag & ME_DRAWSHARP) {
2860                         UI_ThemeColor(TH_EDGE_SHARP);
2861                         glLineWidth(2);
2862         
2863                         draw_dm_edges_sharp(cageDM);
2864         
2865                         glColor3ub(0,0,0);
2866                         glLineWidth(1);
2867                 }
2868         
2869                 if(me->drawflag & ME_DRAWCREASES) {
2870                         draw_dm_creases(cageDM);
2871                 }
2872                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2873                         draw_dm_bweights(scene, cageDM);
2874                 }
2875         
2876                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2877         }
2878         if(em) {
2879 // XXX          retopo_matrix_update(v3d);
2880
2881                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2882
2883                 if(me->drawflag & ME_DRAWNORMALS) {
2884                         UI_ThemeColor(TH_NORMAL);
2885                         draw_dm_face_normals(scene, cageDM);
2886                 }
2887                 if(me->drawflag & ME_DRAW_VNORMALS) {
2888                         UI_ThemeColor(TH_VNORMAL);
2889                         draw_dm_vert_normals(scene, cageDM);
2890                 }
2891
2892                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2893                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2894         }
2895
2896         if(dt>OB_WIRE) {
2897                 glDepthMask(1);
2898                 bglPolygonOffset(rv3d->dist, 0.0);
2899                 GPU_disable_material();
2900         }
2901
2902         EM_free_index_arrays();
2903 }
2904
2905 /* Mesh drawing routines */
2906
2907 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2908 {
2909         
2910         if(v3d->transp==0) {    // not when we draw the transparent pass
2911                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2912                 glDepthMask(0);
2913                 
2914                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2915                    drawFacesSolid() doesn't draw the transparent faces */
2916                 if(ob->dtx & OB_DRAWTRANSP) {
2917                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2918                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2919                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2920                         GPU_disable_material();
2921                 }
2922                 else {
2923                         dm->drawEdges(dm, 0, 1);
2924                 }
2925                                         
2926                 glLineWidth(1.0);
2927                 glDepthMask(1);
2928         }
2929 }
2930
2931 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2932 {
2933         *drawSmooth_r = 1;
2934         return 1;
2935 }
2936
2937 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2938 {
2939         Object *ob= base->object;
2940         Mesh *me = ob->data;
2941         Material *ma= give_current_material(ob, 1);
2942         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2943         eWireDrawMode draw_wire= OBDRAW_WIRE_OFF;
2944         int /* totvert,*/ totedge, totface;
2945         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2946         ModifierData *md = NULL;
2947         int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
2948
2949         if(!dm)
2950                 return;
2951
2952         /* check to draw dynamic paint colors */
2953         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
2954         {
2955                 /* check if target has an active dpaint modifier        */
2956                 if(md && (md->mode & eModifierMode_Realtime))                                   
2957                 {
2958                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2959                         /* if canvas is ready to preview vertex colors */
2960                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
2961                                 DM_get_face_data_layer(dm, CD_WEIGHT_MCOL)) {
2962                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
2963                         }
2964                 }
2965         }
2966
2967         /* Unwanted combination */
2968         if (draw_flags & DRAW_FACE_SELECT) {
2969                 draw_wire= OBDRAW_WIRE_OFF;
2970         }
2971         else if (ob->dtx & OB_DRAWWIRE) {
2972                 draw_wire= OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
2973         }
2974         
2975         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2976         totedge = dm->getNumEdges(dm);
2977         totface = dm->getNumFaces(dm);
2978         
2979         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2980         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2981
2982         if(dt==OB_BOUNDBOX) {
2983                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2984                         draw_bounding_volume(scene, ob, ob->boundtype);
2985         }
2986         else if(hasHaloMat || (totface==0 && totedge==0)) {
2987                 glPointSize(1.5);
2988                 dm->drawVerts(dm);
2989                 glPointSize(1.0);
2990         }
2991         else if(dt==OB_WIRE || totface==0) {
2992                 draw_wire= OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff  */
2993         }
2994         else if ( (draw_flags & DRAW_FACE_SELECT || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2995                   CHECK_OB_DRAWTEXTURE(v3d, dt))
2996         {
2997                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
2998                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
2999                      (base->flag & SELECT) &&
3000                      !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3001                      (draw_wire == OBDRAW_WIRE_OFF))
3002                 {
3003                         draw_mesh_object_outline(v3d, ob, dm);
3004                 }
3005
3006                 if(draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
3007                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3008
3009                         dm->drawFacesGLSL(dm, GPU_enable_material);
3010 //                      if(get_ob_property(ob, "Text"))
3011 // XXX                          draw_mesh_text(ob, 1);
3012                         GPU_disable_material();
3013
3014                         glFrontFace(GL_CCW);
3015                 }
3016                 else {
3017                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3018                 }
3019
3020                 if(!(draw_flags & DRAW_FACE_SELECT)) {
3021                         if(base->flag & SELECT)
3022                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
3023                         else
3024                                 UI_ThemeColor(TH_WIRE);
3025
3026                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3027                                 dm->drawLooseEdges(dm);
3028                 }
3029         }
3030         else if(dt==OB_SOLID) {
3031                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
3032                         /* weight paint in solid mode, special case. focus on making the weights clear
3033                          * rather than the shading, this is also forced in wire view */
3034                         GPU_enable_material(0, NULL);
3035                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, GPU_enable_material, NULL, me->mface, 1);
3036                 
3037                         bglPolygonOffset(rv3d->dist, 1.0);
3038                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3039
3040                         glEnable(GL_BLEND);
3041                         glColor4ub(255, 255, 255, 96);
3042                         glEnable(GL_LINE_STIPPLE);
3043                         glLineStipple(1, 0xAAAA);
3044
3045                         dm->drawEdges(dm, 1, 1);
3046
3047                         bglPolygonOffset(rv3d->dist, 0.0);
3048                         glDepthMask(1);
3049                         glDisable(GL_LINE_STIPPLE);
3050
3051                         GPU_disable_material();
3052                         
3053                         /* since we already draw wire as wp guide, dont draw over the top */
3054                         draw_wire= OBDRAW_WIRE_OFF;
3055                 }
3056                 else if (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW) {
3057                         /* for object selection draws no shade */
3058                         if (flag & (DRAW_PICKING|DRAW_CONSTCOLOR)) {
3059                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3060                         }
3061                         else {
3062                                 /* draw outline */
3063                                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3064                                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3065                                      (base->flag & SELECT) &&
3066                                      (draw_wire == OBDRAW_WIRE_OFF) &&
3067                                      (ob->sculpt == NULL))
3068                                 {
3069                                         draw_mesh_object_outline(v3d, ob, dm);
3070                                 }
3071
3072                                 /* materials arent compatible with vertex colors */
3073                                 GPU_end_object_materials();
3074
3075                                 GPU_enable_material(0, NULL);
3076                                 
3077                                 /* set default spec */
3078                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
3079                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
3080                                 glColor3ub(120, 120, 120);
3081                                 glDisable(GL_COLOR_MATERIAL);
3082                                 /* diffuse */
3083                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
3084                                 glEnable(GL_LIGHTING);
3085                                 glEnable(GL_COLOR_MATERIAL);
3086
3087                                 dm->drawMappedFaces(dm, NULL, GPU_enable_material, NULL, NULL, 1);
3088                                 glDisable(GL_COLOR_MATERIAL);
3089                                 glDisable(GL_LIGHTING);
3090
3091                                 GPU_disable_material();
3092                         }
3093                 }
3094                 else {
3095                         Paint *p;
3096
3097                         if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3098                              ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3099                              (base->flag & SELECT) &&
3100                              (draw_wire == OBDRAW_WIRE_OFF) &&
3101                              (ob->sculpt == NULL))
3102                         {
3103                                 draw_mesh_object_outline(v3d, ob, dm);
3104                         }
3105
3106                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
3107
3108                         glEnable(GL_LIGHTING);
3109                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3110