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