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