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