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