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