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