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