changes to the sequencer in trunk between 20855:20928, (excluding UI changes)
[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->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         Scene *scene= (Scene *)userData;
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]*scene->editbutsize,
1502                                         cent[1] + no[1]*scene->editbutsize,
1503                                         cent[2] + no[2]*scene->editbutsize);
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         EditVert *eve = EM_get_vert_for_index(index);
1533
1534         if (eve->h==0) {
1535                 glVertex3fv(co);
1536
1537                 if (no_f) {
1538                         glVertex3f(     co[0] + no_f[0]*scene->editbutsize,
1539                                                 co[1] + no_f[1]*scene->editbutsize,
1540                                                 co[2] + no_f[2]*scene->editbutsize);
1541                 } else {
1542                         glVertex3f(     co[0] + no_s[0]*scene->editbutsize/32767.0f,
1543                                                 co[1] + no_s[1]*scene->editbutsize/32767.0f,
1544                                                 co[2] + no_s[2]*scene->editbutsize/32767.0f);
1545                 }
1546         }
1547 }
1548 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1549 {
1550         glBegin(GL_LINES);
1551         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1552         glEnd();
1553 }
1554
1555         /* Draw verts with color set based on selection */
1556 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1557 {
1558         struct { int sel; EditVert *eve_act; } * data = userData;
1559         EditVert *eve = EM_get_vert_for_index(index);
1560
1561         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1562                 /* draw active larger - need to stop/start point drawing for this :/ */
1563                 if (eve==data->eve_act) {
1564                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1565                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1566                         
1567                         bglEnd();
1568                         
1569                         glPointSize(size);
1570                         bglBegin(GL_POINTS);
1571                         bglVertex3fv(co);
1572                         bglEnd();
1573                         
1574                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1575                         glPointSize(size);
1576                         bglBegin(GL_POINTS);
1577                 } else {
1578                         bglVertex3fv(co);
1579                 }
1580         }
1581 }
1582 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1583 {
1584         struct { int sel; EditVert *eve_act; } data;
1585         data.sel = sel;
1586         data.eve_act = eve_act;
1587         
1588         bglBegin(GL_POINTS);
1589         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1590         bglEnd();
1591 }
1592
1593         /* Draw edges with color set based on selection */
1594 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1595 {
1596         EditEdge *eed = EM_get_edge_for_index(index);
1597         //unsigned char **cols = userData, *col;
1598         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1599         unsigned char *col;
1600
1601         if (eed->h==0) {
1602                 if (eed==data->eed_act) {
1603                         glColor4ubv(data->actCol);
1604                 } else {
1605                         if (eed->f&SELECT) {
1606                                 col = data->selCol;
1607                         } else {
1608                                 col = data->baseCol;
1609                         }
1610                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1611                         if (col[3]==0) return 0;
1612                         
1613                         glColor4ubv(col);
1614                 }
1615                 return 1;
1616         } else {
1617                 return 0;
1618         }
1619 }
1620 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1621 {
1622         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1623         
1624         data.baseCol = baseCol;
1625         data.selCol = selCol;
1626         data.actCol = actCol;
1627         data.eed_act = eed_act;
1628         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1629 }
1630
1631         /* Draw edges */
1632 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1633 {
1634         return EM_get_edge_for_index(index)->h==0;
1635 }
1636 static void draw_dm_edges(DerivedMesh *dm) 
1637 {
1638         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1639 }
1640
1641         /* Draw edges with color interpolated based on selection */
1642 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1643 {
1644         return EM_get_edge_for_index(index)->h==0;
1645 }
1646 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1647 {
1648         EditEdge *eed = EM_get_edge_for_index(index);
1649         unsigned char **cols = userData;
1650         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1651         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1652
1653         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1654                                 col0[1] + (col1[1]-col0[1])*t,
1655                                 col0[2] + (col1[2]-col0[2])*t,
1656                                 col0[3] + (col1[3]-col0[3])*t);
1657 }
1658 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1659 {
1660         unsigned char *cols[2];
1661         cols[0] = baseCol;
1662         cols[1] = selCol;
1663         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1664 }
1665
1666         /* Draw only seam edges */
1667 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1668 {
1669         EditEdge *eed = EM_get_edge_for_index(index);
1670
1671         return (eed->h==0 && eed->seam);
1672 }
1673 static void draw_dm_edges_seams(DerivedMesh *dm)
1674 {
1675         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1676 }
1677
1678         /* Draw only sharp edges */
1679 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1680 {
1681         EditEdge *eed = EM_get_edge_for_index(index);
1682
1683         return (eed->h==0 && eed->sharp);
1684 }
1685 static void draw_dm_edges_sharp(DerivedMesh *dm)
1686 {
1687         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1688 }
1689
1690
1691         /* Draw faces with color set based on selection
1692          * return 2 for the active face so it renders with stipple enabled */
1693 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1694 {
1695         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1696         EditFace *efa = EM_get_face_for_index(index);
1697         unsigned char *col;
1698         
1699         if (efa->h==0) {
1700                 if (efa == data->efa_act) {
1701                         glColor4ubv(data->cols[2]);
1702                         return 2; /* stipple */
1703                 } else {
1704                         col = data->cols[(efa->f&SELECT)?1:0];
1705                         if (col[3]==0) return 0;
1706                         glColor4ubv(col);
1707                         return 1;
1708                 }
1709         }
1710         return 0;
1711 }
1712
1713 /* also draws the active face */
1714 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1715 {
1716         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1717         data.cols[0] = baseCol;
1718         data.cols[1] = selCol;
1719         data.cols[2] = actCol;
1720         data.efa_act = efa_act;
1721         
1722         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1723 }
1724
1725 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1726 {
1727         EditEdge *eed = EM_get_edge_for_index(index);
1728
1729         if (eed->h==0 && eed->crease!=0.0) {
1730                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1731                 return 1;
1732         } else {
1733                 return 0;
1734         }
1735 }
1736 static void draw_dm_creases(DerivedMesh *dm)
1737 {
1738         glLineWidth(3.0);
1739         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1740         glLineWidth(1.0);
1741 }
1742
1743 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1744 {
1745         EditEdge *eed = EM_get_edge_for_index(index);
1746
1747         if (eed->h==0 && eed->bweight!=0.0) {
1748                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1749                 return 1;
1750         } else {
1751                 return 0;
1752         }
1753 }
1754 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1755 {
1756         EditVert *eve = EM_get_vert_for_index(index);
1757
1758         if (eve->h==0 && eve->bweight!=0.0) {
1759                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1760                 bglVertex3fv(co);
1761         }
1762 }
1763 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1764 {
1765         if (scene->selectmode & SCE_SELECT_VERTEX) {
1766                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1767                 bglBegin(GL_POINTS);
1768                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1769                 bglEnd();
1770         }
1771         else {
1772                 glLineWidth(3.0);
1773                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1774                 glLineWidth(1.0);
1775         }
1776 }
1777
1778 /* Second section of routines: Combine first sets to form fancy
1779  * drawing routines (for example rendering twice to get overlays).
1780  *
1781  * Also includes routines that are basic drawing but are too
1782  * specialized to be split out (like drawing creases or measurements).
1783  */
1784
1785 /* EditMesh drawing routines*/
1786
1787 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1788 {
1789         int sel;
1790
1791         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
1792
1793         for (sel=0; sel<2; sel++) {
1794                 char col[4], fcol[4];
1795                 int pass;
1796
1797                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1798                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1799
1800                 for (pass=0; pass<2; pass++) {
1801                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1802                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1803
1804                         if (pass==0) {
1805                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1806                                         glDisable(GL_DEPTH_TEST);
1807                                                 
1808                                         glEnable(GL_BLEND);
1809                                 } else {
1810                                         continue;
1811                                 }
1812
1813                                 size = (size>2.1?size/2.0:size);
1814                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1815                                 col[3] = fcol[3] = 100;
1816                         } else {
1817                                 col[3] = fcol[3] = 255;
1818                         }
1819                                 
1820                         if(scene->selectmode & SCE_SELECT_VERTEX) {
1821                                 glPointSize(size);
1822                                 glColor4ubv((GLubyte *)col);
1823                                 draw_dm_verts(cageDM, sel, eve_act);
1824                         }
1825                         
1826                         if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
1827                                 glPointSize(fsize);
1828                                 glColor4ubv((GLubyte *)fcol);
1829                                 draw_dm_face_centers(cageDM, sel);
1830                         }
1831                         
1832                         if (pass==0) {
1833                                 glDisable(GL_BLEND);
1834                                 glEnable(GL_DEPTH_TEST);
1835                         }
1836                 }
1837         }
1838
1839         if(v3d->zbuf) glDepthMask(1);
1840         glPointSize(1.0);
1841 }
1842
1843 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1844 {
1845         int pass;
1846         unsigned char wireCol[4], selCol[4], actCol[4];
1847
1848         /* since this function does transparant... */
1849         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1850         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1851         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1852         
1853         /* when sel only is used, dont render wire, only selected, this is used for
1854          * textured draw mode when the 'edges' option is disabled */
1855         if (sel_only)
1856                 wireCol[3] = 0;
1857
1858         for (pass=0; pass<2; pass++) {
1859                         /* show wires in transparant when no zbuf clipping for select */
1860                 if (pass==0) {
1861                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1862                                 glEnable(GL_BLEND);
1863                                 glDisable(GL_DEPTH_TEST);
1864                                 selCol[3] = 85;
1865                                 if (!sel_only) wireCol[3] = 85;
1866                         } else {
1867                                 continue;
1868                         }
1869                 } else {
1870                         selCol[3] = 255;
1871                         if (!sel_only) wireCol[3] = 255;
1872                 }
1873
1874                 if(scene->selectmode == SCE_SELECT_FACE) {
1875                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1876                 }       
1877                 else if( (me->drawflag & ME_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {     
1878                         if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
1879                                 glShadeModel(GL_SMOOTH);
1880                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1881                                 glShadeModel(GL_FLAT);
1882                         } else {
1883                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1884                         }
1885                 }
1886                 else {
1887                         if (!sel_only) {
1888                                 glColor4ubv(wireCol);
1889                                 draw_dm_edges(cageDM);
1890                         }
1891                 }
1892
1893                 if (pass==0) {
1894                         glDisable(GL_BLEND);
1895                         glEnable(GL_DEPTH_TEST);
1896                 }
1897         }
1898 }       
1899
1900 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em)
1901 {
1902         Mesh *me= ob->data;
1903         EditEdge *eed;
1904         EditFace *efa;
1905         float v1[3], v2[3], v3[3], v4[3], x, y, z;
1906         float fvec[3];
1907         char val[32]; /* Stores the measurement display text here */
1908         char conv_float[5]; /* Use a float conversion matching the grid size */
1909         float area, col[3]; /* area of the face,  color of the text to draw */
1910         
1911         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1912                 return;
1913
1914         /* make the precission of the pronted value proportionate to the gridsize */
1915         if ((v3d->grid) < 0.01)
1916                 strcpy(conv_float, "%.6f");
1917         else if ((v3d->grid) < 0.1)
1918                 strcpy(conv_float, "%.5f");
1919         else if ((v3d->grid) < 1.0)
1920                 strcpy(conv_float, "%.4f");
1921         else if ((v3d->grid) < 10.0)
1922                 strcpy(conv_float, "%.3f");
1923         else
1924                 strcpy(conv_float, "%.2f");
1925         
1926         
1927         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1928                 glDisable(GL_DEPTH_TEST);
1929
1930         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0);
1931         
1932         if(me->drawflag & ME_DRAW_EDGELEN) {
1933                 UI_GetThemeColor3fv(TH_TEXT, col);
1934                 /* make color a bit more red */
1935                 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1936                 else col[0]= col[0]*0.7 + 0.3;
1937                 glColor3fv(col);
1938                 
1939                 for(eed= em->edges.first; eed; eed= eed->next) {
1940                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1941                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1942                                 VECCOPY(v1, eed->v1->co);
1943                                 VECCOPY(v2, eed->v2->co);
1944                                 
1945                                 x= 0.5*(v1[0]+v2[0]);
1946                                 y= 0.5*(v1[1]+v2[1]);
1947                                 z= 0.5*(v1[2]+v2[2]);
1948                                 
1949                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1950                                         Mat4MulVecfl(ob->obmat, v1);
1951                                         Mat4MulVecfl(ob->obmat, v2);
1952                                 }
1953                                 
1954                                 sprintf(val, conv_float, VecLenf(v1, v2));
1955                                 view3d_object_text_draw_add(x, y, z, val, 0);
1956                         }
1957                 }
1958         }
1959
1960         if(me->drawflag & ME_DRAW_FACEAREA) {
1961 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1962                 
1963                 UI_GetThemeColor3fv(TH_TEXT, col);
1964                 /* make color a bit more green */
1965                 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1966                 else col[1]= col[1]*0.7 + 0.3;
1967                 glColor3fv(col);
1968                 
1969                 for(efa= em->faces.first; efa; efa= efa->next) {
1970                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1971                                 VECCOPY(v1, efa->v1->co);
1972                                 VECCOPY(v2, efa->v2->co);
1973                                 VECCOPY(v3, efa->v3->co);
1974                                 if (efa->v4) {
1975                                         VECCOPY(v4, efa->v4->co);
1976                                 }
1977                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1978                                         Mat4MulVecfl(ob->obmat, v1);
1979                                         Mat4MulVecfl(ob->obmat, v2);
1980                                         Mat4MulVecfl(ob->obmat, v3);
1981                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1982                                 }
1983                                 
1984                                 if (efa->v4)
1985                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1986                                 else
1987                                         area = AreaT3Dfl(v1, v2, v3);
1988
1989                                 sprintf(val, conv_float, area);
1990                                 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
1991                         }
1992                 }
1993         }
1994
1995         if(me->drawflag & ME_DRAW_EDGEANG) {
1996                 EditEdge *e1, *e2, *e3, *e4;
1997                 
1998                 UI_GetThemeColor3fv(TH_TEXT, col);
1999                 /* make color a bit more blue */
2000                 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
2001                 else col[2]= col[2]*0.7 + 0.3;
2002                 glColor3fv(col);
2003                 
2004                 for(efa= em->faces.first; efa; efa= efa->next) {
2005                         VECCOPY(v1, efa->v1->co);
2006                         VECCOPY(v2, efa->v2->co);
2007                         VECCOPY(v3, efa->v3->co);
2008                         if(efa->v4) {
2009                                 VECCOPY(v4, efa->v4->co); 
2010                         }
2011                         else {
2012                                 VECCOPY(v4, v3);
2013                         }
2014                         if(v3d->flag & V3D_GLOBAL_STATS) {
2015                                 Mat4MulVecfl(ob->obmat, v1);
2016                                 Mat4MulVecfl(ob->obmat, v2);
2017                                 Mat4MulVecfl(ob->obmat, v3);
2018                                 Mat4MulVecfl(ob->obmat, v4);
2019                         }
2020                         
2021                         e1= efa->e1;
2022                         e2= efa->e2;
2023                         e3= efa->e3;
2024                         if(efa->e4) e4= efa->e4; else e4= e3;
2025                         
2026                         /* Calculate the angles */
2027                                 
2028                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
2029                                 /* Vec 1 */
2030                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
2031                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
2032                                 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
2033                         }
2034                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
2035                                 /* Vec 2 */
2036                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
2037                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
2038                                 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2039                         }
2040                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2041                                 /* Vec 3 */
2042                                 if(efa->v4) 
2043                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
2044                                 else
2045                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
2046                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
2047                                 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2048                         }
2049                                 /* Vec 4 */
2050                         if(efa->v4) {
2051                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2052                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
2053                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
2054                                         view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2055                                 }
2056                         }
2057                 }
2058         }    
2059         
2060         if(v3d->zbuf) {
2061                 glEnable(GL_DEPTH_TEST);
2062                 bglPolygonOffset(rv3d->dist, 0.0);
2063         }
2064 }
2065
2066 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2067 {
2068         EditFace *efa = EM_get_face_for_index(index);
2069
2070         if (efa->h==0) {
2071                 GPU_enable_material(efa->mat_nr+1, NULL);
2072                 return 1;
2073         }
2074         else
2075                 return 0;
2076 }
2077
2078 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2079 {
2080         EditFace *efa = EM_get_face_for_index(index);
2081
2082         return (efa->h==0);
2083 }
2084
2085 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2086 {
2087         Mesh *me = ob->data;
2088         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2089         EditEdge *eed_act = NULL;
2090         EditVert *eve_act = NULL;
2091         
2092         if (em->selected.last) {
2093                 EditSelection *ese = em->selected.last;
2094                 /* face is handeled above */
2095                 /*if (ese->type == EDITFACE ) {
2096                         efa_act = (EditFace *)ese->data;
2097                 } else */ if ( ese->type == EDITEDGE ) {
2098                         eed_act = (EditEdge *)ese->data;
2099                 } else if ( ese->type == EDITVERT ) {
2100                         eve_act = (EditVert *)ese->data;
2101                 }
2102         }
2103         
2104         EM_init_index_arrays(em, 1, 1, 1);
2105
2106         if(dt>OB_WIRE) {
2107                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2108                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2109                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2110
2111                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2112                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2113                                 GPU_disable_material();
2114
2115                                 glFrontFace(GL_CCW);
2116                         }
2117                         else {
2118                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2119                         }
2120                 }
2121                 else {
2122                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2123
2124                         glEnable(GL_LIGHTING);
2125                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2126
2127                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2128
2129                         glFrontFace(GL_CCW);
2130                         glDisable(GL_LIGHTING);
2131                 }
2132                         
2133                 // Setup for drawing wire over, disable zbuffer
2134                 // write to show selected edge wires better
2135                 UI_ThemeColor(TH_WIRE);
2136
2137                 bglPolygonOffset(rv3d->dist, 1.0);
2138                 glDepthMask(0);
2139         } 
2140         else {
2141                 if (cageDM!=finalDM) {
2142                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2143                         finalDM->drawEdges(finalDM, 1);
2144                 }
2145         }
2146         
2147         if((me->drawflag & (ME_DRAWFACES)) || FACESEL_PAINT_TEST) {     /* transp faces */
2148                 unsigned char col1[4], col2[4], col3[4];
2149                         
2150                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2151                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2152                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2153                 
2154                 glEnable(GL_BLEND);
2155                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2156                 
2157                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2158                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2159                         col1[3] = 0;
2160                 
2161                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2162
2163                 glDisable(GL_BLEND);
2164                 glDepthMask(1);         // restore write in zbuffer
2165         } else if (efa_act) {
2166                 /* even if draw faces is off it would be nice to draw the stipple face
2167                  * Make all other faces zero alpha except for the active
2168                  * */
2169                 unsigned char col1[4], col2[4], col3[4];
2170                 col1[3] = col2[3] = 0; /* dont draw */
2171                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2172                 
2173                 glEnable(GL_BLEND);
2174                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2175                 
2176                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2177
2178                 glDisable(GL_BLEND);
2179                 glDepthMask(1);         // restore write in zbuffer
2180                 
2181         }
2182
2183         /* here starts all fancy draw-extra over */
2184         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2185                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2186                 
2187                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2188                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2189                 
2190         } else {
2191                 if(me->drawflag & ME_DRAWSEAMS) {
2192                         UI_ThemeColor(TH_EDGE_SEAM);
2193                         glLineWidth(2);
2194         
2195                         draw_dm_edges_seams(cageDM);
2196         
2197                         glColor3ub(0,0,0);
2198                         glLineWidth(1);
2199                 }
2200                 
2201                 if(me->drawflag & ME_DRAWSHARP) {
2202                         UI_ThemeColor(TH_EDGE_SHARP);
2203                         glLineWidth(2);
2204         
2205                         draw_dm_edges_sharp(cageDM);
2206         
2207                         glColor3ub(0,0,0);
2208                         glLineWidth(1);
2209                 }
2210         
2211                 if(me->drawflag & ME_DRAWCREASES) {
2212                         draw_dm_creases(cageDM);
2213                 }
2214                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2215                         draw_dm_bweights(scene, cageDM);
2216                 }
2217         
2218                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2219         }
2220         if(em) {
2221 // XXX          retopo_matrix_update(v3d);
2222
2223                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2224
2225                 if(me->drawflag & ME_DRAWNORMALS) {
2226                         UI_ThemeColor(TH_NORMAL);
2227                         draw_dm_face_normals(scene, cageDM);
2228                 }
2229                 if(me->drawflag & ME_DRAW_VNORMALS) {
2230                         UI_ThemeColor(TH_NORMAL);
2231                         draw_dm_vert_normals(scene, cageDM);
2232                 }
2233
2234                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2235                         draw_em_measure_stats(v3d, rv3d, ob, em);
2236         }
2237
2238         if(dt>OB_WIRE) {
2239                 glDepthMask(1);
2240                 bglPolygonOffset(rv3d->dist, 0.0);
2241                 GPU_disable_material();
2242         }
2243
2244         EM_free_index_arrays();
2245 }
2246
2247 /* Mesh drawing routines */
2248
2249 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2250 {
2251         
2252         if(v3d->transp==0) {    // not when we draw the transparent pass
2253                 glLineWidth(2.0);
2254                 glDepthMask(0);
2255                 
2256                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2257                    drawFacesSolid() doesn't draw the transparent faces */
2258                 if(ob->dtx & OB_DRAWTRANSP) {
2259                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2260                         dm->drawFacesSolid(dm, GPU_enable_material);
2261                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2262                         GPU_disable_material();
2263                 }
2264                 else {
2265                         dm->drawEdges(dm, 0);
2266                 }
2267                                         
2268                 glLineWidth(1.0);
2269                 glDepthMask(1);
2270         }
2271 }
2272
2273 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2274 {
2275         *drawSmooth_r = 1;
2276         return 1;
2277 }
2278
2279 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2280 {
2281         Object *ob= base->object;
2282         Mesh *me = ob->data;
2283         Material *ma= give_current_material(ob, 1);
2284         int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2285         int draw_wire = 0;
2286         int totvert, totedge, totface;
2287         DispList *dl;
2288         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2289
2290         if(!dm)
2291                 return;
2292         
2293         if (ob->dtx&OB_DRAWWIRE) {
2294                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2295         }
2296         
2297         totvert = dm->getNumVerts(dm);
2298         totedge = dm->getNumEdges(dm);
2299         totface = dm->getNumFaces(dm);
2300         
2301         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2302         if(dt!=OB_SHADED)
2303                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2304
2305                 // Unwanted combination.
2306         if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2307
2308         if(dt==OB_BOUNDBOX) {
2309                 draw_bounding_volume(scene, ob);
2310         }
2311         else if(hasHaloMat || (totface==0 && totedge==0)) {
2312                 glPointSize(1.5);
2313                 dm->drawVerts(dm);
2314                 glPointSize(1.0);
2315         }
2316         else if(dt==OB_WIRE || totface==0) {
2317                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2318         }
2319         else if(        (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2320                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2321         {
2322                 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2323
2324                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2325                         draw_mesh_object_outline(v3d, ob, dm);
2326                 }
2327
2328                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2329                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2330
2331                         dm->drawFacesGLSL(dm, GPU_enable_material);
2332 //                      if(get_ob_property(ob, "Text"))
2333 // XXX                          draw_mesh_text(ob, 1);
2334                         GPU_disable_material();
2335
2336                         glFrontFace(GL_CCW);
2337                 }
2338                 else {
2339                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2340                 }
2341
2342                 if(!faceselect) {
2343                         if(base->flag & SELECT)
2344                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2345                         else
2346                                 UI_ThemeColor(TH_WIRE);
2347
2348                         dm->drawLooseEdges(dm);
2349                 }
2350         }
2351         else if(dt==OB_SOLID) {
2352                 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2353                         draw_mesh_object_outline(v3d, ob, dm);
2354
2355                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2356
2357                 glEnable(GL_LIGHTING);
2358                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2359
2360                 dm->drawFacesSolid(dm, GPU_enable_material);
2361                 GPU_disable_material();
2362
2363                 glFrontFace(GL_CCW);
2364                 glDisable(GL_LIGHTING);
2365
2366                 if(base->flag & SELECT) {
2367                         UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2368                 } else {
2369                         UI_ThemeColor(TH_WIRE);
2370                 }
2371                 dm->drawLooseEdges(dm);
2372         }
2373         else if(dt==OB_SHADED) {
2374                 int do_draw= 1; /* to resolve all G.f settings below... */
2375                 
2376                 if(ob==OBACT) {
2377                         do_draw= 0;
2378                         if( (G.f & G_WEIGHTPAINT)) {
2379                                 /* enforce default material settings */
2380                                 GPU_enable_material(0, NULL);
2381                                 
2382                                 /* but set default spec */
2383                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2384                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2385                                 glColor3ub(120, 120, 120);
2386                                 glDisable(GL_COLOR_MATERIAL);
2387                                 /* diffuse */
2388                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2389                                 glEnable(GL_LIGHTING);
2390                                 glEnable(GL_COLOR_MATERIAL);
2391
2392                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2393                                 glDisable(GL_COLOR_MATERIAL);
2394                                 glDisable(GL_LIGHTING);
2395
2396                                 GPU_disable_material();
2397                         }
2398                         else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2399                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2400                         }
2401                         else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2402                                 glColor3f(1.0f, 1.0f, 1.0f);
2403                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2404                         }
2405                         else do_draw= 1;
2406                 }
2407                 if(do_draw) {
2408                         dl = ob->disp.first;
2409                         if (!dl || !dl->col1) {
2410                                 /* release and reload derivedmesh because it might be freed in
2411                                    shadeDispList due to a different datamask */
2412                                 dm->release(dm);
2413                                 shadeDispList(scene, base);
2414                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2415                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2416                         }
2417
2418                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2419                                 draw_mesh_object_outline(v3d, ob, dm);
2420                         }
2421
2422                                 /* False for dupliframe objects */
2423                         if (dl) {
2424                                 unsigned int *obCol1 = dl->col1;
2425                                 unsigned int *obCol2 = dl->col2;
2426
2427                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2428                         }
2429
2430                         if(base->flag & SELECT) {
2431                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2432                         } else {
2433                                 UI_ThemeColor(TH_WIRE);
2434                         }
2435                         dm->drawLooseEdges(dm);
2436                 }
2437         }
2438         
2439         /* set default draw color back for wire or for draw-extra later on */
2440         if (dt!=OB_WIRE) {
2441                 if(base->flag & SELECT) {
2442                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2443                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2444                         else if(ob->flag & OB_FROMGROUP) 
2445                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2446                         else if(flag!=DRAW_CONSTCOLOR)
2447                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2448                         else
2449                                 glColor3ub(80,80,80);
2450                 } else {
2451                         if (ob->flag & OB_FROMGROUP) 
2452                                 UI_ThemeColor(TH_GROUP);
2453                         else {
2454                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2455                                         glColor3ub(80,80,80);
2456                                 else
2457                                         UI_ThemeColor(TH_WIRE);
2458                         }
2459                 }
2460         }
2461         if (draw_wire) {
2462                         /* If drawing wire and drawtype is not OB_WIRE then we are
2463                                 * overlaying the wires.
2464                                 *
2465                                 * UPDATE bug #10290 - With this wire-only objects can draw
2466                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2467                                 * 
2468                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2469                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2470                                 */
2471                 if (dt!=OB_WIRE && draw_wire==2) {
2472                         bglPolygonOffset(rv3d->dist, 1.0);
2473                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2474                 }
2475                 
2476                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2477                 
2478                 if (dt!=OB_WIRE && draw_wire==2) {
2479                         glDepthMask(1);
2480                         bglPolygonOffset(rv3d->dist, 0.0);
2481                 }
2482         }
2483
2484         dm->release(dm);
2485 }
2486
2487 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2488 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2489 {
2490         Object *ob= base->object;
2491         Object *obedit= scene->obedit;
2492         Mesh *me= ob->data;
2493         EditMesh *em= me->edit_mesh;
2494         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2495         
2496         if(obedit && ob!=obedit && ob->data==obedit->data) {
2497                 if(ob_get_key(ob));
2498                 else drawlinked= 1;
2499         }
2500         
2501         if(ob==obedit || drawlinked) {
2502                 DerivedMesh *finalDM, *cageDM;
2503                 
2504                 if (obedit!=ob)
2505                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2506                 else
2507                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2508                                                         v3d->customdata_mask);
2509
2510                 if(dt>OB_WIRE) {
2511                         // no transp in editmode, the fancy draw over goes bad then
2512                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2513                         GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2514                 }
2515
2516                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2517
2518                 if (obedit!=ob && finalDM)
2519                         finalDM->release(finalDM);
2520         }
2521 //      else if(!em && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2522 //              OBACT==ob && !sculpt_modifiers_active(ob)) {
2523 // XXX          sculptmode_draw_mesh(0);
2524 //      }
2525         else {
2526                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2527                 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2528                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2529                         check_alpha = check_material_alpha(base, me, glsl);
2530
2531                         if(dt==OB_SOLID || glsl) {
2532                                 GPU_set_object_materials(v3d, rv3d, scene, ob, glsl,
2533                                         (check_alpha)? &do_alpha_pass: NULL);
2534                         }
2535
2536                         draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
2537                         
2538                         if(me->totvert==0) retval= 1;
2539                 }
2540         }
2541         
2542         /* GPU_set_object_materials checked if this is needed */
2543         if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2544         
2545         return retval;
2546 }
2547
2548 /* ************** DRAW DISPLIST ****************** */
2549
2550 static int draw_index_wire= 1;
2551 static int index3_nors_incr= 1;
2552
2553 /* returns 1 when nothing was drawn */
2554 static int drawDispListwire(ListBase *dlbase)
2555 {
2556         DispList *dl;
2557         int parts, nr;
2558         float *data;
2559
2560         if(dlbase==NULL) return 1;
2561         
2562         glDisableClientState(GL_NORMAL_ARRAY);
2563         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2564
2565         for(dl= dlbase->first; dl; dl= dl->next) {
2566                 if(dl->parts==0 || dl->nr==0)
2567                         continue;
2568                 
2569                 data= dl->verts;
2570         
2571                 switch(dl->type) {
2572                 case DL_SEGM:
2573                         
2574                         glVertexPointer(3, GL_FLOAT, 0, data);
2575                         
2576                         for(parts=0; parts<dl->parts; parts++)
2577                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2578                                 
2579                         break;
2580                 case DL_POLY:
2581                         
2582                         glVertexPointer(3, GL_FLOAT, 0, data);
2583                         
2584                         for(parts=0; parts<dl->parts; parts++)
2585                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2586                         
2587                         break;
2588                 case DL_SURF:
2589                         
2590                         glVertexPointer(3, GL_FLOAT, 0, data);
2591                         
2592                         for(parts=0; parts<dl->parts; parts++) {
2593                                 if(dl->flag & DL_CYCL_U) 
2594                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2595                                 else
2596                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2597                         }
2598                         
2599                         for(nr=0; nr<dl->nr; nr++) {
2600                                 int ofs= 3*dl->nr;
2601                                 
2602                                 data= (  dl->verts )+3*nr;
2603                                 parts= dl->parts;
2604
2605                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2606                                 else glBegin(GL_LINE_STRIP);
2607                                 
2608                                 while(parts--) {
2609                                         glVertex3fv(data);
2610                                         data+=ofs;
2611                                 }
2612                                 glEnd();
2613                                 
2614                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2615 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2616 //                              if(dl->flag & DL_CYCL_V) 
2617 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2618 //                              else
2619 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2620                         }
2621                         break;
2622                         
2623                 case DL_INDEX3:
2624                         if(draw_index_wire) {
2625                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2626                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2627                         }
2628                         break;
2629                         
2630                 case DL_INDEX4:
2631                         if(draw_index_wire) {
2632                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2633                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2634                         }
2635                         break;
2636                 }
2637         }
2638         
2639         glEnableClientState(GL_NORMAL_ARRAY);
2640         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2641         
2642         return 0;
2643 }
2644
2645 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2646 {
2647         DispList *dl;
2648         GPUVertexAttribs gattribs;
2649         float *data, curcol[4];
2650         float *ndata;
2651         
2652         if(lb==NULL) return;
2653         
2654         /* for drawing wire */
2655         glGetFloatv(GL_CURRENT_COLOR, curcol);
2656
2657         glEnable(GL_LIGHTING);
2658         
2659         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2660         else glFrontFace(GL_CCW);
2661         
2662         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2663                 glShadeModel(GL_SMOOTH);
2664         }
2665         
2666         dl= lb->first;
2667         while(dl) {
2668                 data= dl->verts;
2669                 ndata= dl->nors;
2670
2671                 switch(dl->type) {
2672                 case DL_SEGM:
2673                         if(ob->type==OB_SURF) {
2674                                 int nr;
2675
2676                                 glDisable(GL_LIGHTING);
2677                                 glColor3fv(curcol);
2678                                 
2679                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2680                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2681
2682                                 glBegin(GL_LINE_STRIP);
2683                                 for(nr= dl->nr; nr; nr--, data+=3)
2684                                         glVertex3fv(data);
2685                                 glEnd();
2686
2687                                 glEnable(GL_LIGHTING);
2688                         }
2689                         break;
2690                 case DL_POLY:
2691                         if(ob->type==OB_SURF) {
2692                                 int nr;
2693                                 
2694                                 UI_ThemeColor(TH_WIRE);
2695                                 glDisable(GL_LIGHTING);
2696                                 
2697                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2698                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2699                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2700                                 
2701                                 glBegin(GL_LINE_LOOP);
2702                                 for(nr= dl->nr; nr; nr--, data+=3)
2703                                         glVertex3fv(data);
2704                                 glEnd();
2705                                 
2706                                 glEnable(GL_LIGHTING);
2707                                 break;
2708                         }
2709                 case DL_SURF:
2710                         
2711                         if(dl->index) {
2712                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2713                                 
2714                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2715                                 else glShadeModel(GL_FLAT);
2716                                 
2717                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2718                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2719                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2720                                 GPU_disable_material();
2721                         }                       
2722                         break;
2723
2724                 case DL_INDEX3:
2725                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2726                         
2727                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2728                         
2729                         /* voor polys only one normal needed */
2730                         if(index3_nors_incr==0) {
2731                                 glDisableClientState(GL_NORMAL_ARRAY);
2732                                 glNormal3fv(ndata);
2733                         }
2734                         else
2735                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2736                         
2737                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2738                         GPU_disable_material();
2739                         
2740                         if(index3_nors_incr==0)
2741                                 glEnableClientState(GL_NORMAL_ARRAY);
2742
2743                         break;
2744
2745                 case DL_INDEX4:
2746                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2747                         
2748                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2749                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2750                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2751
2752                         GPU_disable_material();
2753                         
2754                         break;
2755                 }
2756                 dl= dl->next;
2757         }
2758
2759         glShadeModel(GL_FLAT);
2760         glDisable(GL_LIGHTING);
2761         glFrontFace(GL_CCW);
2762 }
2763
2764 static void drawDispListshaded(ListBase *lb, Object *ob)
2765 {
2766         DispList *dl, *dlob;
2767         unsigned int *cdata;
2768
2769         if(lb==NULL) return;
2770
2771         glShadeModel(GL_SMOOTH);
2772         glDisableClientState(GL_NORMAL_ARRAY);
2773         glEnableClientState(GL_COLOR_ARRAY);
2774         
2775         dl= lb->first;
2776         dlob= ob->disp.first;
2777         while(dl && dlob) {
2778                 
2779                 cdata= dlob->col1;
2780                 if(cdata==NULL) break;
2781                 
2782                 switch(dl->type) {
2783                 case DL_SURF:
2784                         if(dl->index) {
2785                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2786                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2787                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2788                         }                       
2789                         break;
2790
2791                 case DL_INDEX3:
2792                         
2793                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2794                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2795                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2796                         break;
2797
2798                 case DL_INDEX4:
2799                         
2800                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2801                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2802                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2803                         break;
2804                 }
2805                 
2806                 dl= dl->next;
2807                 dlob= dlob->next;
2808         }
2809         
2810         glShadeModel(GL_FLAT);
2811         glEnableClientState(GL_NORMAL_ARRAY);
2812         glDisableClientState(GL_COLOR_ARRAY);
2813 }
2814
2815 /* returns 1 when nothing was drawn */
2816 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
2817 {
2818         Object *ob= base->object;
2819         ListBase *lb=0;
2820         DispList *dl;
2821         Curve *cu;
2822         int solid, retval= 0;
2823         
2824         solid= (dt > OB_WIRE);
2825
2826         switch(ob->type) {
2827         case OB_FONT:
2828         case OB_CURVE:
2829                 cu= ob->data;
2830                 
2831                 lb= &cu->disp;
2832                 
2833                 if(solid) {
2834                         dl= lb->first;
2835                         if(dl==NULL) return 1;
2836                         
2837                         if(dl->nors==0) addnormalsDispList(ob, lb);
2838                         index3_nors_incr= 0;
2839                         
2840                         if( displist_has_faces(lb)==0) {
2841                                 draw_index_wire= 0;
2842                                 drawDispListwire(lb);
2843                                 draw_index_wire= 1;
2844                         }
2845                         else {
2846                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2847                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2848                                         drawDispListsolid(lb, ob, 1);
2849                                 }
2850                                 else if(dt == OB_SHADED) {
2851                                         if(ob->disp.first==0) shadeDispList(scene, base);
2852                                         drawDispListshaded(lb, ob);
2853                                 }
2854                                 else {
2855                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2856                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2857                                         drawDispListsolid(lb, ob, 0);
2858                                 }
2859                                 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2860                                         cpack(0);
2861                                         draw_index_wire= 0;
2862                                         drawDispListwire(lb);
2863                                         draw_index_wire= 1;
2864                                 }
2865                         }
2866                         index3_nors_incr= 1;
2867                 }
2868                 else {
2869                         draw_index_wire= 0;
2870                         retval= drawDispListwire(lb);
2871                         draw_index_wire= 1;
2872                 }
2873                 break;
2874         case OB_SURF:
2875         
2876                 lb= &((Curve *)ob->data)->disp;
2877                 
2878                 if(solid) {
2879                         dl= lb->first;
2880                         if(dl==NULL) return 1;
2881                         
2882                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
2883                         
2884                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2885                                 GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2886                                 drawDispListsolid(lb, ob, 1);
2887                         }
2888                         else if(dt==OB_SHADED) {
2889                                 if(ob->disp.first==NULL) shadeDispList(scene, base);
2890                                 drawDispListshaded(lb, ob);
2891                         }
2892                         else {
2893                                 GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2894                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2895                         
2896                                 drawDispListsolid(lb, ob, 0);
2897                         }
2898                 }
2899                 else {
2900                         retval= drawDispListwire(lb);
2901                 }
2902                 break;
2903         case OB_MBALL:
2904                 
2905                 if( is_basis_mball(ob)) {
2906                         lb= &ob->disp;
2907                         if(lb->first==NULL) makeDispListMBall(scene, ob);
2908                         if(lb->first==NULL) return 1;
2909                         
2910                         if(solid) {
2911                                 
2912                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2913                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2914                                         drawDispListsolid(lb, ob, 1);
2915                                 }
2916                                 else if(dt == OB_SHADED) {
2917                                         dl= lb->first;
2918                                         if(dl && dl->col1==0) shadeDispList(scene, base);
2919                                         drawDispListshaded(lb, ob);
2920                                 }
2921                                 else {
2922                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2923                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2924                                 
2925                                         drawDispListsolid(lb, ob, 0);
2926                                 }
2927                         }
2928                         else{
2929                                 /* MetaBalls use DL_INDEX4 type of DispList */
2930                                 retval= drawDispListwire(lb);
2931                         }
2932                 }
2933                 break;
2934         }
2935         
2936         return retval;
2937 }
2938
2939 /* unified drawing of all new particle systems draw types except dupli ob & group       */
2940 /* mostly tries to use vertex arrays for speed                                                                          */
2941
2942 /* 1. check that everything is ok & updated */
2943 /* 2. start initialising things                         */
2944 /* 3. initialize according to draw type         */
2945 /* 4. allocate drawing data arrays                      */
2946 /* 5. start filling the arrays                          */
2947 /* 6. draw the arrays                                           */
2948 /* 7. clean up                                                          */
2949 static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int dt)
2950 {
2951         Object *ob=base->object;
2952         ParticleSystemModifierData *psmd;
2953         ParticleSettings *part;
2954         ParticleData *pars, *pa;
2955         ParticleKey state, *states=0;
2956         ParticleBillboardData bb;
2957         Material *ma;
2958         float vel[3], vec[3], vec2[3], imat[4][4], bb_center[3];
2959         float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
2960         float cfra= bsystem_time(scene, ob,(float)CFRA,0.0);
2961         float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
2962         float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
2963         int a, totpart, totpoint=0, draw_as, totchild=0;
2964         int select=ob->flag&SELECT, create_cdata=0;
2965         GLint polygonmode[2];
2966         char val[32];
2967
2968 /* 1. */
2969         if(psys==0)
2970                 return;
2971
2972         part=psys->part;
2973         pars=psys->particles;
2974
2975         if(part==0 || !psys_check_enabled(ob, psys))
2976                 return;
2977
2978         if(pars==0) return;
2979
2980         // XXX what logic is this?
2981         if(!scene->obedit && psys_in_edit_mode(scene, psys)
2982                 && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
2983                 return;
2984                 
2985         if(part->draw_as==PART_DRAW_NOT) return;
2986
2987 /* 2. */
2988         if(part->phystype==PART_PHYS_KEYED){
2989                 if(psys->flag & PSYS_FIRST_KEYED){
2990                         if(psys->flag&PSYS_KEYED){
2991                                 select=psys_count_keyed_targets(ob,psys);
2992                                 if(psys->totkeyed==0)
2993                                         return;
2994                         }
2995                 }
2996                 else
2997                         return;
2998         }
2999
3000         if(select){
3001                 select=0;
3002                 if(psys_get_current(ob)==psys)
3003                         select=1;
3004         }
3005
3006         psys->flag|=PSYS_DRAWING;
3007
3008         if(part->type==PART_HAIR && !psys->childcache)
3009                 totchild=0;
3010         else
3011                 totchild=psys->totchild*part->disp/100;
3012         
3013         ma= give_current_material(ob,part->omat);
3014
3015         if(ma) {
3016                 ma_r = ma->r;
3017                 ma_g = ma->g;
3018                 ma_b = ma->b;
3019         }
3020
3021         if(v3d->zbuf) glDepthMask(1);
3022
3023         if(select)
3024                 cpack(0xFFFFFF);
3025         else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
3026                 glColor3f(ma->r,ma->g,ma->b);
3027                 create_cdata = 1;
3028         }
3029         else
3030                 cpack(0);
3031
3032         psmd= psys_get_modifier(ob,psys);
3033
3034         timestep= psys_get_timestep(part);
3035
3036         wmLoadMatrix(rv3d->viewmat);
3037
3038         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
3039                 float mat[4][4];
3040                 Mat4MulMat4(mat, psys->imat, ob->obmat);
3041                 wmMultMatrix(mat);
3042         }
3043
3044         totpart=psys->totpart;
3045
3046         if(part->draw_as==PART_DRAW_REND)
3047                 draw_as = part->ren_as;
3048         else
3049                 draw_as = part->draw_as;
3050
3051         if(part->flag&PART_GLOB_TIME)
3052                 cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
3053
3054         if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL)
3055                 draw_as=PART_DRAW_DOT;
3056
3057 /* 3. */
3058         switch(draw_as){
3059                 case PART_DRAW_DOT:
3060                         if(part->draw_size)
3061                                 glPointSize(part->draw_size);
3062                         else
3063                                 glPointSize(2.0); /* default dot size */
3064                         break;
3065                 case PART_DRAW_CIRC:
3066                         /* calculate view aligned matrix: */
3067                         Mat4CpyMat4(imat, rv3d->viewinv);
3068                         Normalize(imat[0]);
3069                         Normalize(imat[1]);