Object tracking; initial commit
[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,
693          * but not checks for it, so centers remain visible independt order of drawing */
694         if(v3d->zbuf)  glDepthFunc(GL_ALWAYS);
695         glEnable(GL_BLEND);
696         
697         if(special_color) {
698                 if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
699
700                 else glColor4ub(0x55, 0xCC, 0xCC, 155);
701         }
702         else {
703                 if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
704                 else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
705                 else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
706         }
707
708         circball_array_fill(verts, co, size, rv3d->viewinv);
709
710         /* enable vertex array */
711         glEnableClientState(GL_VERTEX_ARRAY);
712         glVertexPointer(3, GL_FLOAT, 0, verts);
713
714         /* 1. draw filled, blended polygon */
715         glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
716
717         /* 2. draw outline */
718         UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
719         glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
720
721         /* finishe up */
722         glDisableClientState(GL_VERTEX_ARRAY);
723
724         glDisable(GL_BLEND);
725
726         if(v3d->zbuf)  glDepthFunc(GL_LEQUAL);
727 }
728
729 /* *********** text drawing for object/particles/armature ************* */
730 static ListBase CachedText[3];
731 static int CachedTextLevel= 0;
732
733 typedef struct ViewCachedString {
734         struct ViewCachedString *next, *prev;
735         float vec[3];
736         union {
737                 unsigned char ub[4];
738                 int pack;
739         } col;
740         short sco[2];
741         short xoffs;
742         short flag;
743         int str_len, pad;
744         /* str is allocated past the end */
745 } ViewCachedString;
746
747 void view3d_cached_text_draw_begin(void)
748 {
749         ListBase *strings= &CachedText[CachedTextLevel];
750         strings->first= strings->last= NULL;
751         CachedTextLevel++;
752 }
753
754 void view3d_cached_text_draw_add(const float co[3],
755                                  const char *str,
756                                  short xoffs, short flag,
757                                  const unsigned char col[4])
758 {
759         int alloc_len= strlen(str) + 1;
760         ListBase *strings= &CachedText[CachedTextLevel-1];
761         /* TODO, replace with more efficient malloc, perhaps memarena per draw? */
762         ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString) + alloc_len, "ViewCachedString");
763
764         BLI_addtail(strings, vos);
765         copy_v3_v3(vos->vec, co);
766         vos->col.pack= *((int *)col);
767         vos->xoffs= xoffs;
768         vos->flag= flag;
769         vos->str_len= alloc_len-1;
770
771         /* allocate past the end */
772         memcpy(++vos, str, alloc_len);
773 }
774
775 void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4])
776 {
777         RegionView3D *rv3d= ar->regiondata;
778         ListBase *strings= &CachedText[CachedTextLevel-1];
779         ViewCachedString *vos;
780         int a, tot= 0;
781         
782         /* project first and test */
783         for(vos= strings->first; vos; vos= vos->next) {
784                 if(mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
785                         mul_m4_v3(mat, vos->vec);
786
787                 if(vos->flag&V3D_CACHE_TEXT_GLOBALSPACE)
788                         view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, 0);
789                 else
790                         view3d_project_short_clip(ar, vos->vec, vos->sco, 0);
791
792                 if(vos->sco[0]!=IS_CLIPPED)
793                         tot++;
794         }
795
796         if(tot) {
797                 int col_pack_prev= 0;
798
799 #if 0
800                 bglMats mats; /* ZBuffer depth vars */
801                 double ux, uy, uz;
802                 float depth;
803
804                 if(v3d->zbuf)
805                         bgl_get_mats(&mats);
806 #endif
807                 if(rv3d->rflag & RV3D_CLIPPING)
808                         for(a=0; a<6; a++)
809                                 glDisable(GL_CLIP_PLANE0+a);
810                 
811                 glMatrixMode(GL_PROJECTION);
812                 glPushMatrix();
813                 glMatrixMode(GL_MODELVIEW);
814                 glPushMatrix();
815                 ED_region_pixelspace(ar);
816                 
817                 if(depth_write) {
818                         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
819                 }
820                 else glDepthMask(0);
821                 
822                 for(vos= strings->first; vos; vos= vos->next) {
823                         /* too slow, reading opengl info while drawing is very bad,
824                          * better to see if we can use the zbuffer while in pixel space - campbell */
825 #if 0
826                         if(v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
827                                 gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
828                                 glReadPixels(ar->winrct.xmin+vos->mval[0]+vos->xoffs, ar->winrct.ymin+vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
829
830                                 if(uz > depth)
831                                         continue;
832                         }
833 #endif
834                         if(vos->sco[0]!=IS_CLIPPED) {
835                                 const char *str= (char *)(vos+1);
836
837                                 if(col_pack_prev != vos->col.pack) {
838                                         glColor3ubv(vos->col.ub);
839                                         col_pack_prev= vos->col.pack;
840                                 }
841                                 ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
842                                             BLF_draw_default_ascii :
843                                             BLF_draw_default
844                                             ) ( (float)vos->sco[0] + vos->xoffs,
845                                                 (float)vos->sco[1],
846                                                 (depth_write) ? 0.0f: 2.0f,
847                                                 str,
848                                                 vos->str_len);
849                         }
850                 }
851                 
852                 if(depth_write) {
853                         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
854                 }
855                 else glDepthMask(1);
856                 
857                 glMatrixMode(GL_PROJECTION);
858                 glPopMatrix();
859                 glMatrixMode(GL_MODELVIEW);
860                 glPopMatrix();
861
862                 if(rv3d->rflag & RV3D_CLIPPING)
863                         for(a=0; a<6; a++)
864                                 glEnable(GL_CLIP_PLANE0+a);
865         }
866         
867         if(strings->first) 
868                 BLI_freelistN(strings);
869         
870         CachedTextLevel--;
871 }
872
873 /* ******************** primitive drawing ******************* */
874
875 static void drawcube(void)
876 {
877
878         glBegin(GL_LINE_STRIP);
879                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
880                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
881                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
882         glEnd();
883
884         glBegin(GL_LINE_STRIP);
885                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
886         glEnd();
887
888         glBegin(GL_LINE_STRIP);
889                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
890         glEnd();
891
892         glBegin(GL_LINE_STRIP);
893                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
894         glEnd();
895 }
896
897 /* draws a cube on given the scaling of the cube, assuming that 
898  * all required matrices have been set (used for drawing empties)
899  */
900 static void drawcube_size(float size)
901 {
902         glBegin(GL_LINE_STRIP);
903                 glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);
904                 glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
905
906                 glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);
907                 glVertex3f(size,-size,size); glVertex3f(size,size,size);
908
909                 glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
910         glEnd();
911
912         glBegin(GL_LINE_STRIP);
913                 glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
914         glEnd();
915
916         glBegin(GL_LINE_STRIP);
917                 glVertex3f(-size,size,size); glVertex3f(size,size,size);
918         glEnd();
919
920         glBegin(GL_LINE_STRIP);
921                 glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
922         glEnd();
923 }
924
925 /* this is an unused (old) cube-drawing function based on a given size */
926 #if 0
927 static void drawcube_size(const float size[3])
928 {
929
930         glPushMatrix();
931         glScalef(size[0],  size[1],  size[2]);
932         
933
934         glBegin(GL_LINE_STRIP);
935                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
936                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
937                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
938         glEnd();
939
940         glBegin(GL_LINE_STRIP);
941                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
942         glEnd();
943
944         glBegin(GL_LINE_STRIP);
945                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
946         glEnd();
947
948         glBegin(GL_LINE_STRIP);
949                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
950         glEnd();
951         
952         glPopMatrix();
953 }
954 #endif
955
956 static void drawshadbuflimits(Lamp *la, float mat[][4])
957 {
958         float sta[3], end[3], lavec[3];
959
960         negate_v3_v3(lavec, mat[2]);
961         normalize_v3(lavec);
962
963         madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
964         madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
965
966         glBegin(GL_LINE_STRIP);
967                 glVertex3fv(sta);
968                 glVertex3fv(end);
969         glEnd();
970
971         glPointSize(3.0);
972         bglBegin(GL_POINTS);
973         bglVertex3fv(sta);
974         bglVertex3fv(end);
975         bglEnd();
976         glPointSize(1.0);
977 }
978
979
980
981 static void spotvolume(float lvec[3], float vvec[3], const float inp)
982 {
983         /* camera is at 0,0,0 */
984         float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
985
986         normalize_v3(lvec);
987         normalize_v3(vvec);                             /* is this the correct vector ? */
988
989         cross_v3_v3v3(temp,vvec,lvec);          /* equation for a plane through vvec en lvec */
990         cross_v3_v3v3(plane,lvec,temp);         /* a plane perpendicular to this, parrallel with lvec */
991
992         /* vectors are exactly aligned, use the X axis, this is arbitrary */
993         if(normalize_v3(plane) == 0.0f)
994                 plane[1]= 1.0f;
995
996         /* now we've got two equations: one of a cone and one of a plane, but we have
997         three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
998
999         /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
1000         /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
1001
1002         /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
1003         
1004         q[1] = plane[1] ; 
1005         q[2] = -plane[0] ; 
1006         q[3] = 0 ;
1007         normalize_v3(&q[1]);
1008
1009         angle = saacos(plane[2])/2.0f;
1010         co = cosf(angle);
1011         si = sqrtf(1-co*co);
1012
1013         q[0] =  co;
1014         q[1] *= si;
1015         q[2] *= si;
1016         q[3] =  0;
1017
1018         quat_to_mat3(mat1,q);
1019
1020         /* rotate lamp vector now over acos(inp) degrees */
1021         copy_v3_v3(vvec, lvec);
1022
1023         unit_m3(mat2);
1024         co = inp;
1025         si = sqrtf(1.0f-inp*inp);
1026
1027         mat2[0][0] =  co;
1028         mat2[1][0] = -si;
1029         mat2[0][1] =  si;
1030         mat2[1][1] =  co;
1031         mul_m3_m3m3(mat3,mat2,mat1);
1032
1033         mat2[1][0] =  si;
1034         mat2[0][1] = -si;
1035         mul_m3_m3m3(mat4,mat2,mat1);
1036         transpose_m3(mat1);
1037
1038         mul_m3_m3m3(mat2,mat1,mat3);
1039         mul_m3_v3(mat2,lvec);
1040         mul_m3_m3m3(mat2,mat1,mat4);
1041         mul_m3_v3(mat2,vvec);
1042
1043         return;
1044 }
1045
1046 static void draw_spot_cone(Lamp *la, float x, float z)
1047 {
1048         z= fabs(z);
1049
1050         glBegin(GL_TRIANGLE_FAN);
1051         glVertex3f(0.0f, 0.0f, -x);
1052
1053         if(la->mode & LA_SQUARE) {
1054                 glVertex3f(z, z, 0);
1055                 glVertex3f(-z, z, 0);
1056                 glVertex3f(-z, -z, 0);
1057                 glVertex3f(z, -z, 0);
1058                 glVertex3f(z, z, 0);
1059         }
1060         else {
1061                 float angle;
1062                 int a;
1063
1064                 for(a=0; a<33; a++) {
1065                         angle= a*M_PI*2/(33-1);
1066                         glVertex3f(z*cosf(angle), z*sinf(angle), 0);
1067                 }
1068         }
1069
1070         glEnd();
1071 }
1072
1073 static void draw_transp_spot_volume(Lamp *la, float x, float z)
1074 {
1075         glEnable(GL_CULL_FACE);
1076         glEnable(GL_BLEND);
1077         glDepthMask(0);
1078
1079         /* draw backside darkening */
1080         glCullFace(GL_FRONT);
1081
1082         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
1083         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
1084
1085         draw_spot_cone(la, x, z);
1086
1087         /* draw front side lighting */
1088         glCullFace(GL_BACK);
1089
1090         glBlendFunc(GL_ONE,  GL_ONE); 
1091         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
1092
1093         draw_spot_cone(la, x, z);
1094
1095         /* restore state */
1096         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1097         glDisable(GL_BLEND);
1098         glDepthMask(1);
1099         glDisable(GL_CULL_FACE);
1100         glCullFace(GL_BACK);
1101 }
1102
1103 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
1104 {
1105         Object *ob= base->object;
1106         const float pixsize= ED_view3d_pixel_size(rv3d, ob->obmat[3]);
1107         Lamp *la= ob->data;
1108         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
1109         float lampsize;
1110         float imat[4][4], curcol[4];
1111         unsigned char col[4];
1112         /* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
1113         /* the moment of view3d_draw_transp() call */
1114         const short is_view= (rv3d->persp==RV3D_CAMOB && v3d->camera == base->object);
1115         const short drawcone= ((dt > OB_WIRE) &&
1116                                !(G.f & G_PICKSEL) &&
1117                                (la->type == LA_SPOT) &&
1118                                (la->mode & LA_SHOW_CONE) &&
1119                                !(base->flag & OB_FROMDUPLI) &&
1120                                !is_view);
1121
1122         if(drawcone && !v3d->transp) {
1123                 /* in this case we need to draw delayed */
1124                 add_view3d_after(&v3d->afterdraw_transp, base, flag);
1125                 return;
1126         }
1127         
1128         /* we first draw only the screen aligned & fixed scale stuff */
1129         glPushMatrix();
1130         glLoadMatrixf(rv3d->viewmat);
1131
1132         /* lets calculate the scale: */
1133         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
1134
1135         /* and view aligned matrix: */
1136         copy_m4_m4(imat, rv3d->viewinv);
1137         normalize_v3(imat[0]);
1138         normalize_v3(imat[1]);
1139
1140         /* lamp center */
1141         copy_v3_v3(vec, ob->obmat[3]);
1142         
1143         /* for AA effects */
1144         glGetFloatv(GL_CURRENT_COLOR, curcol);
1145         curcol[3]= 0.6;
1146         glColor4fv(curcol);
1147         
1148         if(lampsize > 0.0f) {
1149
1150                 if(ob->id.us>1) {
1151                         if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
1152                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
1153                 }
1154                 
1155                 /* Inner Circle */
1156                 glEnable(GL_BLEND);
1157                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
1158                 glDisable(GL_BLEND);
1159                 drawcircball(GL_POLYGON, vec, lampsize, imat);
1160                 
1161                 /* restore */
1162                 if(ob->id.us>1)
1163                         glColor4fv(curcol);
1164                         
1165                 /* Outer circle */
1166                 circrad = 3.0f*lampsize;
1167                 setlinestyle(3);
1168
1169                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
1170
1171                 /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
1172                 if(la->type!=LA_HEMI) {
1173                         if(     (la->mode & LA_SHAD_RAY) ||
1174                                 ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT))
1175                         ) {
1176                                 drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
1177                         }
1178                 }
1179         }
1180         else {
1181                 setlinestyle(3);
1182                 circrad = 0.0f;
1183         }
1184         
1185         /* draw the pretty sun rays */
1186         if(la->type==LA_SUN) {
1187                 float v1[3], v2[3], mat[3][3];
1188                 short axis;
1189                 
1190                 /* setup a 45 degree rotation matrix */
1191                 vec_rot_to_mat3(mat, imat[2], (float)M_PI/4.0f);
1192                 
1193                 /* vectors */
1194                 mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
1195                 mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
1196                 
1197                 /* center */
1198                 glTranslatef(vec[0], vec[1], vec[2]);
1199                 
1200                 setlinestyle(3);
1201                 
1202                 glBegin(GL_LINES);
1203                 for (axis=0; axis<8; axis++) {
1204                         glVertex3fv(v1);
1205                         glVertex3fv(v2);
1206                         mul_m3_v3(mat, v1);
1207                         mul_m3_v3(mat, v2);
1208                 }
1209                 glEnd();
1210                 
1211                 glTranslatef(-vec[0], -vec[1], -vec[2]);
1212
1213         }               
1214         
1215         if (la->type==LA_LOCAL) {
1216                 if(la->mode & LA_SPHERE) {
1217                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
1218                 }
1219                 /* yafray: for photonlight also draw lightcone as for spot */
1220         }
1221         
1222         glPopMatrix();  /* back in object space */
1223         zero_v3(vec);
1224         
1225         if(is_view) {
1226                 /* skip drawing extra info */
1227         }
1228         else if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
1229                 lvec[0]=lvec[1]= 0.0; 
1230                 lvec[2] = 1.0;
1231                 x = rv3d->persmat[0][2];
1232                 y = rv3d->persmat[1][2];
1233                 z = rv3d->persmat[2][2];
1234                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
1235                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
1236                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
1237
1238                 y = cosf(la->spotsize*(float)(M_PI/360.0));
1239                 spotvolume(lvec, vvec, y);
1240                 x = -la->dist;
1241                 mul_v3_fl(lvec, x);
1242                 mul_v3_fl(vvec, x);
1243
1244                 /* draw the angled sides of the cone */
1245                 glBegin(GL_LINE_STRIP);
1246                         glVertex3fv(vvec);
1247                         glVertex3fv(vec);
1248                         glVertex3fv(lvec);
1249                 glEnd();
1250                 
1251                 z = x*sqrtf(1.0f - y*y);
1252                 x *= y;
1253
1254                 /* draw the circle/square at the end of the cone */
1255                 glTranslatef(0.0, 0.0 ,  x);
1256                 if(la->mode & LA_SQUARE) {
1257                         float tvec[3];
1258                         float z_abs= fabs(z);
1259
1260                         tvec[0]= tvec[1]= z_abs;
1261                         tvec[2]= 0.0;
1262
1263                         glBegin(GL_LINE_LOOP);
1264                                 glVertex3fv(tvec);
1265                                 tvec[1]= -z_abs; /* neg */
1266                                 glVertex3fv(tvec);
1267                                 tvec[0]= -z_abs; /* neg */
1268                                 glVertex3fv(tvec);
1269                                 tvec[1]= z_abs; /* pos */
1270                                 glVertex3fv(tvec);
1271                         glEnd();
1272                 }
1273                 else circ(0.0, 0.0, fabsf(z));
1274                 
1275                 /* draw the circle/square representing spotbl */
1276                 if(la->type==LA_SPOT) {
1277                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
1278                         /* hide line if it is zero size or overlaps with outer border,
1279                            previously it adjusted to always to show it but that seems
1280                            confusing because it doesn't show the actual blend size */
1281                         if (spotblcirc != 0 && spotblcirc != fabsf(z))
1282                                 circ(0.0, 0.0, spotblcirc);
1283                 }
1284
1285                 if(drawcone)
1286                         draw_transp_spot_volume(la, x, z);
1287
1288                 /* draw clip start, useful for wide cones where its not obvious where the start is */
1289                 glTranslatef(0.0, 0.0 , -x); /* reverse translation above */
1290                 if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1291                         float lvec_clip[3];
1292                         float vvec_clip[3];
1293                         float clipsta_fac= la->clipsta / -x;
1294
1295                         interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
1296                         interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
1297
1298                         glBegin(GL_LINE_STRIP);
1299                                 glVertex3fv(lvec_clip);
1300                                 glVertex3fv(vvec_clip);
1301                         glEnd();
1302                 }
1303         }
1304         else if ELEM(la->type, LA_HEMI, LA_SUN) {
1305                 
1306                 /* draw the line from the circle along the dist */
1307                 glBegin(GL_LINE_STRIP);
1308                         vec[2] = -circrad;
1309                         glVertex3fv(vec); 
1310                         vec[2]= -la->dist; 
1311                         glVertex3fv(vec);
1312                 glEnd();
1313                 
1314                 if(la->type==LA_HEMI) {
1315                         /* draw the hemisphere curves */
1316                         short axis, steps, dir;
1317                         float outdist, zdist, mul;
1318                         zero_v3(vec);
1319                         outdist = 0.14; mul = 1.4; dir = 1;
1320                         
1321                         setlinestyle(4);
1322                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1323                         for (axis=0; axis<4; axis++) {
1324                                 float v[3]= {0.0, 0.0, 0.0};
1325                                 zdist = 0.02;
1326                                 
1327                                 glBegin(GL_LINE_STRIP);
1328                                 
1329                                 for (steps=0; steps<6; steps++) {
1330                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
1331                                                 /* make the arcs start at the edge of the energy circle */
1332                                                 if (steps == 0) v[0] = dir*circrad;
1333                                                 else v[0] = v[0] + dir*(steps*outdist);
1334                                         } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
1335                                                 /* make the arcs start at the edge of the energy circle */
1336                                                 if (steps == 0) v[1] = dir*circrad;
1337                                                 else v[1] = v[1] + dir*(steps*outdist); 
1338                                         }
1339                 
1340                                         v[2] = v[2] - steps*zdist;
1341                                         
1342                                         glVertex3fv(v);
1343                                         
1344                                         zdist = zdist * mul;
1345                                 }
1346                                 
1347                                 glEnd();
1348                                 /* flip the direction */
1349                                 dir = -dir;
1350                         }
1351                 }
1352         } else if(la->type==LA_AREA) {
1353                 setlinestyle(3);
1354                 if(la->area_shape==LA_AREA_SQUARE) 
1355                         fdrawbox(-la->area_size*0.5f, -la->area_size*0.5f, la->area_size*0.5f, la->area_size*0.5f);
1356                 else if(la->area_shape==LA_AREA_RECT) 
1357                         fdrawbox(-la->area_size*0.5f, -la->area_sizey*0.5f, la->area_size*0.5f, la->area_sizey*0.5f);
1358
1359                 glBegin(GL_LINE_STRIP); 
1360                 glVertex3f(0.0,0.0,-circrad);
1361                 glVertex3f(0.0,0.0,-la->dist);
1362                 glEnd();
1363         }
1364         
1365         /* and back to viewspace */
1366         glLoadMatrixf(rv3d->viewmat);
1367         copy_v3_v3(vec, ob->obmat[3]);
1368
1369         setlinestyle(0);
1370         
1371         if((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
1372                 drawshadbuflimits(la, ob->obmat);
1373         }
1374         
1375         UI_GetThemeColor4ubv(TH_LAMP, col);
1376         glColor4ubv(col);
1377          
1378         glEnable(GL_BLEND);
1379         
1380         if (vec[2]>0) vec[2] -= circrad;
1381         else vec[2] += circrad;
1382         
1383         glBegin(GL_LINE_STRIP);
1384                 glVertex3fv(vec); 
1385                 vec[2]= 0; 
1386                 glVertex3fv(vec);
1387         glEnd();
1388         
1389         glPointSize(2.0);
1390         glBegin(GL_POINTS);
1391                 glVertex3fv(vec);
1392         glEnd();
1393         glPointSize(1.0);
1394         
1395         glDisable(GL_BLEND);
1396         
1397         /* restore for drawing extra stuff */
1398         glColor3fv(curcol);
1399
1400 }
1401
1402 static void draw_limit_line(float sta, float end, unsigned int col)
1403 {
1404         glBegin(GL_LINES);
1405         glVertex3f(0.0, 0.0, -sta);
1406         glVertex3f(0.0, 0.0, -end);
1407         glEnd();
1408
1409         glPointSize(3.0);
1410         glBegin(GL_POINTS);
1411         cpack(col);
1412         glVertex3f(0.0, 0.0, -sta);
1413         glVertex3f(0.0, 0.0, -end);
1414         glEnd();
1415         glPointSize(1.0);
1416 }               
1417
1418
1419 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1420 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1421 static void draw_focus_cross(float dist, float size)
1422 {
1423         glBegin(GL_LINES);
1424         glVertex3f(-size, 0.f, -dist);
1425         glVertex3f(size, 0.f, -dist);
1426         glVertex3f(0.f, -size, -dist);
1427         glVertex3f(0.f, size, -dist);
1428         glEnd();
1429 }
1430
1431 #ifdef VIEW3D_CAMERA_BORDER_HACK
1432 float view3d_camera_border_hack_col[4];
1433 short view3d_camera_border_hack_test= FALSE;
1434 #endif
1435
1436 /* ****************** draw clip data *************** */
1437
1438 static void draw_bundle_sphere(void)
1439 {
1440         static GLuint displist= 0;
1441
1442         if (displist == 0) {
1443                 GLUquadricObj *qobj;
1444
1445                 displist= glGenLists(1);
1446                 glNewList(displist, GL_COMPILE);
1447
1448                 qobj= gluNewQuadric();
1449                 gluQuadricDrawStyle(qobj, GLU_FILL);
1450                 glShadeModel(GL_SMOOTH);
1451                 gluSphere(qobj, 0.05, 8, 8);
1452                 glShadeModel(GL_FLAT);
1453                 gluDeleteQuadric(qobj);
1454
1455                 glEndList();
1456         }
1457
1458         glCallList(displist);
1459 }
1460
1461 static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1462                         MovieClip *clip, MovieTrackingObject *tracking_object, int flag)
1463 {
1464         MovieTracking *tracking= &clip->tracking;
1465         MovieTrackingTrack *track;
1466         float mat[4][4], imat[4][4];
1467         unsigned char col[4], scol[4];
1468         int bundlenr= 1;
1469         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
1470
1471         UI_GetThemeColor4ubv(TH_TEXT, col);
1472         UI_GetThemeColor4ubv(TH_SELECT, scol);
1473
1474         BKE_get_tracking_mat(scene, base->object, mat);
1475
1476         glPushMatrix();
1477
1478         if(tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1479                 /* current ogl matrix is translated in camera space, bundles should
1480                    be rendered in world space, so camera matrix should be "removed"
1481                    from current ogl matrix */
1482                 invert_m4_m4(imat, base->object->obmat);
1483
1484                 glMultMatrixf(imat);
1485                 glMultMatrixf(mat);
1486         }
1487         else {
1488                 float obmat[4][4];
1489
1490                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1491
1492                 invert_m4_m4(imat, obmat);
1493                 glMultMatrixf(imat);
1494         }
1495
1496         for (track= tracksbase->first; track; track= track->next) {
1497                 int selected= TRACK_SELECTED(track);
1498
1499                 if((track->flag&TRACK_HAS_BUNDLE)==0)
1500                         continue;
1501
1502                 if(flag&DRAW_PICKING)
1503                         glLoadName(base->selcol + (bundlenr<<16));
1504
1505                 glPushMatrix();
1506                         glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1507                         glScalef(v3d->bundle_size/0.05f, v3d->bundle_size/0.05f, v3d->bundle_size/0.05f);
1508
1509                         if(v3d->drawtype==OB_WIRE) {
1510                                 glDisable(GL_LIGHTING);
1511                                 glDepthMask(0);
1512
1513                                 if(selected) {
1514                                         if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1515                                         else UI_ThemeColor(TH_SELECT);
1516                                 } else {
1517                                         if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1518                                         else UI_ThemeColor(TH_WIRE);
1519                                 }
1520
1521                                 drawaxes(0.05f, v3d->bundle_drawtype);
1522
1523                                 glDepthMask(1);
1524                                 glEnable(GL_LIGHTING);
1525                         } else if(v3d->drawtype>OB_WIRE) {
1526                                 if(v3d->bundle_drawtype==OB_EMPTY_SPHERE) {
1527                                         /* selection outline */
1528                                         if(selected) {
1529                                                 if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1530                                                 else UI_ThemeColor(TH_SELECT);
1531
1532                                                 glDepthMask(0);
1533                                                 glLineWidth(2.f);
1534                                                 glDisable(GL_LIGHTING);
1535                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1536
1537                                                 draw_bundle_sphere();
1538
1539                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1540                                                 glEnable(GL_LIGHTING);
1541                                                 glLineWidth(1.f);
1542                                                 glDepthMask(1);
1543                                         }
1544
1545                                         if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1546                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1547
1548                                         draw_bundle_sphere();
1549                                 } else {
1550                                         glDisable(GL_LIGHTING);
1551                                         glDepthMask(0);
1552
1553                                         if(selected) {
1554                                                 if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1555                                                 else UI_ThemeColor(TH_SELECT);
1556                                         } else {
1557                                                 if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1558                                                 else UI_ThemeColor(TH_WIRE);
1559                                         }
1560
1561                                         drawaxes(0.05f, v3d->bundle_drawtype);
1562
1563                                         glDepthMask(1);
1564                                         glEnable(GL_LIGHTING);
1565                                 }
1566                         }
1567
1568                 glPopMatrix();
1569
1570                 if((flag & DRAW_PICKING)==0 && (v3d->flag2&V3D_SHOW_BUNDLENAME)) {
1571                         float pos[3];
1572                         unsigned char tcol[4];
1573
1574                         if(selected) memcpy(tcol, scol, sizeof(tcol));
1575                         else memcpy(tcol, col, sizeof(tcol));
1576
1577                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1578                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1579                 }
1580
1581                 bundlenr++;
1582         }
1583
1584         if((flag & DRAW_PICKING)==0) {
1585                 if((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) {
1586                         MovieTrackingReconstruction *reconstruction;
1587                         reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object);
1588
1589                         if(reconstruction->camnr) {
1590                                 MovieReconstructedCamera *camera= reconstruction->cameras;
1591                                 int a= 0;
1592
1593                                 glDisable(GL_LIGHTING);
1594                                 UI_ThemeColor(TH_CAMERA_PATH);
1595                                 glLineWidth(2.0f);
1596
1597                                 glBegin(GL_LINE_STRIP);
1598                                         for(a= 0; a<reconstruction->camnr; a++, camera++) {
1599                                                 glVertex3fv(camera->mat[3]);
1600                                         }
1601                                         glEnd();
1602
1603                                         glLineWidth(1.0f);
1604                                         glEnable(GL_LIGHTING);
1605                         }
1606                 }
1607         }
1608
1609         glPopMatrix();
1610 }
1611
1612 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag)
1613 {
1614         MovieTracking *tracking= &clip->tracking;
1615         MovieTrackingObject *tracking_object;
1616         float curcol[4];
1617
1618         if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
1619                 return;
1620
1621         if(v3d->flag2&V3D_RENDER_OVERRIDE)
1622                 return;
1623
1624         glGetFloatv(GL_CURRENT_COLOR, curcol);
1625
1626         glEnable(GL_LIGHTING);
1627         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1628         glEnable(GL_COLOR_MATERIAL);
1629         glShadeModel(GL_SMOOTH);
1630
1631         tracking_object= tracking->objects.first;
1632         while(tracking_object) {
1633                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object, flag);
1634
1635                 tracking_object= tracking_object->next;
1636         }
1637
1638         /* restore */
1639         glShadeModel(GL_FLAT);
1640         glDisable(GL_COLOR_MATERIAL);
1641         glDisable(GL_LIGHTING);
1642
1643         glColor4fv(curcol);
1644
1645         if(flag&DRAW_PICKING)
1646                 glLoadName(base->selcol);
1647 }
1648
1649 /* flag similar to draw_object() */
1650 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag)
1651 {
1652         /* a standing up pyramid with (0,0,0) as top */
1653         Camera *cam;
1654         Object *ob= base->object;
1655         float tvec[3];
1656         float vec[4][3], asp[2], shift[2], scale[3];
1657         int i;
1658         float drawsize;
1659         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1660         MovieClip *clip= object_get_movieclip(scene, base->object, 0);
1661
1662         /* draw data for movie clip set as active for scene */
1663         if(clip)
1664                 draw_viewport_reconstruction(scene, base, v3d, clip, flag);
1665
1666 #ifdef VIEW3D_CAMERA_BORDER_HACK
1667         if(is_view && !(G.f & G_PICKSEL)) {
1668                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1669                 view3d_camera_border_hack_test= TRUE;
1670                 return;
1671         }
1672 #endif
1673
1674         cam= ob->data;
1675
1676         scale[0]= 1.0f / len_v3(ob->obmat[0]);
1677         scale[1]= 1.0f / len_v3(ob->obmat[1]);
1678         scale[2]= 1.0f / len_v3(ob->obmat[2]);
1679
1680         camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1681                              asp, shift, &drawsize, vec);
1682
1683         glDisable(GL_LIGHTING);
1684         glDisable(GL_CULL_FACE);
1685
1686         /* camera frame */
1687         glBegin(GL_LINE_LOOP);
1688         glVertex3fv(vec[0]);
1689         glVertex3fv(vec[1]);
1690         glVertex3fv(vec[2]);
1691         glVertex3fv(vec[3]);
1692         glEnd();
1693
1694         if(is_view)
1695                 return;
1696
1697         zero_v3(tvec);
1698
1699         /* center point to camera frame */
1700         glBegin(GL_LINE_STRIP);
1701         glVertex3fv(vec[1]);
1702         glVertex3fv(tvec);
1703         glVertex3fv(vec[0]);
1704         glVertex3fv(vec[3]);
1705         glVertex3fv(tvec);
1706         glVertex3fv(vec[2]);
1707         glEnd();
1708
1709
1710         /* arrow on top */
1711         tvec[2]= vec[1][2]; /* copy the depth */
1712
1713
1714         /* draw an outline arrow for inactive cameras and filled
1715          * for active cameras. We actually draw both outline+filled
1716          * for active cameras so the wire can be seen side-on */        
1717         for (i=0;i<2;i++) {
1718                 if (i==0) glBegin(GL_LINE_LOOP);
1719                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1720                 else break;
1721
1722                 tvec[0]= shift[0] + ((-0.7f * drawsize) * scale[0]);
1723                 tvec[1]= shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1724                 glVertex3fv(tvec); /* left */
1725                 
1726                 tvec[0]= shift[0] + ((0.7f * drawsize) * scale[0]);
1727                 glVertex3fv(tvec); /* right */
1728                 
1729                 tvec[0]= shift[0];
1730                 tvec[1]= shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1731                 glVertex3fv(tvec); /* top */
1732         
1733                 glEnd();
1734         }
1735
1736         if(flag==0) {
1737                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1738                         float nobmat[4][4];
1739                         World *wrld;
1740         
1741                         /* draw in normalized object matrix space */
1742                         copy_m4_m4(nobmat, ob->obmat);
1743                         normalize_m4(nobmat);
1744
1745                         glPushMatrix();
1746                         glLoadMatrixf(rv3d->viewmat);
1747                         glMultMatrixf(nobmat);
1748
1749                         if(cam->flag & CAM_SHOWLIMITS) {
1750                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1751                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1752                                 draw_focus_cross(object_camera_dof_distance(ob), cam->drawsize);
1753                         }
1754
1755                         wrld= scene->world;
1756                         if(cam->flag & CAM_SHOWMIST) 
1757                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1758                                 
1759                         glPopMatrix();
1760                 }
1761         }
1762 }
1763
1764 /* flag similar to draw_object() */
1765 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1766                         Object *UNUSED(ob), int UNUSED(flag))
1767 {
1768         //Speaker *spk = ob->data;
1769
1770         float vec[3];
1771         int i, j;
1772
1773         glEnable(GL_BLEND);
1774
1775         for(j = 0; j < 3; j++) {
1776                 vec[2] = 0.25f * j -0.125f;
1777
1778                 glBegin(GL_LINE_LOOP);
1779                 for(i = 0; i < 16; i++) {
1780                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1781                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1782                         glVertex3fv(vec);
1783                 }
1784                 glEnd();
1785         }
1786
1787         for(j = 0; j < 4; j++) {
1788                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1789                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1790                 glBegin(GL_LINE_STRIP);
1791                 for(i = 0; i < 3; i++) {
1792                         if(i == 1) {
1793                                 vec[0] *= 0.5f;
1794                                 vec[1] *= 0.5f;
1795                         }
1796
1797                         vec[2] = 0.25f * i -0.125f;
1798                         glVertex3fv(vec);
1799                 }
1800                 glEnd();
1801         }
1802
1803         glDisable(GL_BLEND);
1804 }
1805
1806 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1807 {
1808         BPoint *bp = lt->def;
1809         float *co = dl?dl->verts:NULL;
1810         int u, v, w;
1811
1812         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1813         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1814         bglBegin(GL_POINTS);
1815
1816         for(w=0; w<lt->pntsw; w++) {
1817                 int wxt = (w==0 || w==lt->pntsw-1);
1818                 for(v=0; v<lt->pntsv; v++) {
1819                         int vxt = (v==0 || v==lt->pntsv-1);
1820                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1821                                 int uxt = (u==0 || u==lt->pntsu-1);
1822                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1823                                         if(bp->hide==0) {
1824                                                 if((bp->f1 & SELECT)==sel) {
1825                                                         bglVertex3fv(dl?co:bp->vec);
1826                                                 }
1827                                         }
1828                                 }
1829                         }
1830                 }
1831         }
1832         
1833         glPointSize(1.0);
1834         bglEnd();       
1835 }
1836
1837 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1838 {
1839         Object *obedit= vc->obedit;
1840         Lattice *lt= obedit->data;
1841         BPoint *bp = lt->editlatt->latt->def;
1842         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1843         float *co = dl?dl->verts:NULL;
1844         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1845         short s[2] = {IS_CLIPPED, 0};
1846
1847         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1848
1849         for (i=0; i<N; i++, bp++, co+=3) {
1850                 if (bp->hide==0) {
1851                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1852                         if (s[0] != IS_CLIPPED)
1853                                 func(userData, bp, s[0], s[1]);
1854                 }
1855         }
1856 }
1857
1858 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1859 {
1860         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1861
1862         if(use_wcol) {
1863                 float col[3];
1864                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1865                 
1866                 weight_to_rgb(col, mdw?mdw->weight:0.0f);
1867                 glColor3fv(col);
1868
1869         }
1870         
1871         if (dl) {
1872                 glVertex3fv(&dl->verts[index*3]);
1873         } else {
1874                 glVertex3fv(lt->def[index].vec);
1875         }
1876 }
1877
1878 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1879 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1880 {
1881         Lattice *lt= ob->data;
1882         DispList *dl;
1883         int u, v, w;
1884         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1885
1886         /* now we default make displist, this will modifiers work for non animated case */
1887         if(ob->disp.first==NULL)
1888                 lattice_calc_modifiers(scene, ob);
1889         dl= find_displist(&ob->disp, DL_VERTS);
1890         
1891         if(is_edit) {
1892                 lt= lt->editlatt->latt;
1893
1894                 cpack(0x004000);
1895                 
1896                 if(ob->defbase.first && lt->dvert) {
1897                         use_wcol= ob->actdef;
1898                         glShadeModel(GL_SMOOTH);
1899                 }
1900         }
1901         
1902         glBegin(GL_LINES);
1903         for(w=0; w<lt->pntsw; w++) {
1904                 int wxt = (w==0 || w==lt->pntsw-1);
1905                 for(v=0; v<lt->pntsv; v++) {
1906                         int vxt = (v==0 || v==lt->pntsv-1);
1907                         for(u=0; u<lt->pntsu; u++) {
1908                                 int uxt = (u==0 || u==lt->pntsu-1);
1909
1910                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1911                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1912                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1913                                 }
1914                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1915                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1916                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1917                                 }
1918                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1919                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1920                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1921                                 }
1922                         }
1923                 }
1924         }               
1925         glEnd();
1926         
1927         /* restoration for weight colors */
1928         if(use_wcol)
1929                 glShadeModel(GL_FLAT);
1930
1931         if(is_edit) {
1932                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1933                 
1934                 lattice_draw_verts(lt, dl, 0);
1935                 lattice_draw_verts(lt, dl, 1);
1936                 
1937                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1938         }
1939 }
1940
1941 /* ***************** ******************** */
1942
1943 /* Note! - foreach funcs should be called while drawing or directly after
1944  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1945  * but would not give correct results with dupli's for eg. which dont
1946  * use the object matrix in the useual way */
1947 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1948 {
1949         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index);
1950                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } *data = userData;
1951
1952         EditVert *eve = EM_get_vert_for_index(index);
1953
1954         if (eve->h==0) {
1955                 short s[2]= {IS_CLIPPED, 0};
1956
1957                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
1958                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1959                 } else {
1960                         view3d_project_short_noclip(data->vc.ar, co, s);
1961                 }
1962
1963                 if (s[0]!=IS_CLIPPED)
1964                         data->func(data->userData, eve, s[0], s[1], index);
1965         }
1966 }
1967
1968 void mesh_foreachScreenVert(
1969         ViewContext *vc,
1970         void (*func)(void *userData, EditVert *eve, int x, int y, int index),
1971         void *userData, eV3DClipTest clipVerts)
1972 {
1973         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index);
1974                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } data;
1975
1976         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1977         
1978         data.vc= *vc;
1979         data.func = func;
1980         data.userData = userData;
1981         data.clipVerts = clipVerts;
1982
1983         if(clipVerts != V3D_CLIP_TEST_OFF)
1984                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1985
1986         EM_init_index_arrays(vc->em, 1, 0, 0);
1987         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1988         EM_free_index_arrays();
1989
1990         dm->release(dm);
1991 }
1992
1993 /*  draw callback */
1994 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1995 {
1996         MVert *mv = &((MVert *)userData)[index];
1997
1998         if(!(mv->flag & ME_HIDE)) {
1999                 const char sel= mv->flag & SELECT;
2000
2001                 // TODO define selected color
2002                 if(sel) {
2003                         glColor3f(1.0f, 1.0f, 0.0f);
2004                 }
2005                 else {
2006                         glColor3f(0.0f, 0.0f, 0.0f);
2007                 }
2008
2009                 glVertex3fv(co);
2010         }
2011 }
2012
2013 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2014 {
2015         glBegin(GL_POINTS);
2016         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2017         glEnd();
2018 }
2019 static int is_co_in_region(ARegion *ar, const short co[2])
2020 {
2021         return ( (co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
2022                  (co[0] >= 0)          &&
2023                  (co[0] <  ar->winx)   &&
2024                  (co[1] >= 0)          &&
2025                  (co[1] <  ar->winy));
2026 }
2027 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
2028 {
2029         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
2030                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } *data = userData;
2031         EditEdge *eed = EM_get_edge_for_index(index);
2032         short s[2][2];
2033
2034         if (eed->h==0) {
2035                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2036                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
2037                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
2038                 }
2039                 else {
2040                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
2041                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
2042
2043                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2044                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
2045                                      !is_co_in_region(data->vc.ar, s[1]))
2046                                 {
2047                                         return;
2048                                 }
2049                         }
2050                 }
2051
2052                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2053         }
2054 }
2055
2056 void mesh_foreachScreenEdge(
2057         ViewContext *vc,
2058         void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index),
2059         void *userData, eV3DClipTest clipVerts)
2060 {
2061         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
2062                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } data;
2063         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2064
2065         data.vc= *vc;
2066         data.func = func;
2067         data.userData = userData;
2068         data.clipVerts = clipVerts;
2069
2070         if(clipVerts != V3D_CLIP_TEST_OFF)
2071                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2072
2073         EM_init_index_arrays(vc->em, 0, 1, 0);
2074         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2075         EM_free_index_arrays();
2076
2077         dm->release(dm);
2078 }
2079
2080 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2081 {
2082         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
2083         EditFace *efa = EM_get_face_for_index(index);
2084         short s[2];
2085
2086         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
2087                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
2088
2089                 if (s[0] != IS_CLIPPED) {
2090                         data->func(data->userData, efa, s[0], s[1], index);
2091                 }
2092         }
2093 }
2094
2095 void mesh_foreachScreenFace(
2096         ViewContext *vc,
2097         void (*func)(void *userData, EditFace *efa, int x, int y, int index),
2098         void *userData)
2099 {
2100         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
2101         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2102
2103         data.vc= *vc;
2104         data.func = func;
2105         data.userData = userData;
2106
2107         //if(clipVerts)
2108         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2109
2110         EM_init_index_arrays(vc->em, 0, 0, 1);
2111         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2112         EM_free_index_arrays();
2113
2114         dm->release(dm);
2115 }
2116
2117 void nurbs_foreachScreenVert(
2118         ViewContext *vc,
2119         void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2120         void *userData)
2121 {
2122         Curve *cu= vc->obedit->data;
2123         short s[2] = {IS_CLIPPED, 0};
2124         Nurb *nu;
2125         int i;
2126         ListBase *nurbs= curve_editnurbs(cu);
2127
2128         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2129
2130         for (nu= nurbs->first; nu; nu=nu->next) {
2131                 if(nu->type == CU_BEZIER) {
2132                         for (i=0; i<nu->pntsu; i++) {
2133                                 BezTriple *bezt = &nu->bezt[i];
2134
2135                                 if(bezt->hide==0) {
2136                                         
2137                                         if(cu->drawflag & CU_HIDE_HANDLES) {
2138                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2139                                                 if (s[0] != IS_CLIPPED)
2140                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2141                                         } else {
2142                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
2143                                                 if (s[0] != IS_CLIPPED)
2144                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2145                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2146                                                 if (s[0] != IS_CLIPPED)
2147                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2148                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
2149                                                 if (s[0] != IS_CLIPPED)
2150                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2151                                         }
2152                                 }
2153                         }
2154                 }
2155                 else {
2156                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2157                                 BPoint *bp = &nu->bp[i];
2158
2159                                 if(bp->hide==0) {
2160                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
2161                                         if (s[0] != IS_CLIPPED)
2162                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2163                                 }
2164                         }
2165                 }
2166         }
2167 }
2168
2169 /* ************** DRAW MESH ****************** */
2170
2171 /* First section is all the "simple" draw routines, 
2172  * ones that just pass some sort of primitive to GL,
2173  * with perhaps various options to control lighting,
2174  * color, etc.
2175  *
2176  * These routines should not have user interface related
2177  * logic!!!
2178  */
2179
2180 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2181 {
2182         ToolSettings *ts= ((Scene *)userData)->toolsettings;
2183         EditFace *efa = EM_get_face_for_index(index);
2184
2185         if (efa->h==0 && efa->fgonf!=EM_FGON) {
2186                 glVertex3fv(cent);
2187                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
2188                                         cent[1] + no[1]*ts->normalsize,
2189                                         cent[2] + no[2]*ts->normalsize);
2190         }
2191 }
2192 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
2193 {
2194         glBegin(GL_LINES);
2195         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
2196         glEnd();
2197 }
2198
2199 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2200 {
2201         EditFace *efa = EM_get_face_for_index(index);
2202         int sel = *((int*) userData);
2203
2204         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
2205                 bglVertex3fv(cent);
2206         }
2207 }
2208 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
2209 {
2210         bglBegin(GL_POINTS);
2211         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
2212         bglEnd();
2213 }
2214
2215 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2216 {
2217         Scene *scene= (Scene *)userData;
2218         ToolSettings *ts= scene->toolsettings;
2219         EditVert *eve = EM_get_vert_for_index(index);
2220
2221         if (eve->h==0) {
2222                 glVertex3fv(co);
2223
2224                 if (no_f) {
2225                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
2226                                                 co[1] + no_f[1]*ts->normalsize,
2227                                                 co[2] + no_f[2]*ts->normalsize);
2228                 } else {
2229                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
2230                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
2231                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
2232                 }
2233         }
2234 }
2235 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
2236 {
2237         glBegin(GL_LINES);
2238         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
2239         glEnd();
2240 }
2241
2242         /* Draw verts with color set based on selection */
2243 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2244 {
2245         struct { int sel; EditVert *eve_act; } * data = userData;
2246         EditVert *eve = EM_get_vert_for_index(index);
2247
2248         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
2249                 /* draw active larger - need to stop/start point drawing for this :/ */
2250                 if (eve==data->eve_act) {
2251                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2252                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2253                         
2254                         bglEnd();
2255                         
2256                         glPointSize(size);
2257                         bglBegin(GL_POINTS);
2258                         bglVertex3fv(co);
2259                         bglEnd();
2260                         
2261                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2262                         glPointSize(size);
2263                         bglBegin(GL_POINTS);
2264                 } else {
2265                         bglVertex3fv(co);
2266                 }
2267         }
2268 }
2269
2270 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
2271 {
2272         struct { int sel; EditVert *eve_act; } data;
2273         data.sel = sel;
2274         data.eve_act = eve_act;
2275
2276         bglBegin(GL_POINTS);
2277         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2278         bglEnd();
2279 }
2280
2281         /* Draw edges with color set based on selection */
2282 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2283 {
2284         EditEdge *eed = EM_get_edge_for_index(index);
2285         //unsigned char **cols = userData, *col;
2286         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
2287         unsigned char *col;
2288
2289         if (eed->h==0) {
2290                 if (eed==data->eed_act) {
2291                         glColor4ubv(data->actCol);
2292                 } else {
2293                         if (eed->f&SELECT) {
2294                                 col = data->selCol;
2295                         } else {
2296                                 col = data->baseCol;
2297                         }
2298                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2299                         if (col[3]==0) return 0;
2300                         
2301                         glColor4ubv(col);
2302                 }
2303                 return 1;
2304         } else {
2305                 return 0;
2306         }
2307 }
2308 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
2309 {
2310         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
2311         
2312         data.baseCol = baseCol;
2313         data.selCol = selCol;
2314         data.actCol = actCol;
2315         data.eed_act = eed_act;
2316         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2317 }
2318
2319         /* Draw edges */
2320 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2321 {
2322         return EM_get_edge_for_index(index)->h==0;
2323 }
2324 static void draw_dm_edges(DerivedMesh *dm) 
2325 {
2326         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2327 }
2328
2329         /* Draw edges with color interpolated based on selection */
2330 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2331 {
2332         return EM_get_edge_for_index(index)->h==0;
2333 }
2334 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2335 {
2336         EditEdge *eed = EM_get_edge_for_index(index);
2337         unsigned char **cols = userData;
2338         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2339         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2340
2341         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2342                                 col0[1] + (col1[1]-col0[1])*t,
2343                                 col0[2] + (col1[2]-col0[2])*t,
2344                                 col0[3] + (col1[3]-col0[3])*t);
2345 }
2346
2347 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2348 {
2349         unsigned char *cols[2];
2350         cols[0]= baseCol;
2351         cols[1]= selCol;
2352         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2353 }
2354
2355         /* Draw only seam edges */
2356 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2357 {
2358         EditEdge *eed = EM_get_edge_for_index(index);
2359
2360         return (eed->h==0 && eed->seam);
2361 }
2362 static void draw_dm_edges_seams(DerivedMesh *dm)
2363 {
2364         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2365 }
2366
2367         /* Draw only sharp edges */
2368 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2369 {
2370         EditEdge *eed = EM_get_edge_for_index(index);
2371
2372         return (eed->h==0 && eed->sharp);
2373 }
2374 static void draw_dm_edges_sharp(DerivedMesh *dm)
2375 {
2376         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2377 }
2378
2379
2380         /* Draw faces with color set based on selection
2381          * return 2 for the active face so it renders with stipple enabled */
2382 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2383 {
2384         struct { DerivedMesh *dm; unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2385         EditFace *efa = EM_get_face_for_index(index);
2386         unsigned char *col;
2387         
2388         if (efa->h==0) {
2389                 if (efa == data->efa_act) {
2390                         glColor4ubv(data->cols[2]);
2391                         return 2; /* stipple */
2392                 } else {
2393                         col = data->cols[(efa->f&SELECT)?1:0];
2394                         if (col[3]==0) return 0;
2395                         glColor4ubv(col);
2396                         return 1;
2397                 }
2398         }
2399         return 0;
2400 }
2401
2402 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2403 {
2404         struct { DerivedMesh *dm; unsigned char *cols[3]; EditFace *efa_act; } *data = userData;
2405         int *orig_index= DM_get_face_data_layer(data->dm, CD_ORIGINDEX);
2406         EditFace *efa;
2407         EditFace *next_efa;
2408         unsigned char *col, *next_col;
2409
2410         if(!orig_index)
2411                 return 0;
2412
2413         efa= EM_get_face_for_index(orig_index[index]);
2414         next_efa= EM_get_face_for_index(orig_index[next_index]);
2415
2416         if(efa == next_efa)
2417                 return 1;
2418
2419         if(efa == data->efa_act || next_efa == data->efa_act)
2420                 return 0;
2421
2422         col = data->cols[(efa->f&SELECT)?1:0];
2423         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2424
2425         if(col[3]==0 || next_col[3]==0)
2426                 return 0;
2427
2428         return col == next_col;
2429 }
2430
2431 /* also draws the active face */
2432 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2433 {
2434         struct { DerivedMesh *dm; unsigned char *cols[3]; EditFace *efa_act; } data;
2435         data.dm= dm;
2436         data.cols[0] = baseCol;
2437         data.cols[1] = selCol;
2438         data.cols[2] = actCol;
2439         data.efa_act = efa_act;
2440
2441         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2442 }
2443
2444 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2445 {
2446         EditEdge *eed = EM_get_edge_for_index(index);
2447
2448         if (eed->h==0 && eed->crease != 0.0f) {
2449                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2450                 return 1;
2451         } else {
2452                 return 0;
2453         }
2454 }
2455 static void draw_dm_creases(DerivedMesh *dm)
2456 {
2457         glLineWidth(3.0);
2458         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2459         glLineWidth(1.0);
2460 }
2461
2462 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2463 {
2464         EditEdge *eed = EM_get_edge_for_index(index);
2465
2466         if (eed->h==0 && eed->bweight != 0.0f) {
2467                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2468                 return 1;
2469         } else {
2470                 return 0;
2471         }
2472 }
2473 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2474 {
2475         EditVert *eve = EM_get_vert_for_index(index);
2476
2477         if (eve->h==0 && eve->bweight != 0.0f) {
2478                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2479                 bglVertex3fv(co);
2480         }
2481 }
2482 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2483 {
2484         ToolSettings *ts= scene->toolsettings;
2485
2486         if (ts->selectmode & SCE_SELECT_VERTEX) {
2487                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2488                 bglBegin(GL_POINTS);
2489                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2490                 bglEnd();
2491         }
2492         else {
2493                 glLineWidth(3.0);
2494                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2495                 glLineWidth(1.0);
2496         }
2497 }
2498
2499 /* Second section of routines: Combine first sets to form fancy
2500  * drawing routines (for example rendering twice to get overlays).
2501  *
2502  * Also includes routines that are basic drawing but are too
2503  * specialized to be split out (like drawing creases or measurements).
2504  */
2505
2506 /* EditMesh drawing routines*/
2507
2508 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2509                                 DerivedMesh *cageDM, EditVert *eve_act)
2510 {
2511         ToolSettings *ts= scene->toolsettings;
2512         int sel;
2513
2514         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2515
2516         for (sel=0; sel<2; sel++) {
2517                 unsigned char col[4], fcol[4];
2518                 int pass;
2519
2520                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2521                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2522
2523                 for (pass=0; pass<2; pass++) {
2524                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2525                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2526
2527                         if (pass==0) {
2528                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2529                                         glDisable(GL_DEPTH_TEST);
2530                                                 
2531                                         glEnable(GL_BLEND);
2532                                 } else {
2533                                         continue;
2534                                 }
2535
2536                                 size = (size > 2.1f ? size/2.0f:size);
2537                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2538                                 col[3] = fcol[3] = 100;
2539                         } else {
2540                                 col[3] = fcol[3] = 255;
2541                         }
2542                                 
2543                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2544                                 glPointSize(size);
2545                                 glColor4ubv(col);
2546                                 draw_dm_verts(cageDM, sel, eve_act);
2547                         }
2548                         
2549                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2550                                 glPointSize(fsize);
2551                                 glColor4ubv(fcol);
2552                                 draw_dm_face_centers(cageDM, sel);
2553                         }
2554                         
2555                         if (pass==0) {
2556                                 glDisable(GL_BLEND);
2557                                 glEnable(GL_DEPTH_TEST);
2558                         }
2559                 }
2560         }
2561
2562         if(v3d->zbuf) glDepthMask(1);
2563         glPointSize(1.0);
2564 }
2565
2566 static void draw_em_fancy_edges(Scene *scene, View3D *v3d,
2567                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2568                                 EditEdge *eed_act)
2569 {
2570         ToolSettings *ts= scene->toolsettings;
2571         int pass;
2572         unsigned char wireCol[4], selCol[4], actCol[4];
2573
2574         /* since this function does transparant... */
2575         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2576         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2577         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2578         
2579         /* when sel only is used, dont render wire, only selected, this is used for
2580          * textured draw mode when the 'edges' option is disabled */
2581         if (sel_only)
2582                 wireCol[3] = 0;
2583
2584         for (pass=0; pass<2; pass++) {
2585                         /* show wires in transparant when no zbuf clipping for select */
2586                 if (pass==0) {
2587                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2588                                 glEnable(GL_BLEND);
2589                                 glDisable(GL_DEPTH_TEST);
2590                                 selCol[3] = 85;
2591                                 if (!sel_only) wireCol[3] = 85;
2592                         } else {
2593                                 continue;
2594                         }
2595                 } else {
2596                         selCol[3] = 255;
2597                         if (!sel_only) wireCol[3] = 255;
2598                 }
2599
2600                 if(ts->selectmode == SCE_SELECT_FACE) {
2601                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2602                 }       
2603                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2604                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2605                                 glShadeModel(GL_SMOOTH);
2606                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2607                                 glShadeModel(GL_FLAT);
2608                         } else {
2609                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2610                         }
2611                 }
2612                 else {
2613                         if (!sel_only) {
2614                                 glColor4ubv(wireCol);
2615                                 draw_dm_edges(cageDM);
2616                         }
2617                 }
2618
2619                 if (pass==0) {
2620                         glDisable(GL_BLEND);
2621                         glEnable(GL_DEPTH_TEST);
2622                 }
2623         }
2624 }       
2625
2626 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d,
2627                                   Object *ob, EditMesh *em, UnitSettings *unit)
2628 {
2629         Mesh *me= ob->data;
2630         EditEdge *eed;
2631         EditFace *efa;
2632         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2633         float fvec[3];
2634         char val[32]; /* Stores the measurement display text here */
2635         const char *conv_float; /* Use a float conversion matching the grid size */
2636         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2637         float area; /* area of the face */
2638         float grid= unit->system ? unit->scale_length : v3d->grid;
2639         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2640         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2641         const int do_moving= G.moving;
2642
2643         /* make the precision of the pronted value proportionate to the gridsize */
2644
2645         if (grid < 0.01f)               conv_float= "%.6g";
2646         else if (grid < 0.1f)   conv_float= "%.5g";
2647         else if (grid < 1.0f)   conv_float= "%.4g";
2648         else if (grid < 10.0f)  conv_float= "%.3g";
2649         else                                    conv_float= "%.2g";
2650
2651         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2652                 glDisable(GL_DEPTH_TEST);
2653
2654         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2655         
2656         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2657                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2658
2659                 for(eed= em->edges.first; eed; eed= eed->next) {
2660                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2661                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2662                                 copy_v3_v3(v1, eed->v1->co);
2663                                 copy_v3_v3(v2, eed->v2->co);
2664
2665                                 mid_v3_v3v3(vmid, v1, v2);
2666
2667                                 if(do_global) {
2668                                         mul_mat3_m4_v3(ob->obmat, v1);
2669                                         mul_mat3_m4_v3(ob->obmat, v2);
2670                                 }
2671                                 if(unit->system)
2672                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2673                                 else
2674                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2675
2676                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2677                         }
2678                 }
2679         }
2680
2681         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2682 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2683                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2684                 
2685                 for(efa= em->faces.first; efa; efa= efa->next) {
2686                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2687                                 copy_v3_v3(v1, efa->v1->co);
2688                                 copy_v3_v3(v2, efa->v2->co);
2689                                 copy_v3_v3(v3, efa->v3->co);
2690                                 if (efa->v4) {
2691                                         copy_v3_v3(v4, efa->v4->co);
2692                                 }
2693                                 if(do_global) {
2694                                         mul_mat3_m4_v3(ob->obmat, v1);
2695                                         mul_mat3_m4_v3(ob->obmat, v2);
2696                                         mul_mat3_m4_v3(ob->obmat, v3);
2697                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2698                                 }
2699                                 
2700                                 if (efa->v4)
2701                                         area=  area_quad_v3(v1, v2, v3, v4);
2702                                 else
2703                                         area = area_tri_v3(v1, v2, v3);
2704
2705                                 if(unit->system)
2706                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2707                                 else
2708                                         sprintf(val, conv_float, area);
2709
2710                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2711                         }
2712                 }
2713         }
2714
2715         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2716                 EditEdge *e1, *e2, *e3, *e4;
2717                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2718                 for(efa= em->faces.first; efa; efa= efa->next) {
2719                         copy_v3_v3(v1, efa->v1->co);
2720                         copy_v3_v3(v2, efa->v2->co);
2721                         copy_v3_v3(v3, efa->v3->co);
2722                         if(efa->v4) {
2723                                 copy_v3_v3(v4, efa->v4->co); 
2724                         }
2725                         else {
2726                                 copy_v3_v3(v4, v3);
2727                         }
2728                         if(do_global) {
2729                                 mul_mat3_m4_v3(ob->obmat, v1);
2730                                 mul_mat3_m4_v3(ob->obmat, v2);
2731                                 mul_mat3_m4_v3(ob->obmat, v3);
2732                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2733                         }
2734                         
2735                         e1= efa->e1;
2736                         e2= efa->e2;
2737                         e3= efa->e3;
2738                         if(efa->e4) e4= efa->e4; else e4= e3;
2739                         
2740                         /* Calculate the angles */
2741                                 
2742                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2743                                 /* Vec 1 */
2744                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2745                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2746                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2747                         }
2748                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2749                                 /* Vec 2 */
2750                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2751                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2752                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2753                         }
2754                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2755                                 /* Vec 3 */
2756                                 if(efa->v4) 
2757                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2758                                 else
2759                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2760                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2761                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2762                         }
2763                                 /* Vec 4 */
2764                         if(efa->v4) {
2765                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2766                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2767                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2768                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2769                                 }
2770                         }
2771                 }
2772         }
2773
2774         /* useful for debugging index vs shape key index */
2775 #if 0
2776         {
2777                 EditVert *eve;
2778                 int j;
2779                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2780                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2781                         sprintf(val, "%d:%d", j, eve->keyindex);
2782                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2783                 }
2784         }
2785 #endif
2786
2787         if(v3d->zbuf) {
2788                 glEnable(GL_DEPTH_TEST);
2789                 bglPolygonOffset(rv3d->dist, 0.0f);
2790         }
2791 }
2792
2793 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2794 {
2795         EditFace *efa = EM_get_face_for_index(index);
2796
2797         if (efa->h==0) {
2798                 GPU_enable_material(efa->mat_nr+1, NULL);
2799                 return 1;
2800         }
2801         else
2802                 return 0;
2803 }
2804
2805 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2806 {
2807         EditFace *efa = EM_get_face_for_index(index);
2808
2809         return (efa->h==0);
2810 }
2811
2812 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2813                           Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2814 {
2815         Mesh *me = ob->data;
2816         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2817         EditEdge *eed_act = NULL;
2818         EditVert *eve_act = NULL;
2819         
2820         if (em->selected.last) {
2821                 EditSelection *ese = em->selected.last;
2822                 /* face is handeled above */
2823                 /*if (ese->type == EDITFACE ) {
2824                         efa_act = (EditFace *)ese->data;
2825                 } else */ if ( ese->type == EDITEDGE ) {
2826                         eed_act = (EditEdge *)ese->data;
2827                 } else if ( ese->type == EDITVERT ) {
2828                         eve_act = (EditVert *)ese->data;
2829                 }
2830         }
2831         
2832         EM_init_index_arrays(em, 1, 1, 1);
2833
2834         if(dt>OB_WIRE) {
2835                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2836                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2837                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2838
2839                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2840                                                              draw_em_fancy__setGLSLFaceOpts, em);
2841                                 GPU_disable_material();
2842
2843                                 glFrontFace(GL_CCW);
2844                         }
2845                         else {
2846                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2847                         }
2848                 }
2849                 else {
2850                         /* 3 floats for position,
2851                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
2852                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2853
2854                         glEnable(GL_LIGHTING);
2855                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2856                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, NULL, 0);
2857
2858                         glFrontFace(GL_CCW);
2859                         glDisable(GL_LIGHTING);
2860                 }
2861                         
2862                 // Setup for drawing wire over, disable zbuffer
2863                 // write to show selected edge wires better
2864                 UI_ThemeColor(TH_WIRE);
2865
2866                 bglPolygonOffset(rv3d->dist, 1.0);
2867                 glDepthMask(0);
2868         } 
2869         else {
2870                 if (cageDM!=finalDM) {
2871                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2872                         finalDM->drawEdges(finalDM, 1, 0);
2873                 }
2874         }
2875         
2876         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2877                 unsigned char col1[4], col2[4], col3[4];
2878                         
2879                 UI_GetThemeColor4ubv(TH_FACE, col1);
2880                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2881                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2882                 
2883                 glEnable(GL_BLEND);
2884                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2885                 
2886                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2887                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2888                         col1[3] = 0;
2889                 
2890                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2891
2892                 glDisable(GL_BLEND);
2893                 glDepthMask(1);         // restore write in zbuffer
2894         } else if (efa_act) {
2895                 /* even if draw faces is off it would be nice to draw the stipple face
2896                  * Make all other faces zero alpha except for the active
2897                  * */
2898                 unsigned char col1[4], col2[4], col3[4];
2899                 col1[3] = col2[3] = 0; /* dont draw */
2900                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2901                 
2902                 glEnable(GL_BLEND);
2903                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2904                 
2905                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2906
2907                 glDisable(GL_BLEND);
2908                 glDepthMask(1);         // restore write in zbuffer
2909                 
2910         }
2911
2912         /* here starts all fancy draw-extra over */
2913         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2914                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2915                 
2916                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2917                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2918                 
2919         } else {
2920                 if(me->drawflag & ME_DRAWSEAMS) {
2921                         UI_ThemeColor(TH_EDGE_SEAM);
2922                         glLineWidth(2);
2923         
2924                         draw_dm_edges_seams(cageDM);
2925         
2926                         glColor3ub(0,0,0);
2927                         glLineWidth(1);
2928                 }
2929                 
2930                 if(me->drawflag & ME_DRAWSHARP) {
2931                         UI_ThemeColor(TH_EDGE_SHARP);
2932                         glLineWidth(2);
2933         
2934                         draw_dm_edges_sharp(cageDM);
2935         
2936                         glColor3ub(0,0,0);
2937                         glLineWidth(1);
2938                 }
2939         
2940                 if(me->drawflag & ME_DRAWCREASES) {
2941                         draw_dm_creases(cageDM);
2942                 }
2943                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2944                         draw_dm_bweights(scene, cageDM);
2945                 }
2946
2947                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2948         }
2949         if(em) {
2950 // XXX          retopo_matrix_update(v3d);
2951
2952                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2953
2954                 if(me->drawflag & ME_DRAWNORMALS) {
2955                         UI_ThemeColor(TH_NORMAL);
2956                         draw_dm_face_normals(scene, cageDM);
2957                 }
2958                 if(me->drawflag & ME_DRAW_VNORMALS) {
2959                         UI_ThemeColor(TH_VNORMAL);
2960                         draw_dm_vert_normals(scene, cageDM);
2961                 }
2962
2963                 if ( (me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG)) &&
2964                      !(v3d->flag2 & V3D_RENDER_OVERRIDE))
2965                 {
2966                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2967                 }
2968         }
2969
2970         if(dt>OB_WIRE) {
2971                 glDepthMask(1);
2972                 bglPolygonOffset(rv3d->dist, 0.0);
2973                 GPU_disable_material();
2974         }
2975
2976         EM_free_index_arrays();
2977 }
2978
2979 /* Mesh drawing routines */
2980
2981 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2982 {
2983         
2984         if(v3d->transp==0) {    // not when we draw the transparent pass
2985                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2986                 glDepthMask(0);
2987                 
2988                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2989                    drawFacesSolid() doesn't draw the transparent faces */
2990                 if(ob->dtx & OB_DRAWTRANSP) {
2991                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2992                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2993                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2994                         GPU_disable_material();
2995                 }
2996                 else {
2997                         dm->drawEdges(dm, 0, 1);
2998                 }
2999                                         
3000                 glLineWidth(1.0);
3001                 glDepthMask(1);
3002         }
3003 }
3004
3005 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
3006 {
3007         *drawSmooth_r = 1;
3008         return 1;
3009 }
3010
3011 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
3012 {
3013         Object *ob= base->object;
3014         Mesh *me = ob->data;
3015         Material *ma= give_current_material(ob, 1);
3016         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3017         eWireDrawMode draw_wire= OBDRAW_WIRE_OFF;
3018         int /* totvert,*/ totedge, totface;
3019         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
3020         ModifierData *md = NULL;
3021         const short is_obact= (ob != NULL && ob == OBACT);
3022         int draw_flags = (is_obact && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3023
3024         if(!dm)
3025                 return;
3026
3027         /* check to draw dynamic paint colors */
3028         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
3029         {
3030                 /* check if target has an active dpaint modifier        */
3031                 if(md && (md->mode & eModifierMode_Realtime))                                   
3032                 {
3033                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
3034                         /* if canvas is ready to preview vertex colors */
3035                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
3036                                 DM_get_face_data_layer(dm, CD_WEIGHT_MCOL)) {
3037                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
3038                         }
3039                 }
3040         }
3041
3042         /* Unwanted combination */
3043         if (draw_flags & DRAW_FACE_SELECT) {
3044                 draw_wire= OBDRAW_WIRE_OFF;
3045         }
3046         else if (ob->dtx & OB_DRAWWIRE) {
3047                 draw_wire= OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3048         }
3049         
3050         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3051         totedge = dm->getNumEdges(dm);
3052         totface = dm->getNumFaces(dm);
3053         
3054         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3055         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3056
3057         if(dt==OB_BOUNDBOX) {
3058                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
3059                         draw_bounding_volume(scene, ob, ob->boundtype);
3060         }
3061         else if(hasHaloMat || (totface==0 && totedge==0)) {
3062                 glPointSize(1.5);
3063                 dm->drawVerts(dm);
3064                 glPointSize(1.0);
3065         }
3066         else if(dt==OB_WIRE || totface==0) {
3067                 draw_wire= OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff  */
3068         }
3069         else if ( (draw_flags & DRAW_FACE_SELECT || (is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
3070                   CHECK_OB_DRAWTEXTURE(v3d, dt))
3071         {
3072                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3073                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3074                      (base->flag & SELECT) &&
3075                      !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3076                      (draw_wire == OBDRAW_WIRE_OFF))
3077                 {
3078                         draw_mesh_object_outline(v3d, ob, dm);
3079                 }
3080
3081                 if(draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
3082                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3083
3084                         dm->drawFacesGLSL(dm, GPU_enable_material);
3085 //                      if(get_ob_property(ob, "Text"))
3086 // XXX                          draw_mesh_text(ob, 1);
3087                         GPU_disable_material();
3088
3089                         glFrontFace(GL_CCW);
3090                 }
3091                 else {
3092                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3093                 }
3094
3095                 if(!(draw_flags & DRAW_FACE_SELECT)) {
3096                         if(base->flag & SELECT)
3097                                 UI_ThemeColor(is_obact ? TH_ACTIVE : TH_SELECT);
3098                         else
3099                                 UI_ThemeColor(TH_WIRE);
3100
3101                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3102                                 dm->drawLooseEdges(dm);
3103                 }
3104         }
3105         else if(dt==OB_SOLID) {
3106                 if(is_obact && ob->mode & OB_MODE_WEIGHT_PAINT) {
3107                         /* weight paint in solid mode, special case. focus on making the weights clear
3108                          * rather than the shading, this is also forced in wire view */
3109                         GPU_enable_material(0, NULL);
3110                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, GPU_enable_material, NULL, me->mface, 1);
3111                 
3112                         bglPolygonOffset(rv3d->dist, 1.0);
3113                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3114
3115                         glEnable(GL_BLEND);
3116                         glColor4ub(255, 255, 255, 96);
3117                         glEnable(GL_LINE_STIPPLE);
3118                         glLineStipple(1, 0xAAAA);
3119
3120                         dm->drawEdges(dm, 1, 1);
3121
3122                         bglPolygonOffset(rv3d->dist, 0.0);
3123                         glDepthMask(1);
3124                         glDisable(GL_LINE_STIPPLE);
3125
3126               &nb