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