Made minor revisions (no functional changes).
[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         /* Draw only Freestyle feature edges */
2294 static int draw_dm_edges_freestyle__setDrawOptions(void *UNUSED(userData), int index)
2295 {
2296         EditEdge *eed = EM_get_edge_for_index(index);
2297
2298         return (eed->h==0 && eed->freestyle);
2299 }
2300 static void draw_dm_edges_freestyle(DerivedMesh *dm)
2301 {
2302         dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, NULL);
2303 }
2304
2305         /* Draw faces with color set based on selection
2306          * return 2 for the active face so it renders with stipple enabled */
2307 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2308 {
2309         struct { unsigned char *cols[4]; EditFace *efa_act; } * data = userData;
2310         EditFace *efa = EM_get_face_for_index(index);
2311         unsigned char *col;
2312         
2313         if (efa->h==0) {
2314                 if (efa == data->efa_act) {
2315                         glColor4ubv(data->cols[3]);
2316                         return 2; /* stipple */
2317                 } else {
2318                         col = data->cols[(efa->f & SELECT) ? 1 : (efa->flag & ME_FREESTYLE_FACE) ? 2 : 0];
2319                         if (col[3]==0) return 0;
2320                         glColor4ubv(col);
2321                         return 1;
2322                 }
2323         }
2324         return 0;
2325 }
2326
2327 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2328 {
2329         struct { unsigned char *cols[4]; EditFace *efa_act; } * data = userData;
2330         EditFace *efa = EM_get_face_for_index(index);
2331         EditFace *next_efa = EM_get_face_for_index(next_index);
2332         unsigned char *col, *next_col;
2333
2334         if(efa == next_efa)
2335                 return 1;
2336
2337         if(efa == data->efa_act || next_efa == data->efa_act)
2338                 return 0;
2339
2340         col = data->cols[(efa->f & SELECT) ? 1 : (efa->flag & ME_FREESTYLE_FACE) ? 2 : 0];
2341         next_col = data->cols[(next_efa->f & SELECT) ? 1 : (next_efa->flag & ME_FREESTYLE_FACE) ? 2 : 0];
2342
2343         if(col[3]==0 || next_col[3]==0)
2344                 return 0;
2345
2346         return col == next_col;
2347 }
2348
2349 /* also draws the active face */
2350 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *markCol, unsigned char *actCol, EditFace *efa_act) 
2351 {
2352         struct { unsigned char *cols[4]; EditFace *efa_act; } data;
2353         data.cols[0] = baseCol;
2354         data.cols[1] = selCol;
2355         data.cols[2] = markCol;
2356         data.cols[3] = actCol;
2357         data.efa_act = efa_act;
2358
2359         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2360 }
2361
2362 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2363 {
2364         EditEdge *eed = EM_get_edge_for_index(index);
2365
2366         if (eed->h==0 && eed->crease != 0.0f) {
2367                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2368                 return 1;
2369         } else {
2370                 return 0;
2371         }
2372 }
2373 static void draw_dm_creases(DerivedMesh *dm)
2374 {
2375         glLineWidth(3.0);
2376         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2377         glLineWidth(1.0);
2378 }
2379
2380 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2381 {
2382         EditEdge *eed = EM_get_edge_for_index(index);
2383
2384         if (eed->h==0 && eed->bweight != 0.0f) {
2385                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2386                 return 1;
2387         } else {
2388                 return 0;
2389         }
2390 }
2391 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2392 {
2393         EditVert *eve = EM_get_vert_for_index(index);
2394
2395         if (eve->h==0 && eve->bweight != 0.0f) {
2396                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2397                 bglVertex3fv(co);
2398         }
2399 }
2400 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2401 {
2402         ToolSettings *ts= scene->toolsettings;
2403
2404         if (ts->selectmode & SCE_SELECT_VERTEX) {
2405                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2406                 bglBegin(GL_POINTS);
2407                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2408                 bglEnd();
2409         }
2410         else {
2411                 glLineWidth(3.0);
2412                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2413                 glLineWidth(1.0);
2414         }
2415 }
2416
2417 /* Second section of routines: Combine first sets to form fancy
2418  * drawing routines (for example rendering twice to get overlays).
2419  *
2420  * Also includes routines that are basic drawing but are too
2421  * specialized to be split out (like drawing creases or measurements).
2422  */
2423
2424 /* EditMesh drawing routines*/
2425
2426 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2427 {
2428         ToolSettings *ts= scene->toolsettings;
2429         int sel;
2430
2431         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2432
2433         for (sel=0; sel<2; sel++) {
2434                 unsigned char col[4], fcol[4];
2435                 int pass;
2436
2437                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2438                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2439
2440                 for (pass=0; pass<2; pass++) {
2441                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2442                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2443
2444                         if (pass==0) {
2445                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2446                                         glDisable(GL_DEPTH_TEST);
2447                                                 
2448                                         glEnable(GL_BLEND);
2449                                 } else {
2450                                         continue;
2451                                 }
2452
2453                                 size = (size > 2.1f ? size/2.0f:size);
2454                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2455                                 col[3] = fcol[3] = 100;
2456                         } else {
2457                                 col[3] = fcol[3] = 255;
2458                         }
2459                                 
2460                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2461                                 glPointSize(size);
2462                                 glColor4ubv(col);
2463                                 draw_dm_verts(cageDM, sel, eve_act);
2464                         }
2465                         
2466                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2467                                 glPointSize(fsize);
2468                                 glColor4ubv(fcol);
2469                                 draw_dm_face_centers(cageDM, sel);
2470                         }
2471                         
2472                         if (pass==0) {
2473                                 glDisable(GL_BLEND);
2474                                 glEnable(GL_DEPTH_TEST);
2475                         }
2476                 }
2477         }
2478
2479         if(v3d->zbuf) glDepthMask(1);
2480         glPointSize(1.0);
2481 }
2482
2483 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2484 {
2485         ToolSettings *ts= scene->toolsettings;
2486         int pass;
2487         unsigned char wireCol[4], selCol[4], actCol[4];
2488
2489         /* since this function does transparant... */
2490         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2491         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2492         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2493         
2494         /* when sel only is used, dont render wire, only selected, this is used for
2495          * textured draw mode when the 'edges' option is disabled */
2496         if (sel_only)
2497                 wireCol[3] = 0;
2498
2499         for (pass=0; pass<2; pass++) {
2500                         /* show wires in transparant when no zbuf clipping for select */
2501                 if (pass==0) {
2502                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2503                                 glEnable(GL_BLEND);
2504                                 glDisable(GL_DEPTH_TEST);
2505                                 selCol[3] = 85;
2506                                 if (!sel_only) wireCol[3] = 85;
2507                         } else {
2508                                 continue;
2509                         }
2510                 } else {
2511                         selCol[3] = 255;
2512                         if (!sel_only) wireCol[3] = 255;
2513                 }
2514
2515                 if(ts->selectmode == SCE_SELECT_FACE) {
2516                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2517                 }       
2518                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2519                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2520                                 glShadeModel(GL_SMOOTH);
2521                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2522                                 glShadeModel(GL_FLAT);
2523                         } else {
2524                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2525                         }
2526                 }
2527                 else {
2528                         if (!sel_only) {
2529                                 glColor4ubv(wireCol);
2530                                 draw_dm_edges(cageDM);
2531                         }
2532                 }
2533
2534                 if (pass==0) {
2535                         glDisable(GL_BLEND);
2536                         glEnable(GL_DEPTH_TEST);
2537                 }
2538         }
2539 }       
2540
2541 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2542 {
2543         Mesh *me= ob->data;
2544         EditEdge *eed;
2545         EditFace *efa;
2546         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2547         float fvec[3];
2548         char val[32]; /* Stores the measurement display text here */
2549         const char *conv_float; /* Use a float conversion matching the grid size */
2550         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2551         float area; /* area of the face */
2552         float grid= unit->system ? unit->scale_length : v3d->grid;
2553         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2554         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2555         const int do_moving= G.moving;
2556
2557         /* make the precision of the pronted value proportionate to the gridsize */
2558
2559         if (grid < 0.01f)               conv_float= "%.6g";
2560         else if (grid < 0.1f)   conv_float= "%.5g";
2561         else if (grid < 1.0f)   conv_float= "%.4g";
2562         else if (grid < 10.0f)  conv_float= "%.3g";
2563         else                                    conv_float= "%.2g";
2564
2565         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2566                 glDisable(GL_DEPTH_TEST);
2567
2568         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2569         
2570         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2571                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2572
2573                 for(eed= em->edges.first; eed; eed= eed->next) {
2574                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2575                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2576                                 copy_v3_v3(v1, eed->v1->co);
2577                                 copy_v3_v3(v2, eed->v2->co);
2578
2579                                 mid_v3_v3v3(vmid, v1, v2);
2580
2581                                 if(do_global) {
2582                                         mul_mat3_m4_v3(ob->obmat, v1);
2583                                         mul_mat3_m4_v3(ob->obmat, v2);
2584                                 }
2585                                 if(unit->system)
2586                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2587                                 else
2588                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2589
2590                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2591                         }
2592                 }
2593         }
2594
2595         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2596 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2597                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2598                 
2599                 for(efa= em->faces.first; efa; efa= efa->next) {
2600                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2601                                 copy_v3_v3(v1, efa->v1->co);
2602                                 copy_v3_v3(v2, efa->v2->co);
2603                                 copy_v3_v3(v3, efa->v3->co);
2604                                 if (efa->v4) {
2605                                         copy_v3_v3(v4, efa->v4->co);
2606                                 }
2607                                 if(do_global) {
2608                                         mul_mat3_m4_v3(ob->obmat, v1);
2609                                         mul_mat3_m4_v3(ob->obmat, v2);
2610                                         mul_mat3_m4_v3(ob->obmat, v3);
2611                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2612                                 }
2613                                 
2614                                 if (efa->v4)
2615                                         area=  area_quad_v3(v1, v2, v3, v4);
2616                                 else
2617                                         area = area_tri_v3(v1, v2, v3);
2618
2619                                 if(unit->system)
2620                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2621                                 else
2622                                         sprintf(val, conv_float, area);
2623
2624                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2625                         }
2626                 }
2627         }
2628
2629         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2630                 EditEdge *e1, *e2, *e3, *e4;
2631                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2632                 for(efa= em->faces.first; efa; efa= efa->next) {
2633                         copy_v3_v3(v1, efa->v1->co);
2634                         copy_v3_v3(v2, efa->v2->co);
2635                         copy_v3_v3(v3, efa->v3->co);
2636                         if(efa->v4) {
2637                                 copy_v3_v3(v4, efa->v4->co); 
2638                         }
2639                         else {
2640                                 copy_v3_v3(v4, v3);
2641                         }
2642                         if(do_global) {
2643                                 mul_mat3_m4_v3(ob->obmat, v1);
2644                                 mul_mat3_m4_v3(ob->obmat, v2);
2645                                 mul_mat3_m4_v3(ob->obmat, v3);
2646                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2647                         }
2648                         
2649                         e1= efa->e1;
2650                         e2= efa->e2;
2651                         e3= efa->e3;
2652                         if(efa->e4) e4= efa->e4; else e4= e3;
2653                         
2654                         /* Calculate the angles */
2655                                 
2656                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2657                                 /* Vec 1 */
2658                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2659                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2660                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2661                         }
2662                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2663                                 /* Vec 2 */
2664                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2665                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2666                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2667                         }
2668                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2669                                 /* Vec 3 */
2670                                 if(efa->v4) 
2671                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2672                                 else
2673                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2674                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2675                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2676                         }
2677                                 /* Vec 4 */
2678                         if(efa->v4) {
2679                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2680                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2681                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2682                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2683                                 }
2684                         }
2685                 }
2686         }
2687
2688         /* useful for debugging index vs shape key index */
2689 #if 0
2690         {
2691                 EditVert *eve;
2692                 int j;
2693                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2694                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2695                         sprintf(val, "%d:%d", j, eve->keyindex);
2696                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2697                 }
2698         }
2699 #endif
2700
2701         if(v3d->zbuf) {
2702                 glEnable(GL_DEPTH_TEST);
2703                 bglPolygonOffset(rv3d->dist, 0.0f);
2704         }
2705 }
2706
2707 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2708 {
2709         EditFace *efa = EM_get_face_for_index(index);
2710
2711         if (efa->h==0) {
2712                 GPU_enable_material(efa->mat_nr+1, NULL);
2713                 return 1;
2714         }
2715         else
2716                 return 0;
2717 }
2718
2719 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2720 {
2721         EditFace *efa = EM_get_face_for_index(index);
2722
2723         return (efa->h==0);
2724 }
2725
2726 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2727 {
2728         Mesh *me = ob->data;
2729         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2730         EditEdge *eed_act = NULL;
2731         EditVert *eve_act = NULL;
2732         
2733         if (em->selected.last) {
2734                 EditSelection *ese = em->selected.last;
2735                 /* face is handeled above */
2736                 /*if (ese->type == EDITFACE ) {
2737                         efa_act = (EditFace *)ese->data;
2738                 } else */ if ( ese->type == EDITEDGE ) {
2739                         eed_act = (EditEdge *)ese->data;
2740                 } else if ( ese->type == EDITVERT ) {
2741                         eve_act = (EditVert *)ese->data;
2742                 }
2743         }
2744         
2745         EM_init_index_arrays(em, 1, 1, 1);
2746
2747         if(dt>OB_WIRE) {
2748                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2749                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2750                                 /* if em has no faces the drawMappedFaces callback will fail */
2751                                 if(em->faces.first) {
2752                                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2753
2754                                         finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2755                                                                                                  draw_em_fancy__setGLSLFaceOpts, NULL);
2756                                         GPU_disable_material();
2757
2758                                         glFrontFace(GL_CCW);
2759                                 }
2760                         }
2761                         else {
2762                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2763                         }
2764                 }
2765                 else {
2766                         /* if em has no faces the drawMappedFaces callback will fail */
2767                         if(em->faces.first) {
2768                                 /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2769                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2770
2771                                 glEnable(GL_LIGHTING);
2772                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2773
2774                                 finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
2775
2776                                 glFrontFace(GL_CCW);
2777                                 glDisable(GL_LIGHTING);
2778                         }
2779                 }
2780                         
2781                 // Setup for drawing wire over, disable zbuffer
2782                 // write to show selected edge wires better
2783                 UI_ThemeColor(TH_WIRE);
2784
2785                 bglPolygonOffset(rv3d->dist, 1.0);
2786                 glDepthMask(0);
2787         } 
2788         else {
2789                 if (cageDM!=finalDM) {
2790                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2791                         finalDM->drawEdges(finalDM, 1, 0);
2792                 }
2793         }
2794         
2795         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2796                 unsigned char col1[4], col2[4], col3[4], col4[4];
2797                         
2798                 UI_GetThemeColor4ubv(TH_FACE, col1);
2799                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2800                 UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col3);
2801                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
2802                 
2803                 glEnable(GL_BLEND);
2804                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2805                 
2806                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2807                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2808                         col1[3] = 0;
2809                 
2810                 if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE))
2811                         col3[3] = 0;
2812
2813                 draw_dm_faces_sel(cageDM, col1, col2, col3, col4, efa_act);
2814
2815                 glDisable(GL_BLEND);
2816                 glDepthMask(1);         // restore write in zbuffer
2817         } else if (efa_act) {
2818                 /* even if draw faces is off it would be nice to draw the stipple face
2819                  * Make all other faces zero alpha except for the active
2820                  * */
2821                 unsigned char col1[4], col2[4], col3[4], col4[4];
2822                 col1[3] = col2[3] = col3[3] = 0; /* dont draw */
2823                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col4);
2824                 
2825                 glEnable(GL_BLEND);
2826                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2827                 
2828                 draw_dm_faces_sel(cageDM, col1, col2, col3, col4, efa_act);
2829
2830                 glDisable(GL_BLEND);
2831                 glDepthMask(1);         // restore write in zbuffer
2832                 
2833         }
2834
2835         /* here starts all fancy draw-extra over */
2836         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2837                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2838                 
2839                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2840                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2841                 
2842         } else {
2843                 if(me->drawflag & ME_DRAWSEAMS) {
2844                         UI_ThemeColor(TH_EDGE_SEAM);
2845                         glLineWidth(2);
2846         
2847                         draw_dm_edges_seams(cageDM);
2848         
2849                         glColor3ub(0,0,0);
2850                         glLineWidth(1);
2851                 }
2852                 
2853                 if(me->drawflag & ME_DRAWSHARP) {
2854                         UI_ThemeColor(TH_EDGE_SHARP);
2855                         glLineWidth(2);
2856         
2857                         draw_dm_edges_sharp(cageDM);
2858         
2859                         glColor3ub(0,0,0);
2860                         glLineWidth(1);
2861                 }
2862         
2863                 if(me->drawflag & ME_DRAW_FREESTYLE_EDGE) {
2864                         UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
2865                         glLineWidth(2);
2866         
2867                         draw_dm_edges_freestyle(cageDM);
2868         
2869                         glColor3ub(0,0,0);
2870                         glLineWidth(1);
2871                 }
2872         
2873                 if(me->drawflag & ME_DRAWCREASES) {
2874                         draw_dm_creases(cageDM);
2875                 }
2876                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2877                         draw_dm_bweights(scene, cageDM);
2878                 }
2879         
2880                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2881         }
2882         if(em) {
2883 // XXX          retopo_matrix_update(v3d);
2884
2885                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2886
2887                 if(me->drawflag & ME_DRAWNORMALS) {
2888                         UI_ThemeColor(TH_NORMAL);
2889                         draw_dm_face_normals(scene, cageDM);
2890                 }
2891                 if(me->drawflag & ME_DRAW_VNORMALS) {
2892                         UI_ThemeColor(TH_VNORMAL);
2893                         draw_dm_vert_normals(scene, cageDM);
2894                 }
2895
2896                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2897                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2898         }
2899
2900         if(dt>OB_WIRE) {
2901                 glDepthMask(1);
2902                 bglPolygonOffset(rv3d->dist, 0.0);
2903                 GPU_disable_material();
2904         }
2905
2906         EM_free_index_arrays();
2907 }
2908
2909 /* Mesh drawing routines */
2910
2911 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2912 {
2913         
2914         if(v3d->transp==0) {    // not when we draw the transparent pass
2915                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2916                 glDepthMask(0);
2917                 
2918                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2919                    drawFacesSolid() doesn't draw the transparent faces */
2920                 if(ob->dtx & OB_DRAWTRANSP) {
2921                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2922                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2923                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2924                         GPU_disable_material();
2925                 }
2926                 else {
2927                         dm->drawEdges(dm, 0, 1);
2928                 }
2929                                         
2930                 glLineWidth(1.0);
2931                 glDepthMask(1);
2932         }
2933 }
2934
2935 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2936 {
2937         *drawSmooth_r = 1;
2938         return 1;
2939 }
2940
2941 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2942 {
2943         Object *ob= base->object;
2944         Mesh *me = ob->data;
2945         Material *ma= give_current_material(ob, 1);
2946         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2947         int draw_wire = 0;
2948         int /* totvert,*/ totedge, totface;
2949         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2950         ModifierData *md = NULL;
2951         int draw_flags = (ob==OBACT && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
2952
2953         if(!dm)
2954                 return;
2955
2956         /* check to draw dynamic paint colors */
2957         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
2958         {
2959                 /* check if target has an active dpaint modifier        */
2960                 if(md && (md->mode & eModifierMode_Realtime))                                   
2961                 {
2962                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2963                         /* if canvas is ready to preview vertex colors */
2964                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
2965                                 DM_get_face_data_layer(dm, CD_WEIGHT_MCOL)) {
2966                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
2967                         }
2968                 }
2969         }
2970         
2971         if (ob->dtx&OB_DRAWWIRE) {
2972                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2973         }
2974         
2975         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2976         totedge = dm->getNumEdges(dm);
2977         totface = dm->getNumFaces(dm);
2978         
2979         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2980         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2981
2982                 // Unwanted combination.
2983         if (draw_flags & DRAW_FACE_SELECT) draw_wire = 0;
2984
2985         if(dt==OB_BOUNDBOX) {
2986                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2987                         draw_bounding_volume(scene, ob, ob->boundtype);
2988         }
2989         else if(hasHaloMat || (totface==0 && totedge==0)) {
2990                 glPointSize(1.5);
2991                 dm->drawVerts(dm);
2992                 glPointSize(1.0);
2993         }
2994         else if(dt==OB_WIRE || totface==0) {
2995                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2996         }
2997         else if(        (draw_flags & DRAW_FACE_SELECT || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2998                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2999         {
3000                 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) {
3001                         draw_mesh_object_outline(v3d, ob, dm);
3002                 }
3003
3004                 if(draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
3005                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3006
3007                         dm->drawFacesGLSL(dm, GPU_enable_material);
3008 //                      if(get_ob_property(ob, "Text"))
3009 // XXX                          draw_mesh_text(ob, 1);
3010                         GPU_disable_material();
3011
3012                         glFrontFace(GL_CCW);
3013                 }
3014                 else {
3015                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3016                 }
3017
3018                 if(!(draw_flags & DRAW_FACE_SELECT)) {
3019                         if(base->flag & SELECT)
3020                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
3021                         else
3022                                 UI_ThemeColor(TH_WIRE);
3023
3024                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3025                                 dm->drawLooseEdges(dm);
3026                 }
3027         }
3028         else if(dt==OB_SOLID) {
3029                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
3030                         /* weight paint in solid mode, special case. focus on making the weights clear
3031                          * rather than the shading, this is also forced in wire view */
3032                         GPU_enable_material(0, NULL);
3033                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
3034                 
3035                         bglPolygonOffset(rv3d->dist, 1.0);
3036                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3037
3038                         glEnable(GL_BLEND);
3039                         glColor4ub(255, 255, 255, 96);
3040                         glEnable(GL_LINE_STIPPLE);
3041                         glLineStipple(1, 0xAAAA);
3042
3043                         dm->drawEdges(dm, 1, 1);
3044
3045                         bglPolygonOffset(rv3d->dist, 0.0);
3046                         glDepthMask(1);
3047                         glDisable(GL_LINE_STIPPLE);
3048
3049                         GPU_disable_material();
3050                         
3051                         /* since we already draw wire as wp guide, dont draw over the top */
3052                         draw_wire= 0;
3053                 }
3054                 else if (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW) {
3055                         /* for object selection draws no shade */
3056                         if (flag & (DRAW_PICKING|DRAW_CONSTCOLOR)) {
3057                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
3058                         }
3059                         else {
3060                                 /* draw outline */
3061                                 if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
3062                                         draw_mesh_object_outline(v3d, ob, dm);
3063
3064                                 /* materials arent compatible with vertex colors */
3065                                 GPU_end_object_materials();
3066
3067                                 GPU_enable_material(0, NULL);
3068                                 
3069                                 /* set default spec */
3070                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
3071                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
3072                                 glColor3ub(120, 120, 120);
3073                                 glDisable(GL_COLOR_MATERIAL);
3074                                 /* diffuse */
3075                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
3076                                 glEnable(GL_LIGHTING);
3077                                 glEnable(GL_COLOR_MATERIAL);
3078
3079                                 dm->drawMappedFaces(dm, NULL, NULL, 1, GPU_enable_material, NULL);
3080                                 glDisable(GL_COLOR_MATERIAL);
3081                                 glDisable(GL_LIGHTING);
3082
3083                                 GPU_disable_material();
3084                         }
3085                 }
3086                 else {
3087                         Paint *p;
3088
3089                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
3090                                 draw_mesh_object_outline(v3d, ob, dm);
3091
3092                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
3093
3094                         glEnable(GL_LIGHTING);
3095                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3096
3097                         if(ob->sculpt && (p=paint_get_active(scene))) {
3098                                 float planes[4][4];
3099                                 float (*fpl)[4] = NULL;
3100                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
3101
3102                                 if(ob->sculpt->partial_redraw) {
3103                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
3104                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
3105                                                 fpl = planes;
3106                                                 ob->sculpt->partial_redraw = 0;
3107                           &