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