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