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