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