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