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