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