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