Show Cone option for spot lamps, to visualize which objects are being affected.
[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 draw_spot_cone(Lamp *la, float x, float z)
769 {
770         float vec[3];
771
772         z= fabs(z);
773
774         glBegin(GL_TRIANGLE_FAN);
775         glVertex3f(0.0f, 0.0f, -x);
776
777         if(la->mode & LA_SQUARE) {
778                 vec[0]= z;
779                 vec[1]= z;
780                 vec[2]= 0.0;
781
782                 glVertex3fv(vec);
783                 vec[1]= -z;
784                 glVertex3fv(vec);
785                 vec[0]= -z;
786                 glVertex3fv(vec);
787                 vec[1]= z;
788                 glVertex3fv(vec);
789         }
790         else {
791                 float angle;
792                 int a;
793
794                 for(a=0; a<33; a++) {
795                         angle= a*M_PI*2/(33-1);
796                         glVertex3f(z*cos(angle), z*sin(angle), 0);
797                 }
798         }
799
800         glEnd();
801 }
802
803 static void draw_transp_spot_volume(Lamp *la, float x, float z)
804 {
805         glEnable(GL_CULL_FACE);
806         glEnable(GL_BLEND);
807         glDepthMask(0);
808
809         /* draw backside darkening */
810         glCullFace(GL_FRONT);
811
812         glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
813         glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
814
815         draw_spot_cone(la, x, z);
816
817         /* draw front side lightening */
818         glCullFace(GL_BACK);
819
820         glBlendFunc(GL_ONE,  GL_ONE); 
821         glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
822
823         draw_spot_cone(la, x, z);
824
825         /* restore state */
826         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
827         glDisable(GL_BLEND);
828         glDepthMask(1);
829         glDisable(GL_CULL_FACE);
830         glCullFace(GL_BACK);
831 }
832
833 static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
834 {
835         Object *ob= base->object;
836         Lamp *la= ob->data;
837         float vec[3], lvec[3], vvec[3], circrad, x,y,z;
838         float pixsize, lampsize;
839         float imat[4][4], curcol[4];
840         char col[4];
841         int drawcone= (dt>OB_WIRE && !(G.f & G_PICKSEL) && la->type == LA_SPOT && (la->mode & LA_SHOW_CONE));
842
843         if(G.f & G_RENDER_SHADOW)
844                 return;
845         
846         if(drawcone && !v3d->transp) {
847                 /* in this case we need to draw delayed */
848                 add_view3d_after(v3d, base, V3D_TRANSP, flag);
849                 return;
850         }
851         
852         /* we first draw only the screen aligned & fixed scale stuff */
853         glPushMatrix();
854         wmLoadMatrix(rv3d->viewmat);
855
856         /* lets calculate the scale: */
857         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];
858         pixsize*= rv3d->pixsize;
859         lampsize= pixsize*((float)U.obcenter_dia*0.5f);
860
861         /* and view aligned matrix: */
862         copy_m4_m4(imat, rv3d->viewinv);
863         normalize_v3(imat[0]);
864         normalize_v3(imat[1]);
865         
866         /* for AA effects */
867         glGetFloatv(GL_CURRENT_COLOR, curcol);
868         curcol[3]= 0.6;
869         glColor4fv(curcol);
870         
871         if(lampsize > 0.0f) {
872
873                 if(ob->id.us>1) {
874                         if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
875                         else glColor4ub(0x77, 0xCC, 0xCC, 155);
876                 }
877                 
878                 /* Inner Circle */
879                 VECCOPY(vec, ob->obmat[3]);
880                 glEnable(GL_BLEND);
881                 drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
882                 glDisable(GL_BLEND);
883                 drawcircball(GL_POLYGON, vec, lampsize, imat);
884                 
885                 /* restore */
886                 if(ob->id.us>1)
887                         glColor4fv(curcol);
888                         
889                 /* Outer circle */
890                 circrad = 3.0f*lampsize;
891                 drawcircball(GL_LINE_LOOP, vec, circrad, imat);
892         }
893         else
894                 circrad = 0.0f;
895         
896         setlinestyle(3);
897
898         /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
899         if (la->type!=LA_HEMI) {
900                 if ((la->mode & LA_SHAD_RAY) ||
901                         ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
902                 {
903                         drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
904                 }
905         }
906         
907         /* draw the pretty sun rays */
908         if(la->type==LA_SUN) {
909                 float v1[3], v2[3], mat[3][3];
910                 short axis;
911                 
912                 /* setup a 45 degree rotation matrix */
913                 vec_rot_to_mat3( mat,imat[2], M_PI/4.0f);
914                 
915                 /* vectors */
916                 VECCOPY(v1, imat[0]);
917                 mul_v3_fl(v1, circrad*1.2f);
918                 VECCOPY(v2, imat[0]);
919                 mul_v3_fl(v2, circrad*2.5f);
920                 
921                 /* center */
922                 glTranslatef(vec[0], vec[1], vec[2]);
923                 
924                 setlinestyle(3);
925                 
926                 glBegin(GL_LINES);
927                 for (axis=0; axis<8; axis++) {
928                         glVertex3fv(v1);
929                         glVertex3fv(v2);
930                         mul_m3_v3(mat, v1);
931                         mul_m3_v3(mat, v2);
932                 }
933                 glEnd();
934                 
935                 glTranslatef(-vec[0], -vec[1], -vec[2]);
936
937         }               
938         
939         if (la->type==LA_LOCAL) {
940                 if(la->mode & LA_SPHERE) {
941                         drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
942                 }
943                 /* yafray: for photonlight also draw lightcone as for spot */
944         }
945         
946         glPopMatrix();  /* back in object space */
947         vec[0]= vec[1]= vec[2]= 0.0f;
948         
949         if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {  
950                 lvec[0]=lvec[1]= 0.0; 
951                 lvec[2] = 1.0;
952                 x = rv3d->persmat[0][2];
953                 y = rv3d->persmat[1][2];
954                 z = rv3d->persmat[2][2];
955                 vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
956                 vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
957                 vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
958
959                 y = cos( M_PI*la->spotsize/360.0 );
960                 spotvolume(lvec, vvec, y);
961                 x = -la->dist;
962                 mul_v3_fl(lvec, x);
963                 mul_v3_fl(vvec, x);
964
965                 /* draw the angled sides of the cone */
966                 glBegin(GL_LINE_STRIP);
967                         glVertex3fv(vvec);
968                         glVertex3fv(vec);
969                         glVertex3fv(lvec);
970                 glEnd();
971                 
972                 z = x*sqrt(1.0 - y*y);
973                 x *= y;
974
975                 /* draw the circle/square at the end of the cone */
976                 glTranslatef(0.0, 0.0 ,  x);
977                 if(la->mode & LA_SQUARE) {
978                         vvec[0]= fabs(z);
979                         vvec[1]= fabs(z);
980                         vvec[2]= 0.0;
981                         glBegin(GL_LINE_LOOP);
982                                 glVertex3fv(vvec);
983                                 vvec[1]= -fabs(z);
984                                 glVertex3fv(vvec);
985                                 vvec[0]= -fabs(z);
986                                 glVertex3fv(vvec);
987                                 vvec[1]= fabs(z);
988                                 glVertex3fv(vvec);
989                         glEnd();
990                 }
991                 else circ(0.0, 0.0, fabs(z));
992                 
993                 /* draw the circle/square representing spotbl */
994                 if(la->type==LA_SPOT) {
995                         float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
996                         /* hide line if it is zero size or overlaps with outer border,
997                            previously it adjusted to always to show it but that seems
998                            confusing because it doesn't show the actual blend size */
999                         if (spotblcirc != 0 && spotblcirc != fabs(z))
1000                                 circ(0.0, 0.0, spotblcirc);
1001                 }
1002
1003                 if(drawcone)
1004                         draw_transp_spot_volume(la, x, z);
1005         }
1006         else if ELEM(la->type, LA_HEMI, LA_SUN) {
1007                 
1008                 /* draw the line from the circle along the dist */
1009                 glBegin(GL_LINE_STRIP);
1010                         vec[2] = -circrad;
1011                         glVertex3fv(vec); 
1012                         vec[2]= -la->dist; 
1013                         glVertex3fv(vec);
1014                 glEnd();
1015                 
1016                 if(la->type==LA_HEMI) {
1017                         /* draw the hemisphere curves */
1018                         short axis, steps, dir;
1019                         float outdist, zdist, mul;
1020                         vec[0]=vec[1]=vec[2]= 0.0;
1021                         outdist = 0.14; mul = 1.4; dir = 1;
1022                         
1023                         setlinestyle(4);
1024                         /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
1025                         for (axis=0; axis<4; axis++) {
1026                                 float v[3]= {0.0, 0.0, 0.0};
1027                                 zdist = 0.02;
1028                                 
1029                                 glBegin(GL_LINE_STRIP);
1030                                 
1031                                 for (steps=0; steps<6; steps++) {
1032                                         if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
1033                                                 /* make the arcs start at the edge of the energy circle */
1034                                                 if (steps == 0) v[0] = dir*circrad;
1035                                                 else v[0] = v[0] + dir*(steps*outdist);
1036                                         } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
1037                                                 /* make the arcs start at the edge of the energy circle */
1038                                                 if (steps == 0) v[1] = dir*circrad;
1039                                                 else v[1] = v[1] + dir*(steps*outdist); 
1040                                         }
1041                 
1042                                         v[2] = v[2] - steps*zdist;
1043                                         
1044                                         glVertex3fv(v);
1045                                         
1046                                         zdist = zdist * mul;
1047                                 }
1048                                 
1049                                 glEnd();
1050                                 /* flip the direction */
1051                                 dir = -dir;
1052                         }
1053                 }
1054         } else if(la->type==LA_AREA) {
1055                 setlinestyle(3);
1056                 if(la->area_shape==LA_AREA_SQUARE) 
1057                         fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
1058                 else if(la->area_shape==LA_AREA_RECT) 
1059                         fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
1060
1061                 glBegin(GL_LINE_STRIP); 
1062                 glVertex3f(0.0,0.0,-circrad);
1063                 glVertex3f(0.0,0.0,-la->dist);
1064                 glEnd();
1065         }
1066         
1067         /* and back to viewspace */
1068         wmLoadMatrix(rv3d->viewmat);
1069         VECCOPY(vec, ob->obmat[3]);
1070
1071         setlinestyle(0);
1072         
1073         if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
1074                 drawshadbuflimits(la, ob->obmat);
1075         }
1076         
1077         UI_GetThemeColor4ubv(TH_LAMP, col);
1078         glColor4ub(col[0], col[1], col[2], col[3]);
1079          
1080         glEnable(GL_BLEND);
1081         
1082         if (vec[2]>0) vec[2] -= circrad;
1083         else vec[2] += circrad;
1084         
1085         glBegin(GL_LINE_STRIP);
1086                 glVertex3fv(vec); 
1087                 vec[2]= 0; 
1088                 glVertex3fv(vec);
1089         glEnd();
1090         
1091         glPointSize(2.0);
1092         glBegin(GL_POINTS);
1093                 glVertex3fv(vec);
1094         glEnd();
1095         glPointSize(1.0);
1096         
1097         glDisable(GL_BLEND);
1098         
1099         /* restore for drawing extra stuff */
1100         glColor3fv(curcol);
1101
1102 }
1103
1104 static void draw_limit_line(float sta, float end, unsigned int col)
1105 {
1106         glBegin(GL_LINES);
1107         glVertex3f(0.0, 0.0, -sta);
1108         glVertex3f(0.0, 0.0, -end);
1109         glEnd();
1110
1111         glPointSize(3.0);
1112         glBegin(GL_POINTS);
1113         cpack(col);
1114         glVertex3f(0.0, 0.0, -sta);
1115         glVertex3f(0.0, 0.0, -end);
1116         glEnd();
1117         glPointSize(1.0);
1118 }               
1119
1120
1121 /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
1122 /* qdn: now also enabled for Blender to set focus point for defocus composit node */
1123 static void draw_focus_cross(float dist, float size)
1124 {
1125         glBegin(GL_LINES);
1126         glVertex3f(-size, 0.f, -dist);
1127         glVertex3f(size, 0.f, -dist);
1128         glVertex3f(0.f, -size, -dist);
1129         glVertex3f(0.f, size, -dist);
1130         glEnd();
1131 }
1132
1133 /* flag similar to draw_object() */
1134 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int flag)
1135 {
1136         /* a standing up pyramid with (0,0,0) as top */
1137         Camera *cam;
1138         World *wrld;
1139         float vec[8][4], tmat[4][4], fac, facx, facy, depth;
1140         int i;
1141
1142         if(G.f & G_RENDER_SHADOW)
1143                 return;
1144
1145         cam= ob->data;
1146         
1147         glDisable(GL_LIGHTING);
1148         glDisable(GL_CULL_FACE);
1149         
1150         if(rv3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
1151                 facx= 0.5*cam->ortho_scale*1.28;
1152                 facy= 0.5*cam->ortho_scale*1.024;
1153                 depth= -cam->clipsta-0.1;
1154         }
1155         else {
1156                 fac= cam->drawsize;
1157                 if(rv3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
1158                 
1159                 depth= - fac*cam->lens/16.0;
1160                 facx= fac*1.28;
1161                 facy= fac*1.024;
1162         }
1163         
1164         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001;       /* GLBUG: for picking at iris Entry (well thats old!) */
1165         vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
1166         vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
1167         vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
1168         vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
1169
1170         glBegin(GL_LINE_LOOP);
1171                 glVertex3fv(vec[1]); 
1172                 glVertex3fv(vec[2]); 
1173                 glVertex3fv(vec[3]); 
1174                 glVertex3fv(vec[4]);
1175         glEnd();
1176         
1177
1178         if(rv3d->persp>=2 && ob==v3d->camera) return;
1179         
1180         glBegin(GL_LINE_STRIP);
1181                 glVertex3fv(vec[2]); 
1182                 glVertex3fv(vec[0]);
1183                 glVertex3fv(vec[1]);
1184                 glVertex3fv(vec[4]);
1185                 glVertex3fv(vec[0]);
1186                 glVertex3fv(vec[3]); 
1187         glEnd();
1188
1189
1190         /* arrow on top */
1191         vec[0][2]= depth;
1192
1193         
1194         /* draw an outline arrow for inactive cameras and filled
1195          * for active cameras. We actually draw both outline+filled
1196          * for active cameras so the wire can be seen side-on */        
1197         for (i=0;i<2;i++) {
1198                 if (i==0) glBegin(GL_LINE_LOOP);
1199                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1200                 else break;
1201                 
1202                 vec[0][0]= -0.7*cam->drawsize;
1203                 vec[0][1]= 1.1*cam->drawsize;
1204                 glVertex3fv(vec[0]);
1205                 
1206                 vec[0][0]= 0.0; 
1207                 vec[0][1]= 1.8*cam->drawsize;
1208                 glVertex3fv(vec[0]);
1209                 
1210                 vec[0][0]= 0.7*cam->drawsize; 
1211                 vec[0][1]= 1.1*cam->drawsize;
1212                 glVertex3fv(vec[0]);
1213         
1214                 glEnd();
1215         }
1216
1217         if(flag==0) {
1218                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1219                         wmLoadMatrix(rv3d->viewmat);
1220                         copy_m4_m4(vec, ob->obmat);
1221                         normalize_m4(vec);
1222                         wmMultMatrix(vec);
1223
1224                         swap_m4m4(rv3d->persmat, tmat);
1225                         wmGetSingleMatrix(rv3d->persmat);
1226
1227                         if(cam->flag & CAM_SHOWLIMITS) {
1228                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1229                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1230                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
1231                         }
1232
1233                         wrld= scene->world;
1234                         if(cam->flag & CAM_SHOWMIST) 
1235                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1236                                 
1237                         swap_m4m4(rv3d->persmat, tmat);
1238                 }
1239         }
1240 }
1241
1242 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1243 {
1244         BPoint *bp = lt->def;
1245         float *co = dl?dl->verts:NULL;
1246         int u, v, w;
1247
1248         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1249         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1250         bglBegin(GL_POINTS);
1251
1252         for(w=0; w<lt->pntsw; w++) {
1253                 int wxt = (w==0 || w==lt->pntsw-1);
1254                 for(v=0; v<lt->pntsv; v++) {
1255                         int vxt = (v==0 || v==lt->pntsv-1);
1256                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1257                                 int uxt = (u==0 || u==lt->pntsu-1);
1258                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1259                                         if(bp->hide==0) {
1260                                                 if((bp->f1 & SELECT)==sel) {
1261                                                         bglVertex3fv(dl?co:bp->vec);
1262                                                 }
1263                                         }
1264                                 }
1265                         }
1266                 }
1267         }
1268         
1269         glPointSize(1.0);
1270         bglEnd();       
1271 }
1272
1273 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1274 {
1275         Object *obedit= vc->obedit;
1276         Lattice *lt= obedit->data;
1277         BPoint *bp = lt->editlatt->def;
1278         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1279         float *co = dl?dl->verts:NULL;
1280         int i, N = lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1281         short s[2] = {IS_CLIPPED, 0};
1282
1283         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1284
1285         for (i=0; i<N; i++, bp++, co+=3) {
1286                 if (bp->hide==0) {
1287                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1288                         if (s[0] != IS_CLIPPED)
1289                                 func(userData, bp, s[0], s[1]);
1290                 }
1291         }
1292 }
1293
1294 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1295 {
1296         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1297
1298         if(use_wcol) {
1299                 float col[3];
1300                 MDeformWeight *mdw= ED_vgroup_weight_get (lt->dvert+index, use_wcol-1);
1301                 
1302                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1303                 glColor3fv(col);
1304
1305         }
1306         
1307         if (dl) {
1308                 glVertex3fv(&dl->verts[index*3]);
1309         } else {
1310                 glVertex3fv(lt->def[index].vec);
1311         }
1312 }
1313
1314 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1315 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1316 {
1317         Lattice *lt= ob->data;
1318         DispList *dl;
1319         int u, v, w;
1320         int use_wcol= 0;
1321
1322         /* now we default make displist, this will modifiers work for non animated case */
1323         if(ob->disp.first==NULL)
1324                 lattice_calc_modifiers(scene, ob);
1325         dl= find_displist(&ob->disp, DL_VERTS);
1326         
1327         if(lt->editlatt) {
1328                 cpack(0x004000);
1329                 
1330                 if(ob->defbase.first && lt->dvert) {
1331                         use_wcol= ob->actdef;
1332                         glShadeModel(GL_SMOOTH);
1333                 }
1334         }
1335         
1336         if(lt->editlatt) lt= lt->editlatt;
1337         
1338         glBegin(GL_LINES);
1339         for(w=0; w<lt->pntsw; w++) {
1340                 int wxt = (w==0 || w==lt->pntsw-1);
1341                 for(v=0; v<lt->pntsv; v++) {
1342                         int vxt = (v==0 || v==lt->pntsv-1);
1343                         for(u=0; u<lt->pntsu; u++) {
1344                                 int uxt = (u==0 || u==lt->pntsu-1);
1345
1346                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1347                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1348                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1349                                 }
1350                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1351                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1352                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1353                                 }
1354                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1355                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1356                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1357                                 }
1358                         }
1359                 }
1360         }               
1361         glEnd();
1362         
1363         /* restoration for weight colors */
1364         if(use_wcol)
1365                 glShadeModel(GL_FLAT);
1366
1367         if( ((Lattice *)ob->data)->editlatt ) {
1368                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1369                 
1370                 lattice_draw_verts(lt, dl, 0);
1371                 lattice_draw_verts(lt, dl, 1);
1372                 
1373                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1374         }
1375 }
1376
1377 /* ***************** ******************** */
1378
1379 /* Note! - foreach funcs should be called while drawing or directly after
1380  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1381  * but would not give correct results with dupli's for eg. which dont
1382  * use the object matrix in the useual way */
1383 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1384 {
1385         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1386         EditVert *eve = EM_get_vert_for_index(index);
1387
1388         if (eve->h==0) {
1389                 short s[2]= {IS_CLIPPED, 0};
1390
1391                 if (data->clipVerts) {
1392                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1393                 } else {
1394                         view3d_project_short_noclip(data->vc.ar, co, s);
1395                 }
1396
1397                 if (s[0]!=IS_CLIPPED)
1398                         data->func(data->userData, eve, s[0], s[1], index);
1399         }
1400 }
1401
1402 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1403 {
1404         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1405         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1406         
1407         data.vc= *vc;
1408         data.func = func;
1409         data.userData = userData;
1410         data.clipVerts = clipVerts;
1411
1412         if(clipVerts)
1413                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1414
1415         EM_init_index_arrays(vc->em, 1, 0, 0);
1416         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1417         EM_free_index_arrays();
1418
1419         dm->release(dm);
1420 }
1421
1422 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1423 {
1424         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;
1425         EditEdge *eed = EM_get_edge_for_index(index);
1426         short s[2][2];
1427
1428         if (eed->h==0) {
1429                 if (data->clipVerts==1) {
1430                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1431                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1432                 } else {
1433                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1434                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1435
1436                         if (data->clipVerts==2) {
1437                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1438                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1439                                                 return;
1440                         }
1441                 }
1442
1443                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1444         }
1445 }
1446
1447 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)
1448 {
1449         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1450         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1451
1452         data.vc= *vc;
1453         data.func = func;
1454         data.userData = userData;
1455         data.clipVerts = clipVerts;
1456
1457         if(clipVerts)
1458                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1459
1460         EM_init_index_arrays(vc->em, 0, 1, 0);
1461         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1462         EM_free_index_arrays();
1463
1464         dm->release(dm);
1465 }
1466
1467 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1468 {
1469         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1470         EditFace *efa = EM_get_face_for_index(index);
1471         short s[2];
1472
1473         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1474                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1475
1476                 data->func(data->userData, efa, s[0], s[1], index);
1477         }
1478 }
1479
1480 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1481 {
1482         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1483         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1484
1485         data.vc= *vc;
1486         data.func = func;
1487         data.userData = userData;
1488
1489         //if(clipVerts)
1490         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1491
1492         EM_init_index_arrays(vc->em, 0, 0, 1);
1493         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1494         EM_free_index_arrays();
1495
1496         dm->release(dm);
1497 }
1498
1499 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1500 {
1501         Curve *cu= vc->obedit->data;
1502         short s[2] = {IS_CLIPPED, 0};
1503         Nurb *nu;
1504         int i;
1505
1506         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1507
1508         for (nu= cu->editnurb->first; nu; nu=nu->next) {
1509                 if(nu->type == CU_BEZIER) {
1510                         for (i=0; i<nu->pntsu; i++) {
1511                                 BezTriple *bezt = &nu->bezt[i];
1512
1513                                 if(bezt->hide==0) {
1514                                         
1515                                         if(cu->drawflag & CU_HIDE_HANDLES) {
1516                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1517                                                 if (s[0] != IS_CLIPPED)
1518                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1519                                         } else {
1520                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1521                                                 if (s[0] != IS_CLIPPED)
1522                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1523                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1524                                                 if (s[0] != IS_CLIPPED)
1525                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1526                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1527                                                 if (s[0] != IS_CLIPPED)
1528                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1529                                         }
1530                                 }
1531                         }
1532                 }
1533                 else {
1534                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1535                                 BPoint *bp = &nu->bp[i];
1536
1537                                 if(bp->hide==0) {
1538                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1539                                         if (s[0] != IS_CLIPPED)
1540                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1541                                 }
1542                         }
1543                 }
1544         }
1545 }
1546
1547 /* ************** DRAW MESH ****************** */
1548
1549 /* First section is all the "simple" draw routines, 
1550  * ones that just pass some sort of primitive to GL,
1551  * with perhaps various options to control lighting,
1552  * color, etc.
1553  *
1554  * These routines should not have user interface related
1555  * logic!!!
1556  */
1557
1558 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1559 {
1560         ToolSettings *ts= ((Scene *)userData)->toolsettings;
1561         EditFace *efa = EM_get_face_for_index(index);
1562
1563         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1564                 glVertex3fv(cent);
1565                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1566                                         cent[1] + no[1]*ts->normalsize,
1567                                         cent[2] + no[2]*ts->normalsize);
1568         }
1569 }
1570 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1571 {
1572         glBegin(GL_LINES);
1573         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1574         glEnd();
1575 }
1576
1577 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1578 {
1579         EditFace *efa = EM_get_face_for_index(index);
1580         int sel = *((int*) userData);
1581
1582         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1583                 bglVertex3fv(cent);
1584         }
1585 }
1586 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1587 {
1588         bglBegin(GL_POINTS);
1589         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1590         bglEnd();
1591 }
1592
1593 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1594 {
1595         Scene *scene= (Scene *)userData;
1596         ToolSettings *ts= scene->toolsettings;
1597         EditVert *eve = EM_get_vert_for_index(index);
1598
1599         if (eve->h==0) {
1600                 glVertex3fv(co);
1601
1602                 if (no_f) {
1603                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1604                                                 co[1] + no_f[1]*ts->normalsize,
1605                                                 co[2] + no_f[2]*ts->normalsize);
1606                 } else {
1607                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1608                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1609                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1610                 }
1611         }
1612 }
1613 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1614 {
1615         glBegin(GL_LINES);
1616         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1617         glEnd();
1618 }
1619
1620         /* Draw verts with color set based on selection */
1621 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1622 {
1623         struct { int sel; EditVert *eve_act; } * data = userData;
1624         EditVert *eve = EM_get_vert_for_index(index);
1625
1626         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1627                 /* draw active larger - need to stop/start point drawing for this :/ */
1628                 if (eve==data->eve_act) {
1629                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1630                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1631                         
1632                         bglEnd();
1633                         
1634                         glPointSize(size);
1635                         bglBegin(GL_POINTS);
1636                         bglVertex3fv(co);
1637                         bglEnd();
1638                         
1639                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1640                         glPointSize(size);
1641                         bglBegin(GL_POINTS);
1642                 } else {
1643                         bglVertex3fv(co);
1644                 }
1645         }
1646 }
1647
1648 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1649 {
1650         struct { int sel; EditVert *eve_act; } data;
1651         data.sel = sel;
1652         data.eve_act = eve_act;
1653
1654         bglBegin(GL_POINTS);
1655         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1656         bglEnd();
1657 }
1658
1659         /* Draw edges with color set based on selection */
1660 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1661 {
1662         EditEdge *eed = EM_get_edge_for_index(index);
1663         //unsigned char **cols = userData, *col;
1664         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1665         unsigned char *col;
1666
1667         if (eed->h==0) {
1668                 if (eed==data->eed_act) {
1669                         glColor4ubv(data->actCol);
1670                 } else {
1671                         if (eed->f&SELECT) {
1672                                 col = data->selCol;
1673                         } else {
1674                                 col = data->baseCol;
1675                         }
1676                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1677                         if (col[3]==0) return 0;
1678                         
1679                         glColor4ubv(col);
1680                 }
1681                 return 1;
1682         } else {
1683                 return 0;
1684         }
1685 }
1686 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1687 {
1688         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1689         
1690         data.baseCol = baseCol;
1691         data.selCol = selCol;
1692         data.actCol = actCol;
1693         data.eed_act = eed_act;
1694         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1695 }
1696
1697         /* Draw edges */
1698 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1699 {
1700         return EM_get_edge_for_index(index)->h==0;
1701 }
1702 static void draw_dm_edges(DerivedMesh *dm) 
1703 {
1704         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1705 }
1706
1707         /* Draw edges with color interpolated based on selection */
1708 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1709 {
1710         return EM_get_edge_for_index(index)->h==0;
1711 }
1712 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1713 {
1714         EditEdge *eed = EM_get_edge_for_index(index);
1715         unsigned char **cols = userData;
1716         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1717         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1718
1719         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1720                                 col0[1] + (col1[1]-col0[1])*t,
1721                                 col0[2] + (col1[2]-col0[2])*t,
1722                                 col0[3] + (col1[3]-col0[3])*t);
1723 }
1724
1725 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1726 {
1727         unsigned char *cols[2] = {baseCol, selCol};
1728
1729         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1730 }
1731
1732         /* Draw only seam edges */
1733 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1734 {
1735         EditEdge *eed = EM_get_edge_for_index(index);
1736
1737         return (eed->h==0 && eed->seam);
1738 }
1739 static void draw_dm_edges_seams(DerivedMesh *dm)
1740 {
1741         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1742 }
1743
1744         /* Draw only sharp edges */
1745 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1746 {
1747         EditEdge *eed = EM_get_edge_for_index(index);
1748
1749         return (eed->h==0 && eed->sharp);
1750 }
1751 static void draw_dm_edges_sharp(DerivedMesh *dm)
1752 {
1753         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1754 }
1755
1756
1757         /* Draw faces with color set based on selection
1758          * return 2 for the active face so it renders with stipple enabled */
1759 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1760 {
1761         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1762         EditFace *efa = EM_get_face_for_index(index);
1763         unsigned char *col;
1764         
1765         if (efa->h==0) {
1766                 if (efa == data->efa_act) {
1767                         glColor4ubv(data->cols[2]);
1768                         return 2; /* stipple */
1769                 } else {
1770                         col = data->cols[(efa->f&SELECT)?1:0];
1771                         if (col[3]==0) return 0;
1772                         glColor4ubv(col);
1773                         return 1;
1774                 }
1775         }
1776         return 0;
1777 }
1778
1779 /* also draws the active face */
1780 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1781 {
1782         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1783         data.cols[0] = baseCol;
1784         data.cols[1] = selCol;
1785         data.cols[2] = actCol;
1786         data.efa_act = efa_act;
1787
1788         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1789 }
1790
1791 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1792 {
1793         EditEdge *eed = EM_get_edge_for_index(index);
1794
1795         if (eed->h==0 && eed->crease!=0.0) {
1796                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1797                 return 1;
1798         } else {
1799                 return 0;
1800         }
1801 }
1802 static void draw_dm_creases(DerivedMesh *dm)
1803 {
1804         glLineWidth(3.0);
1805         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1806         glLineWidth(1.0);
1807 }
1808
1809 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1810 {
1811         EditEdge *eed = EM_get_edge_for_index(index);
1812
1813         if (eed->h==0 && eed->bweight!=0.0) {
1814                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1815                 return 1;
1816         } else {
1817                 return 0;
1818         }
1819 }
1820 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1821 {
1822         EditVert *eve = EM_get_vert_for_index(index);
1823
1824         if (eve->h==0 && eve->bweight!=0.0) {
1825                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1826                 bglVertex3fv(co);
1827         }
1828 }
1829 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1830 {
1831         ToolSettings *ts= scene->toolsettings;
1832
1833         if (ts->selectmode & SCE_SELECT_VERTEX) {
1834                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1835                 bglBegin(GL_POINTS);
1836                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1837                 bglEnd();
1838         }
1839         else {
1840                 glLineWidth(3.0);
1841                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1842                 glLineWidth(1.0);
1843         }
1844 }
1845
1846 /* Second section of routines: Combine first sets to form fancy
1847  * drawing routines (for example rendering twice to get overlays).
1848  *
1849  * Also includes routines that are basic drawing but are too
1850  * specialized to be split out (like drawing creases or measurements).
1851  */
1852
1853 /* EditMesh drawing routines*/
1854
1855 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1856 {
1857         ToolSettings *ts= scene->toolsettings;
1858         int sel;
1859
1860         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
1861
1862         for (sel=0; sel<2; sel++) {
1863                 char col[4], fcol[4];
1864                 int pass;
1865
1866                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1867                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1868
1869                 for (pass=0; pass<2; pass++) {
1870                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1871                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1872
1873                         if (pass==0) {
1874                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1875                                         glDisable(GL_DEPTH_TEST);
1876                                                 
1877                                         glEnable(GL_BLEND);
1878                                 } else {
1879                                         continue;
1880                                 }
1881
1882                                 size = (size>2.1?size/2.0:size);
1883                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1884                                 col[3] = fcol[3] = 100;
1885                         } else {
1886                                 col[3] = fcol[3] = 255;
1887                         }
1888                                 
1889                         if(ts->selectmode & SCE_SELECT_VERTEX) {
1890                                 glPointSize(size);
1891                                 glColor4ubv((GLubyte *)col);
1892                                 draw_dm_verts(cageDM, sel, eve_act);
1893                         }
1894                         
1895                         if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
1896                                 glPointSize(fsize);
1897                                 glColor4ubv((GLubyte *)fcol);
1898                                 draw_dm_face_centers(cageDM, sel);
1899                         }
1900                         
1901                         if (pass==0) {
1902                                 glDisable(GL_BLEND);
1903                                 glEnable(GL_DEPTH_TEST);
1904                         }
1905                 }
1906         }
1907
1908         if(v3d->zbuf) glDepthMask(1);
1909         glPointSize(1.0);
1910 }
1911
1912 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1913 {
1914         ToolSettings *ts= scene->toolsettings;
1915         int pass;
1916         unsigned char wireCol[4], selCol[4], actCol[4];
1917
1918         /* since this function does transparant... */
1919         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1920         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1921         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1922         
1923         /* when sel only is used, dont render wire, only selected, this is used for
1924          * textured draw mode when the 'edges' option is disabled */
1925         if (sel_only)
1926                 wireCol[3] = 0;
1927
1928         for (pass=0; pass<2; pass++) {
1929                         /* show wires in transparant when no zbuf clipping for select */
1930                 if (pass==0) {
1931                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1932                                 glEnable(GL_BLEND);
1933                                 glDisable(GL_DEPTH_TEST);
1934                                 selCol[3] = 85;
1935                                 if (!sel_only) wireCol[3] = 85;
1936                         } else {
1937                                 continue;
1938                         }
1939                 } else {
1940                         selCol[3] = 255;
1941                         if (!sel_only) wireCol[3] = 255;
1942                 }
1943
1944                 if(ts->selectmode == SCE_SELECT_FACE) {
1945                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1946                 }       
1947                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
1948                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
1949                                 glShadeModel(GL_SMOOTH);
1950                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1951                                 glShadeModel(GL_FLAT);
1952                         } else {
1953                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1954                         }
1955                 }
1956                 else {
1957                         if (!sel_only) {
1958                                 glColor4ubv(wireCol);
1959                                 draw_dm_edges(cageDM);
1960                         }
1961                 }
1962
1963                 if (pass==0) {
1964                         glDisable(GL_BLEND);
1965                         glEnable(GL_DEPTH_TEST);
1966                 }
1967         }
1968 }       
1969
1970 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
1971 {
1972         Mesh *me= ob->data;
1973         EditEdge *eed;
1974         EditFace *efa;
1975         float v1[3], v2[3], v3[3], v4[3], x, y, z;
1976         float fvec[3];
1977         char val[32]; /* Stores the measurement display text here */
1978         char conv_float[5]; /* Use a float conversion matching the grid size */
1979         float area, col[3]; /* area of the face,  color of the text to draw */
1980         float grid= unit->system ? unit->scale_length : v3d->grid;
1981         int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
1982         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1983                 return;
1984
1985         /* make the precision of the pronted value proportionate to the gridsize */
1986
1987         if (grid < 0.01f)
1988                 strcpy(conv_float, "%.6f");
1989         else if (grid < 0.1f)
1990                 strcpy(conv_float, "%.5f");
1991         else if (grid < 1.0f)
1992                 strcpy(conv_float, "%.4f");
1993         else if (grid < 10.0f)
1994                 strcpy(conv_float, "%.3f");
1995         else
1996                 strcpy(conv_float, "%.2f");
1997         
1998         
1999         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2000                 glDisable(GL_DEPTH_TEST);
2001
2002         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2003         
2004         if(me->drawflag & ME_DRAW_EDGELEN) {
2005                 UI_GetThemeColor3fv(TH_TEXT, col);
2006                 /* make color a bit more red */
2007                 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
2008                 else col[0]= col[0]*0.7f + 0.3f;
2009                 glColor3fv(col);
2010                 
2011                 for(eed= em->edges.first; eed; eed= eed->next) {
2012                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2013                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2014                                 VECCOPY(v1, eed->v1->co);
2015                                 VECCOPY(v2, eed->v2->co);
2016                                 
2017                                 x= 0.5f*(v1[0]+v2[0]);
2018                                 y= 0.5f*(v1[1]+v2[1]);
2019                                 z= 0.5f*(v1[2]+v2[2]);
2020                                 
2021                                 if(v3d->flag & V3D_GLOBAL_STATS) {
2022                                         mul_m4_v3(ob->obmat, v1);
2023                                         mul_m4_v3(ob->obmat, v2);
2024                                 }
2025                                 if(unit->system)
2026                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2027                                 else
2028                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2029                                 
2030                                 view3d_cached_text_draw_add(x, y, z, val, 0);
2031                         }
2032                 }
2033         }
2034
2035         if(me->drawflag & ME_DRAW_FACEAREA) {
2036 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2037                 
2038                 UI_GetThemeColor3fv(TH_TEXT, col);
2039                 /* make color a bit more green */
2040                 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
2041                 else col[1]= col[1]*0.7f + 0.3f;
2042                 glColor3fv(col);
2043                 
2044                 for(efa= em->faces.first; efa; efa= efa->next) {
2045                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
2046                                 VECCOPY(v1, efa->v1->co);
2047                                 VECCOPY(v2, efa->v2->co);
2048                                 VECCOPY(v3, efa->v3->co);
2049                                 if (efa->v4) {
2050                                         VECCOPY(v4, efa->v4->co);
2051                                 }
2052                                 if(v3d->flag & V3D_GLOBAL_STATS) {
2053                                         mul_m4_v3(ob->obmat, v1);
2054                                         mul_m4_v3(ob->obmat, v2);
2055                                         mul_m4_v3(ob->obmat, v3);
2056                                         if (efa->v4) mul_m4_v3(ob->obmat, v4);
2057                                 }
2058                                 
2059                                 if (efa->v4)
2060                                         area=  area_quad_v3(v1, v2, v3, v4);
2061                                 else
2062                                         area = area_tri_v3(v1, v2, v3);
2063
2064                                 if(unit->system)
2065                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2066                                 else
2067                                         sprintf(val, conv_float, area);
2068
2069                                 view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2070                         }
2071                 }
2072         }
2073
2074         if(me->drawflag & ME_DRAW_EDGEANG) {
2075                 EditEdge *e1, *e2, *e3, *e4;
2076                 
2077                 UI_GetThemeColor3fv(TH_TEXT, col);
2078                 /* make color a bit more blue */
2079                 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
2080                 else col[2]= col[2]*0.7f + 0.3f;
2081                 glColor3fv(col);
2082                 
2083                 for(efa= em->faces.first; efa; efa= efa->next) {
2084                         VECCOPY(v1, efa->v1->co);
2085                         VECCOPY(v2, efa->v2->co);
2086                         VECCOPY(v3, efa->v3->co);
2087                         if(efa->v4) {
2088                                 VECCOPY(v4, efa->v4->co); 
2089                         }
2090                         else {
2091                                 VECCOPY(v4, v3);
2092                         }
2093                         if(v3d->flag & V3D_GLOBAL_STATS) {
2094                                 mul_m4_v3(ob->obmat, v1);
2095                                 mul_m4_v3(ob->obmat, v2);
2096                                 mul_m4_v3(ob->obmat, v3);
2097                                 mul_m4_v3(ob->obmat, v4);
2098                         }
2099                         
2100                         e1= efa->e1;
2101                         e2= efa->e2;
2102                         e3= efa->e3;
2103                         if(efa->e4) e4= efa->e4; else e4= e3;
2104                         
2105                         /* Calculate the angles */
2106                                 
2107                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2108                                 /* Vec 1 */
2109                                 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v4, v1, v2)));
2110                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2111                                 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2112                         }
2113                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2114                                 /* Vec 2 */
2115                                 sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v1, v2, v3)));
2116                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2117                                 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2118                         }
2119                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2120                                 /* Vec 3 */
2121                                 if(efa->v4) 
2122                                         sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v4)));
2123                                 else
2124                                         sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v2, v3, v1)));
2125                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2126                                 view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2127                         }
2128                                 /* Vec 4 */
2129                         if(efa->v4) {
2130                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2131                                         sprintf(val,"%.3f", RAD2DEG(angle_v3v3v3(v3, v4, v1)));
2132                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2133                                         view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2134                                 }
2135                         }
2136                 }
2137         }
2138         
2139         if(v3d->zbuf) {
2140                 glEnable(GL_DEPTH_TEST);
2141                 bglPolygonOffset(rv3d->dist, 0.0f);
2142         }
2143 }
2144
2145 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2146 {
2147         EditFace *efa = EM_get_face_for_index(index);
2148
2149         if (efa->h==0) {
2150                 GPU_enable_material(efa->mat_nr+1, NULL);
2151                 return 1;
2152         }
2153         else
2154                 return 0;
2155 }
2156
2157 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2158 {
2159         EditFace *efa = EM_get_face_for_index(index);
2160
2161         return (efa->h==0);
2162 }
2163
2164 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2165 {
2166         Mesh *me = ob->data;
2167         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2168         EditEdge *eed_act = NULL;
2169         EditVert *eve_act = NULL;
2170         
2171         if (em->selected.last) {
2172                 EditSelection *ese = em->selected.last;
2173                 /* face is handeled above */
2174                 /*if (ese->type == EDITFACE ) {
2175                         efa_act = (EditFace *)ese->data;
2176                 } else */ if ( ese->type == EDITEDGE ) {
2177                         eed_act = (EditEdge *)ese->data;
2178                 } else if ( ese->type == EDITVERT ) {
2179                         eve_act = (EditVert *)ese->data;
2180                 }
2181         }
2182         
2183         EM_init_index_arrays(em, 1, 1, 1);
2184
2185         if(dt>OB_WIRE) {
2186                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2187                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2188                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2189
2190                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2191                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2192                                 GPU_disable_material();
2193
2194                                 glFrontFace(GL_CCW);
2195                         }
2196                         else {
2197                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2198                         }
2199                 }
2200                 else {
2201                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2202                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2203
2204                         glEnable(GL_LIGHTING);
2205                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2206
2207                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2208
2209                         glFrontFace(GL_CCW);
2210                         glDisable(GL_LIGHTING);
2211                 }
2212                         
2213                 // Setup for drawing wire over, disable zbuffer
2214                 // write to show selected edge wires better
2215                 UI_ThemeColor(TH_WIRE);
2216
2217                 bglPolygonOffset(rv3d->dist, 1.0);
2218                 glDepthMask(0);
2219         } 
2220         else {
2221                 if (cageDM!=finalDM) {
2222                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2223                         finalDM->drawEdges(finalDM, 1);
2224                 }
2225         }
2226         
2227         if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2228                 unsigned char col1[4], col2[4], col3[4];
2229                         
2230                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2231                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2232                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2233                 
2234                 glEnable(GL_BLEND);
2235                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2236                 
2237                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2238                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2239                         col1[3] = 0;
2240                 
2241                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2242
2243                 glDisable(GL_BLEND);
2244                 glDepthMask(1);         // restore write in zbuffer
2245         } else if (efa_act) {
2246                 /* even if draw faces is off it would be nice to draw the stipple face
2247                  * Make all other faces zero alpha except for the active
2248                  * */
2249                 unsigned char col1[4], col2[4], col3[4];
2250                 col1[3] = col2[3] = 0; /* dont draw */
2251                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2252                 
2253                 glEnable(GL_BLEND);
2254                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2255                 
2256                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2257
2258                 glDisable(GL_BLEND);
2259                 glDepthMask(1);         // restore write in zbuffer
2260                 
2261         }
2262
2263         /* here starts all fancy draw-extra over */
2264         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2265                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2266                 
2267                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2268                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2269                 
2270         } else {
2271                 if(me->drawflag & ME_DRAWSEAMS) {
2272                         UI_ThemeColor(TH_EDGE_SEAM);
2273                         glLineWidth(2);
2274         
2275                         draw_dm_edges_seams(cageDM);
2276         
2277                         glColor3ub(0,0,0);
2278                         glLineWidth(1);
2279                 }
2280                 
2281                 if(me->drawflag & ME_DRAWSHARP) {
2282                         UI_ThemeColor(TH_EDGE_SHARP);
2283                         glLineWidth(2);
2284         
2285                         draw_dm_edges_sharp(cageDM);
2286         
2287                         glColor3ub(0,0,0);
2288                         glLineWidth(1);
2289                 }
2290         
2291                 if(me->drawflag & ME_DRAWCREASES) {
2292                         draw_dm_creases(cageDM);
2293                 }
2294                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2295                         draw_dm_bweights(scene, cageDM);
2296                 }
2297         
2298                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2299         }
2300         if(em) {
2301 // XXX          retopo_matrix_update(v3d);
2302
2303                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2304
2305                 if(me->drawflag & ME_DRAWNORMALS) {
2306                         UI_ThemeColor(TH_NORMAL);
2307                         draw_dm_face_normals(scene, cageDM);
2308                 }
2309                 if(me->drawflag & ME_DRAW_VNORMALS) {
2310                         UI_ThemeColor(TH_NORMAL);
2311                         draw_dm_vert_normals(scene, cageDM);
2312                 }
2313
2314                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2315                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2316         }
2317
2318         if(dt>OB_WIRE) {
2319                 glDepthMask(1);
2320                 bglPolygonOffset(rv3d->dist, 0.0);
2321                 GPU_disable_material();
2322         }
2323
2324         EM_free_index_arrays();
2325 }
2326
2327 /* Mesh drawing routines */
2328
2329 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2330 {
2331         
2332         if(v3d->transp==0) {    // not when we draw the transparent pass
2333                 glLineWidth(2.0);
2334                 glDepthMask(0);
2335                 
2336                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2337                    drawFacesSolid() doesn't draw the transparent faces */
2338                 if(ob->dtx & OB_DRAWTRANSP) {
2339                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2340                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2341                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2342                         GPU_disable_material();
2343                 }
2344                 else {
2345                         dm->drawEdges(dm, 0);
2346                 }
2347                                         
2348                 glLineWidth(1.0);
2349                 glDepthMask(1);
2350         }
2351 }
2352
2353 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2354 {
2355         *drawSmooth_r = 1;
2356         return 1;
2357 }
2358
2359 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2360 {
2361         Object *ob= base->object;
2362         Mesh *me = ob->data;
2363         Material *ma= give_current_material(ob, 1);
2364         int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2365         int draw_wire = 0;
2366         int totvert, totedge, totface;
2367         DispList *dl;
2368         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2369
2370         if(!dm)
2371                 return;
2372         
2373         if (ob->dtx&OB_DRAWWIRE) {
2374                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2375         }
2376         
2377         totvert = dm->getNumVerts(dm);
2378         totedge = dm->getNumEdges(dm);
2379         totface = dm->getNumFaces(dm);
2380         
2381         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2382         if(dt!=OB_SHADED)
2383                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2384
2385                 // Unwanted combination.
2386         if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2387
2388         if(dt==OB_BOUNDBOX) {
2389                 draw_bounding_volume(scene, ob);
2390         }
2391         else if(hasHaloMat || (totface==0 && totedge==0)) {
2392                 glPointSize(1.5);
2393                 dm->drawVerts(dm);
2394                 glPointSize(1.0);
2395         }
2396         else if(dt==OB_WIRE || totface==0) {
2397                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2398         }
2399         else if(        (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2400                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2401         {
2402                 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2403
2404                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2405                         draw_mesh_object_outline(v3d, ob, dm);
2406                 }
2407
2408                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2409                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2410
2411                         dm->drawFacesGLSL(dm, GPU_enable_material);
2412 //                      if(get_ob_property(ob, "Text"))
2413 // XXX                          draw_mesh_text(ob, 1);
2414                         GPU_disable_material();
2415
2416                         glFrontFace(GL_CCW);
2417                 }
2418                 else {
2419                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2420                 }
2421
2422                 if(!faceselect) {
2423                         if(base->flag & SELECT)
2424                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2425                         else
2426                                 UI_ThemeColor(TH_WIRE);
2427
2428                         dm->drawLooseEdges(dm);
2429                 }
2430         }
2431         else if(dt==OB_SOLID) {
2432                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2433                         /* weight paint in solid mode, special case. focus on making the weights clear
2434                          * rather then the shading, this is also forced in wire view */
2435                         GPU_enable_material(0, NULL);
2436                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2437
2438                         bglPolygonOffset(rv3d->dist, 1.0);
2439                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2440
2441                         glEnable(GL_BLEND);
2442                         glColor4ub(196, 196, 196, 196);
2443                         glEnable(GL_LINE_STIPPLE);
2444                         glLineStipple(1, 0x8888);
2445
2446                         dm->drawEdges(dm, 1);
2447
2448                         bglPolygonOffset(rv3d->dist, 0.0);
2449                         glDepthMask(1);
2450                         glDisable(GL_LINE_STIPPLE);
2451
2452                         GPU_disable_material();
2453
2454
2455                 }
2456                 else {
2457                         Paint *p;
2458
2459                         if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2460                                 draw_mesh_object_outline(v3d, ob, dm);
2461
2462                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2463
2464                         glEnable(GL_LIGHTING);
2465                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2466
2467                         if(ob->sculpt && (p=paint_get_active(scene))) {
2468                                 float planes[4][4];
2469                                 float (*fpl)[4] = NULL;
2470                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2471
2472                                 if(ob->sculpt->partial_redraw) {
2473                                         sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2474                                         fpl = planes;
2475                                         ob->sculpt->partial_redraw = 0;
2476                                 }
2477
2478                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2479                         }
2480                         else
2481                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2482
2483                         GPU_disable_material();
2484
2485                         glFrontFace(GL_CCW);
2486                         glDisable(GL_LIGHTING);
2487
2488                         if(base->flag & SELECT) {
2489                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2490                         } else {
2491                                 UI_ThemeColor(TH_WIRE);
2492                         }
2493                         if(!ob->sculpt)
2494                                 dm->drawLooseEdges(dm);
2495                 }
2496         }
2497         else if(dt==OB_SHADED) {
2498                 int do_draw= 1; /* to resolve all G.f settings below... */
2499                 
2500                 if(ob==OBACT) {
2501                         do_draw= 0;
2502                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2503                                 /* enforce default material settings */
2504                                 GPU_enable_material(0, NULL);
2505                                 
2506                                 /* but set default spec */
2507                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2508                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2509                                 glColor3ub(120, 120, 120);
2510                                 glDisable(GL_COLOR_MATERIAL);
2511                                 /* diffuse */
2512                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2513                                 glEnable(GL_LIGHTING);
2514                                 glEnable(GL_COLOR_MATERIAL);
2515
2516                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2517                                 glDisable(GL_COLOR_MATERIAL);
2518                                 glDisable(GL_LIGHTING);
2519
2520                                 GPU_disable_material();
2521                         }
2522                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2523                                 if(me->mcol)
2524                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2525                                 else {
2526                                         glColor3f(1.0f, 1.0f, 1.0f);
2527                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2528                                 }
2529                         }
2530                         else do_draw= 1;
2531                 }
2532                 if(do_draw) {
2533                         dl = ob->disp.first;
2534                         if (!dl || !dl->col1) {
2535                                 /* release and reload derivedmesh because it might be freed in
2536                                    shadeDispList due to a different datamask */
2537                                 dm->release(dm);
2538                                 shadeDispList(scene, base);
2539                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2540                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2541                         }
2542
2543                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2544                                 draw_mesh_object_outline(v3d, ob, dm);
2545                         }
2546
2547                                 /* False for dupliframe objects */
2548                         if (dl) {
2549                                 unsigned int *obCol1 = dl->col1;
2550                                 unsigned int *obCol2 = dl->col2;
2551
2552                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2553                         }
2554
2555                         if(base->flag & SELECT) {
2556                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2557                         } else {
2558                                 UI_ThemeColor(TH_WIRE);
2559                         }
2560                         dm->drawLooseEdges(dm);
2561                 }
2562         }
2563         
2564         /* set default draw color back for wire or for draw-extra later on */
2565         if (dt!=OB_WIRE) {
2566                 if(base->flag & SELECT) {
2567                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2568                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2569                         else if(ob->flag & OB_FROMGROUP) 
2570                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2571                         else if(flag!=DRAW_CONSTCOLOR)
2572                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2573                         else
2574                                 glColor3ub(80,80,80);
2575                 } else {
2576                         if (ob->flag & OB_FROMGROUP) 
2577                                 UI_ThemeColor(TH_GROUP);
2578                         else {
2579                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2580                                         glColor3ub(80,80,80);
2581                                 else
2582                                         UI_ThemeColor(TH_WIRE);
2583                         }
2584                 }
2585         }
2586         if (draw_wire) {
2587
2588                 /* When using wireframe object traw in particle edit mode
2589                  * the mesh gets in the way of seeing the particles, fade the wire color
2590                  * with the background. */
2591                 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2592                         float col_wire[4], col_bg[4], col[3];
2593
2594                         UI_GetThemeColor3fv(TH_BACK, col_bg);
2595                         glGetFloatv(GL_CURRENT_COLOR, col_wire);
2596                         interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2597                         glColor3fv(col);
2598                 }
2599
2600                 /* If drawing wire and drawtype is not OB_WIRE then we are
2601                  * overlaying the wires.
2602                  *
2603                  * UPDATE bug #10290 - With this wire-only objects can draw
2604                  * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2605                  *
2606                  * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2607                  * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2608                  */
2609                 if (dt!=OB_WIRE && draw_wire==2) {
2610                         bglPolygonOffset(rv3d->dist, 1.0);
2611                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2612                 }
2613                 
2614                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2615                 
2616                 if (dt!=OB_WIRE && draw_wire==2) {
2617                         glDepthMask(1);
2618                         bglPolygonOffset(rv3d->dist, 0.0);
2619                 }
2620         }
2621
2622         dm->release(dm);
2623 }
2624
2625 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2626 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2627 {
2628         Object *ob= base->object;
2629         Object *obedit= scene->obedit;
2630         Mesh *me= ob->data;
2631         EditMesh *em= me->edit_mesh;
2632         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2633         
2634         if(obedit && ob!=obedit && ob->data==obedit->data) {
2635                 if(ob_get_key(ob));
2636                 else drawlinked= 1;
2637         }
2638         
2639         if(ob==obedit || drawlinked) {
2640                 DerivedMesh *finalDM, *cageDM;
2641                 
2642                 if (obedit!=ob)
2643                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2644                 else
2645                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2646                                                                                         v3d->customdata_mask);
2647
2648                 if(dt>OB_WIRE) {
2649                         // no transp in editmode, the fancy draw over goes bad then
2650                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2651                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2652                 }
2653
2654                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2655
2656                 GPU_end_object_materials();
2657
2658                 if (obedit!=ob && finalDM)
2659                         finalDM->release(finalDM);
2660         }
2661         else {
2662                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2663                 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2664                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2665                         check_alpha = check_material_alpha(base, me, glsl);
2666
2667                         if(dt==OB_SOLID || glsl) {
2668                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2669                                         (check_alpha)? &do_alpha_pass: NULL);
2670                         }
2671
2672                         draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
2673
2674                         GPU_end_object_materials();
2675                         
2676                         if(me->totvert==0) retval= 1;
2677                 }
2678         }
2679         
2680         /* GPU_begin_object_materials checked if this is needed */
2681         if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2682         
2683         return retval;
2684 }
2685
2686 /* ************** DRAW DISPLIST ****************** */
2687
2688 static int draw_index_wire= 1;
2689 static int index3_nors_incr= 1;
2690
2691 /* returns 1 when nothing was drawn */
2692 static int drawDispListwire(ListBase *dlbase)
2693 {
2694         DispList *dl;
2695         int parts, nr;
2696         float *data;
2697
2698         if(dlbase==NULL) return 1;
2699         
2700         glEnableClientState(GL_VERTEX_ARRAY);
2701         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2702
2703         for(dl= dlbase->first; dl; dl= dl->next) {
2704                 if(dl->parts==0 || dl->nr==0)
2705                         continue;
2706                 
2707                 data= dl->verts;
2708         
2709                 switch(dl->type) {
2710                 case DL_SEGM:
2711                         
2712                         glVertexPointer(3, GL_FLOAT, 0, data);
2713                         
2714                         for(parts=0; parts<dl->parts; parts++)
2715                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2716                                 
2717                         break;
2718                 case DL_POLY:
2719                         
2720                         glVertexPointer(3, GL_FLOAT, 0, data);
2721                         
2722                         for(parts=0; parts<dl->parts; parts++)
2723                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2724                         
2725                         break;
2726                 case DL_SURF:
2727                         
2728                         glVertexPointer(3, GL_FLOAT, 0, data);
2729                         
2730                         for(parts=0; parts<dl->parts; parts++) {
2731                                 if(dl->flag & DL_CYCL_U) 
2732                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2733                                 else
2734                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2735                         }
2736                         
2737                         for(nr=0; nr<dl->nr; nr++) {
2738                                 int ofs= 3*dl->nr;
2739                                 
2740                                 data= (  dl->verts )+3*nr;
2741                                 parts= dl->parts;
2742
2743                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2744                                 else glBegin(GL_LINE_STRIP);
2745                                 
2746                                 while(parts--) {
2747                                         glVertex3fv(data);
2748                                         data+=ofs;
2749                                 }
2750                                 glEnd();
2751                                 
2752                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2753 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2754 //                              if(dl->flag & DL_CYCL_V) 
2755 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2756 //                              else
2757 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2758                         }
2759                         break;
2760                         
2761                 case DL_INDEX3:
2762                         if(draw_index_wire) {
2763                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2764                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2765                         }
2766                         break;
2767                         
2768                 case DL_INDEX4:
2769                         if(draw_index_wire) {
2770                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2771                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2772                         }
2773                         break;
2774                 }
2775         }
2776         
2777         glDisableClientState(GL_VERTEX_ARRAY);
2778         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2779         
2780         return 0;
2781 }
2782
2783 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2784 {
2785         DispList *dl;
2786         GPUVertexAttribs gattribs;
2787         float *data, curcol[4];
2788         float *ndata;
2789         
2790         if(lb==NULL) return;
2791         
2792         /* for drawing wire */
2793         glGetFloatv(GL_CURRENT_COLOR, curcol);
2794
2795         glEnable(GL_LIGHTING);
2796         glEnableClientState(GL_VERTEX_ARRAY);
2797         
2798         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2799         else glFrontFace(GL_CCW);
2800         
2801         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2802                 glShadeModel(GL_SMOOTH);
2803         }
2804         
2805         dl= lb->first;
2806         while(dl) {
2807                 data= dl->verts;
2808                 ndata= dl->nors;
2809
2810                 switch(dl->type) {
2811                 case DL_SEGM:
2812                         if(ob->type==OB_SURF) {
2813                                 int nr;
2814
2815                                 glDisable(GL_LIGHTING);
2816                                 glColor3fv(curcol);
2817                                 
2818                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2819                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2820
2821                                 glBegin(GL_LINE_STRIP);
2822                                 for(nr= dl->nr; nr; nr--, data+=3)
2823                                         glVertex3fv(data);
2824                                 glEnd();
2825
2826                                 glEnable(GL_LIGHTING);
2827                         }
2828                         break;
2829                 case DL_POLY:
2830                         if(ob->type==OB_SURF) {
2831                                 int nr;
2832                                 
2833                                 UI_ThemeColor(TH_WIRE);
2834                                 glDisable(GL_LIGHTING);
2835                                 
2836                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2837                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2838                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2839                                 
2840                                 glBegin(GL_LINE_LOOP);
2841                                 for(nr= dl->nr; nr; nr--, data+=3)
2842                                         glVertex3fv(data);
2843                                 glEnd();
2844                                 
2845                                 glEnable(GL_LIGHTING);
2846                                 break;
2847                         }
2848                 case DL_SURF:
2849                         
2850                         if(dl->index) {
2851                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2852                                 
2853                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2854                                 else glShadeModel(GL_FLAT);
2855
2856                                 glEnableClientState(GL_NORMAL_ARRAY);
2857                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2858                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2859                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2860                                 glDisableClientState(GL_NORMAL_ARRAY);
2861                         }                       
2862                         break;
2863
2864                 case DL_INDEX3:
2865                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2866                         
2867                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2868                         
2869                         /* voor polys only one normal needed */
2870                         if(index3_nors_incr) {
2871                                 glEnableClientState(GL_NORMAL_ARRAY);
2872                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2873                         }
2874                         else
2875                                 glNormal3fv(ndata);
2876                         
2877                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2878                         
2879                         if(index3_nors_incr)
2880                                 glDisableClientState(GL_NORMAL_ARRAY);
2881
2882                         break;
2883
2884                 case DL_INDEX4:
2885                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2886                         
2887                         glEnableClientState(GL_NORMAL_ARRAY);
2888                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2889                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2890                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2891                         glDisableClientState(GL_NORMAL_ARRAY);
2892
2893                         break;
2894                 }
2895                 dl= dl->next;
2896         }
2897
2898         glDisableClientState(GL_VERTEX_ARRAY);
2899         glShadeModel(GL_FLAT);
2900         glDisable(GL_LIGHTING);
2901         glFrontFace(GL_CCW);
2902 }
2903
2904 static void drawDispListshaded(ListBase *lb, Object *ob)
2905 {
2906         DispList *dl, *dlob;
2907         unsigned int *cdata;
2908
2909         if(lb==NULL) return;
2910
2911         glShadeModel(GL_SMOOTH);
2912         glEnableClientState(GL_VERTEX_ARRAY);
2913         glEnableClientState(GL_COLOR_ARRAY);
2914         
2915         dl= lb->first;
2916         dlob= ob->disp.first;
2917         while(dl && dlob) {
2918                 
2919                 cdata= dlob->col1;
2920                 if(cdata==NULL) break;
2921                 
2922                 switch(dl->type) {
2923                 case DL_SURF:
2924                         if(dl->index) {
2925                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2926                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2927                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2928                         }                       
2929                         break;
2930
2931                 case DL_INDEX3:
2932                         
2933                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2934                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2935                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2936                         break;
2937
2938                 case DL_INDEX4:
2939                         
2940                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2941                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2942                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2943                         break;
2944                 }
2945                 
2946                 dl= dl->next;
2947                 dlob= dlob->next;
2948         }
2949         
2950         glShadeModel(GL_FLAT);
2951         glDisableClientState(GL_VERTEX_ARRAY);
2952         glDisableClientState(GL_COLOR_ARRAY);
2953 }
2954
2955 /* returns 1 when nothing was drawn */
2956 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
2957 {
2958         Object *ob= base->object;
2959         ListBase *lb=0;
2960         DispList *dl;
2961         Curve *cu;
2962         int solid, retval= 0;
2963         
2964         solid= (dt > OB_WIRE);
2965
2966         switch(ob->type) {
2967         case OB_FONT:
2968         case OB_CURVE:
2969                 cu= ob->data;
2970                 
2971                 lb= &cu->disp;
2972                 
2973                 if(solid) {
2974                         dl= lb->first;
2975                         if(dl==NULL) return 1;
2976
2977                         if(dl->nors==0) addnormalsDispList(ob, lb);
2978                         index3_nors_incr= 0;
2979                         
2980                         if( displist_has_faces(lb)==0) {
2981                                 draw_index_wire= 0;
2982                                 drawDispListwire(lb);
2983                                 draw_index_wire= 1;
2984                         }
2985                         else {
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                                         if(ob->disp.first==0) shadeDispList(scene, base);
2993                                         drawDispListshaded(lb, ob);
2994                                 }
2995                                 else {
2996                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2997                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2998                                         drawDispListsolid(lb, ob, 0);
2999                                         GPU_end_object_materials();
3000                                 }
3001                                 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
3002                                         cpack(0);
3003                                         draw_index_wire= 0;
3004                                         drawDispListwire(lb);
3005                                         draw_index_wire= 1;
3006                                 }
3007                         }
3008                         index3_nors_incr= 1;
3009                 }
3010                 else {
3011                         draw_index_wire= 0;
3012                         retval= drawDispListwire(lb);
3013                         draw_index_wire= 1;
3014                 }
3015                 break;
3016         case OB_SURF:
3017
3018                 lb= &((Curve *)ob->data)->disp;
3019                 
3020                 if(solid) {
3021                         dl= lb->first;
3022                         if(dl==NULL) return 1;
3023                         
3024                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
3025                         
3026                         if(draw_glsl_material(scene, ob, v3d, dt)) {
3027                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
3028                                 drawDispListsolid(lb, ob, 1);
3029                                 GPU_end_object_materials();
3030                         }
3031                         else if(dt==OB_SHADED) {
3032                                 if(ob->disp.first==NULL) shadeDispList(scene, base);
3033                                 drawDispListshaded(lb, ob);
3034                         }
3035                         else {
3036                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
3037                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
3038                                 drawDispListsolid(lb, ob, 0);
3039                                 GPU_end_object_materials();
3040                         }
3041                 }
3042                 else {
3043                         retval= drawDispListwire(lb);
3044                 }
3045                 break;
3046         case OB_MBALL:
3047                 
3048                 if( is_basis_mball(ob)) {
3049                         lb= &ob->disp;
3050                         if(lb->first==NULL) makeDispListMBall(scene, ob);
3051                         if(lb->first==NULL) return 1;
3052                         
3053                         if(solid) {
3054                                 
3055                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
3056                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
3057                                         drawDispListsolid(lb, ob, 1);
3058                                         GPU_end_object_materials();
3059                                 }
3060                                 else if(dt == OB_SHADED) {
3061                                         dl= lb->first;
3062                                         if(dl && dl->col1==0) shadeDispList(scene, base);