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