2.5:
[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_editparticle.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];
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                         func(userData, bp, s[0], s[1]);
1108                 }
1109         }
1110 }
1111
1112 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1113 {
1114         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1115
1116         if(use_wcol) {
1117                 float col[3];
1118                 MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
1119                 
1120                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1121                 glColor3fv(col);
1122
1123         }
1124         
1125         if (dl) {
1126                 glVertex3fv(&dl->verts[index*3]);
1127         } else {
1128                 glVertex3fv(lt->def[index].vec);
1129         }
1130 }
1131
1132 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1133 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1134 {
1135         Lattice *lt= ob->data;
1136         DispList *dl;
1137         int u, v, w;
1138         int use_wcol= 0;
1139
1140         /* now we default make displist, this will modifiers work for non animated case */
1141         if(ob->disp.first==NULL)
1142                 lattice_calc_modifiers(scene, ob);
1143         dl= find_displist(&ob->disp, DL_VERTS);
1144         
1145         if(lt->editlatt) {
1146                 cpack(0x004000);
1147                 
1148                 if(ob->defbase.first && lt->dvert) {
1149                         use_wcol= ob->actdef;
1150                         glShadeModel(GL_SMOOTH);
1151                 }
1152         }
1153         
1154         if(lt->editlatt) lt= lt->editlatt;
1155         
1156         glBegin(GL_LINES);
1157         for(w=0; w<lt->pntsw; w++) {
1158                 int wxt = (w==0 || w==lt->pntsw-1);
1159                 for(v=0; v<lt->pntsv; v++) {
1160                         int vxt = (v==0 || v==lt->pntsv-1);
1161                         for(u=0; u<lt->pntsu; u++) {
1162                                 int uxt = (u==0 || u==lt->pntsu-1);
1163
1164                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1165                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1166                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1167                                 }
1168                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1169                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1170                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1171                                 }
1172                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1173                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1174                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1175                                 }
1176                         }
1177                 }
1178         }               
1179         glEnd();
1180         
1181         /* restoration for weight colors */
1182         if(use_wcol)
1183                 glShadeModel(GL_FLAT);
1184
1185         if( ((Lattice *)ob->data)->editlatt ) {
1186                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1187                 
1188                 lattice_draw_verts(lt, dl, 0);
1189                 lattice_draw_verts(lt, dl, 1);
1190                 
1191                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1192         }
1193 }
1194
1195 /* ***************** ******************** */
1196
1197 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1198 {
1199         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;
1200         EditVert *eve = EM_get_vert_for_index(index);
1201         short s[2];
1202
1203         if (eve->h==0) {
1204                 if (data->clipVerts) {
1205                         view3d_project_short_clip(data->vc.ar, co, s, data->pmat, data->vmat);
1206                 } else {
1207                         view3d_project_short_noclip(data->vc.ar, co, s, data->pmat);
1208                 }
1209
1210                 data->func(data->userData, eve, s[0], s[1], index);
1211         }
1212 }
1213
1214 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1215 {
1216         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;
1217         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1218         
1219         data.vc= *vc;
1220         data.func = func;
1221         data.userData = userData;
1222         data.clipVerts = clipVerts;
1223
1224         view3d_get_object_project_mat(vc->rv3d, vc->obedit, data.pmat, data.vmat);
1225
1226         EM_init_index_arrays(vc->em, 1, 0, 0);
1227         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1228         EM_free_index_arrays();
1229
1230         dm->release(dm);
1231 }
1232
1233 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1234 {
1235         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;
1236         EditEdge *eed = EM_get_edge_for_index(index);
1237         short s[2][2];
1238
1239         if (eed->h==0) {
1240                 if (data->clipVerts==1) {
1241                         view3d_project_short_clip(data->vc.ar, v0co, s[0], data->pmat, data->vmat);
1242                         view3d_project_short_clip(data->vc.ar, v1co, s[1], data->pmat, data->vmat);
1243                 } else {
1244                         view3d_project_short_noclip(data->vc.ar, v0co, s[0], data->pmat);
1245                         view3d_project_short_noclip(data->vc.ar, v1co, s[1], data->pmat);
1246
1247                         if (data->clipVerts==2) {
1248                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy)) 
1249                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1250                                                 return;
1251                         }
1252                 }
1253
1254                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1255         }
1256 }
1257
1258 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)
1259 {
1260         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;
1261         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1262
1263         data.vc= *vc;
1264         data.func = func;
1265         data.userData = userData;
1266         data.clipVerts = clipVerts;
1267
1268         view3d_get_object_project_mat(vc->rv3d, vc->obedit, data.pmat, data.vmat);
1269
1270         EM_init_index_arrays(vc->em, 0, 1, 0);
1271         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1272         EM_free_index_arrays();
1273
1274         dm->release(dm);
1275 }
1276
1277 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
1278 {
1279         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;
1280         EditFace *efa = EM_get_face_for_index(index);
1281         short s[2];
1282
1283         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1284                 view3d_project_short_clip(data->vc.ar, cent, s, data->pmat, data->vmat);
1285
1286                 data->func(data->userData, efa, s[0], s[1], index);
1287         }
1288 }
1289
1290 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1291 {
1292         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;
1293         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1294
1295         data.vc= *vc;
1296         data.func = func;
1297         data.userData = userData;
1298
1299         view3d_get_object_project_mat(vc->rv3d, vc->obedit, data.pmat, data.vmat);
1300
1301         EM_init_index_arrays(vc->em, 0, 0, 1);
1302         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1303         EM_free_index_arrays();
1304
1305         dm->release(dm);
1306 }
1307
1308 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1309 {
1310         Curve *cu= vc->obedit->data;
1311         float pmat[4][4], vmat[4][4];
1312         short s[2];
1313         Nurb *nu;
1314         int i;
1315
1316         view3d_get_object_project_mat(vc->rv3d, vc->obedit, pmat, vmat);
1317
1318         for (nu= cu->editnurb->first; nu; nu=nu->next) {
1319                 if((nu->type & 7)==CU_BEZIER) {
1320                         for (i=0; i<nu->pntsu; i++) {
1321                                 BezTriple *bezt = &nu->bezt[i];
1322
1323                                 if(bezt->hide==0) {
1324                                         if (G.f & G_HIDDENHANDLES) {
1325                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, pmat, vmat);
1326                                                 if (s[0] != IS_CLIPPED)
1327                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1328                                         } else {
1329                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, pmat, vmat);
1330                                                 if (s[0] != IS_CLIPPED)
1331                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1332                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, pmat, vmat);
1333                                                 if (s[0] != IS_CLIPPED)
1334                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1335                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, pmat, vmat);
1336                                                 if (s[0] != IS_CLIPPED)
1337                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1338                                         }
1339                                 }
1340                         }
1341                 }
1342                 else {
1343                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1344                                 BPoint *bp = &nu->bp[i];
1345
1346                                 if(bp->hide==0) {
1347                                         view3d_project_short_clip(vc->ar, bp->vec, s, pmat, vmat);
1348                                         func(userData, nu, bp, NULL, -1, s[0], s[1]);
1349                                 }
1350                         }
1351                 }
1352         }
1353 }
1354
1355 /* ************** DRAW MESH ****************** */
1356
1357 /* First section is all the "simple" draw routines, 
1358  * ones that just pass some sort of primitive to GL,
1359  * with perhaps various options to control lighting,
1360  * color, etc.
1361  *
1362  * These routines should not have user interface related
1363  * logic!!!
1364  */
1365
1366 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1367 {
1368         Scene *scene= (Scene *)userData;
1369         EditFace *efa = EM_get_face_for_index(index);
1370
1371         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1372                 glVertex3fv(cent);
1373                 glVertex3f(     cent[0] + no[0]*scene->editbutsize,
1374                                         cent[1] + no[1]*scene->editbutsize,
1375                                         cent[2] + no[2]*scene->editbutsize);
1376         }
1377 }
1378 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1379 {
1380         glBegin(GL_LINES);
1381         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1382         glEnd();
1383 }
1384
1385 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
1386 {
1387         EditFace *efa = EM_get_face_for_index(index);
1388         int sel = *((int*) userData);
1389
1390         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1391                 bglVertex3fv(cent);
1392         }
1393 }
1394 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1395 {
1396         bglBegin(GL_POINTS);
1397         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1398         bglEnd();
1399 }
1400
1401 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1402 {
1403         Scene *scene= (Scene *)userData;
1404         EditVert *eve = EM_get_vert_for_index(index);
1405
1406         if (eve->h==0) {
1407                 glVertex3fv(co);
1408
1409                 if (no_f) {
1410                         glVertex3f(     co[0] + no_f[0]*scene->editbutsize,
1411                                                 co[1] + no_f[1]*scene->editbutsize,
1412                                                 co[2] + no_f[2]*scene->editbutsize);
1413                 } else {
1414                         glVertex3f(     co[0] + no_s[0]*scene->editbutsize/32767.0f,
1415                                                 co[1] + no_s[1]*scene->editbutsize/32767.0f,
1416                                                 co[2] + no_s[2]*scene->editbutsize/32767.0f);
1417                 }
1418         }
1419 }
1420 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1421 {
1422         glBegin(GL_LINES);
1423         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1424         glEnd();
1425 }
1426
1427         /* Draw verts with color set based on selection */
1428 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1429 {
1430         struct { int sel; EditVert *eve_act; } * data = userData;
1431         EditVert *eve = EM_get_vert_for_index(index);
1432
1433         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1434                 /* draw active larger - need to stop/start point drawing for this :/ */
1435                 if (eve==data->eve_act) {
1436                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1437                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1438                         
1439                         bglEnd();
1440                         
1441                         glPointSize(size);
1442                         bglBegin(GL_POINTS);
1443                         bglVertex3fv(co);
1444                         bglEnd();
1445                         
1446                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1447                         glPointSize(size);
1448                         bglBegin(GL_POINTS);
1449                 } else {
1450                         bglVertex3fv(co);
1451                 }
1452         }
1453 }
1454 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1455 {
1456         struct { int sel; EditVert *eve_act; } data;
1457         data.sel = sel;
1458         data.eve_act = eve_act;
1459         
1460         bglBegin(GL_POINTS);
1461         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
1462         bglEnd();
1463 }
1464
1465         /* Draw edges with color set based on selection */
1466 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
1467 {
1468         EditEdge *eed = EM_get_edge_for_index(index);
1469         //unsigned char **cols = userData, *col;
1470         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
1471         unsigned char *col;
1472
1473         if (eed->h==0) {
1474                 if (eed==data->eed_act) {
1475                         glColor4ubv(data->actCol);
1476                 } else {
1477                         if (eed->f&SELECT) {
1478                                 col = data->selCol;
1479                         } else {
1480                                 col = data->baseCol;
1481                         }
1482                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
1483                         if (col[3]==0) return 0;
1484                         
1485                         glColor4ubv(col);
1486                 }
1487                 return 1;
1488         } else {
1489                 return 0;
1490         }
1491 }
1492 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
1493 {
1494         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
1495         
1496         data.baseCol = baseCol;
1497         data.selCol = selCol;
1498         data.actCol = actCol;
1499         data.eed_act = eed_act;
1500         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
1501 }
1502
1503         /* Draw edges */
1504 static int draw_dm_edges__setDrawOptions(void *userData, int index)
1505 {
1506         return EM_get_edge_for_index(index)->h==0;
1507 }
1508 static void draw_dm_edges(DerivedMesh *dm) 
1509 {
1510         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
1511 }
1512
1513         /* Draw edges with color interpolated based on selection */
1514 static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
1515 {
1516         return EM_get_edge_for_index(index)->h==0;
1517 }
1518 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
1519 {
1520         EditEdge *eed = EM_get_edge_for_index(index);
1521         unsigned char **cols = userData;
1522         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
1523         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
1524
1525         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
1526                                 col0[1] + (col1[1]-col0[1])*t,
1527                                 col0[2] + (col1[2]-col0[2])*t,
1528                                 col0[3] + (col1[3]-col0[3])*t);
1529 }
1530 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
1531 {
1532         unsigned char *cols[2];
1533         cols[0] = baseCol;
1534         cols[1] = selCol;
1535         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
1536 }
1537
1538         /* Draw only seam edges */
1539 static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
1540 {
1541         EditEdge *eed = EM_get_edge_for_index(index);
1542
1543         return (eed->h==0 && eed->seam);
1544 }
1545 static void draw_dm_edges_seams(DerivedMesh *dm)
1546 {
1547         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
1548 }
1549
1550         /* Draw only sharp edges */
1551 static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
1552 {
1553         EditEdge *eed = EM_get_edge_for_index(index);
1554
1555         return (eed->h==0 && eed->sharp);
1556 }
1557 static void draw_dm_edges_sharp(DerivedMesh *dm)
1558 {
1559         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
1560 }
1561
1562
1563         /* Draw faces with color set based on selection
1564          * return 2 for the active face so it renders with stipple enabled */
1565 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
1566 {
1567         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
1568         EditFace *efa = EM_get_face_for_index(index);
1569         unsigned char *col;
1570         
1571         if (efa->h==0) {
1572                 if (efa == data->efa_act) {
1573                         glColor4ubv(data->cols[2]);
1574                         return 2; /* stipple */
1575                 } else {
1576                         col = data->cols[(efa->f&SELECT)?1:0];
1577                         if (col[3]==0) return 0;
1578                         glColor4ubv(col);
1579                         return 1;
1580                 }
1581         }
1582         return 0;
1583 }
1584
1585 /* also draws the active face */
1586 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
1587 {
1588         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
1589         data.cols[0] = baseCol;
1590         data.cols[1] = selCol;
1591         data.cols[2] = actCol;
1592         data.efa_act = efa_act;
1593         
1594         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
1595 }
1596
1597 static int draw_dm_creases__setDrawOptions(void *userData, int index)
1598 {
1599         EditEdge *eed = EM_get_edge_for_index(index);
1600
1601         if (eed->h==0 && eed->crease!=0.0) {
1602                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
1603                 return 1;
1604         } else {
1605                 return 0;
1606         }
1607 }
1608 static void draw_dm_creases(DerivedMesh *dm)
1609 {
1610         glLineWidth(3.0);
1611         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
1612         glLineWidth(1.0);
1613 }
1614
1615 static int draw_dm_bweights__setDrawOptions(void *userData, int index)
1616 {
1617         EditEdge *eed = EM_get_edge_for_index(index);
1618
1619         if (eed->h==0 && eed->bweight!=0.0) {
1620                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
1621                 return 1;
1622         } else {
1623                 return 0;
1624         }
1625 }
1626 static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1627 {
1628         EditVert *eve = EM_get_vert_for_index(index);
1629
1630         if (eve->h==0 && eve->bweight!=0.0) {
1631                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
1632                 bglVertex3fv(co);
1633         }
1634 }
1635 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
1636 {
1637         if (scene->selectmode & SCE_SELECT_VERTEX) {
1638                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
1639                 bglBegin(GL_POINTS);
1640                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
1641                 bglEnd();
1642         }
1643         else {
1644                 glLineWidth(3.0);
1645                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
1646                 glLineWidth(1.0);
1647         }
1648 }
1649
1650 /* Second section of routines: Combine first sets to form fancy
1651  * drawing routines (for example rendering twice to get overlays).
1652  *
1653  * Also includes routines that are basic drawing but are too
1654  * specialized to be split out (like drawing creases or measurements).
1655  */
1656
1657 /* EditMesh drawing routines*/
1658
1659 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
1660 {
1661         int sel;
1662
1663         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
1664
1665         for (sel=0; sel<2; sel++) {
1666                 char col[4], fcol[4];
1667                 int pass;
1668
1669                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
1670                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
1671
1672                 for (pass=0; pass<2; pass++) {
1673                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1674                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
1675
1676                         if (pass==0) {
1677                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
1678                                         glDisable(GL_DEPTH_TEST);
1679                                                 
1680                                         glEnable(GL_BLEND);
1681                                 } else {
1682                                         continue;
1683                                 }
1684
1685                                 size = (size>2.1?size/2.0:size);
1686                                 fsize = (fsize>2.1?fsize/2.0:fsize);
1687                                 col[3] = fcol[3] = 100;
1688                         } else {
1689                                 col[3] = fcol[3] = 255;
1690                         }
1691                                 
1692                         if(scene->selectmode & SCE_SELECT_VERTEX) {
1693                                 glPointSize(size);
1694                                 glColor4ubv((GLubyte *)col);
1695                                 draw_dm_verts(cageDM, sel, eve_act);
1696                         }
1697                         
1698                         if( CHECK_OB_DRAWFACEDOT(scene, v3d, obedit->dt) ) {
1699                                 glPointSize(fsize);
1700                                 glColor4ubv((GLubyte *)fcol);
1701                                 draw_dm_face_centers(cageDM, sel);
1702                         }
1703                         
1704                         if (pass==0) {
1705                                 glDisable(GL_BLEND);
1706                                 glEnable(GL_DEPTH_TEST);
1707                         }
1708                 }
1709         }
1710
1711         if(v3d->zbuf) glDepthMask(1);
1712         glPointSize(1.0);
1713 }
1714
1715 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
1716 {
1717         int pass;
1718         unsigned char wireCol[4], selCol[4], actCol[4];
1719
1720         /* since this function does transparant... */
1721         UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
1722         UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
1723         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
1724         
1725         /* when sel only is used, dont render wire, only selected, this is used for
1726          * textured draw mode when the 'edges' option is disabled */
1727         if (sel_only)
1728                 wireCol[3] = 0;
1729
1730         for (pass=0; pass<2; pass++) {
1731                         /* show wires in transparant when no zbuf clipping for select */
1732                 if (pass==0) {
1733                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
1734                                 glEnable(GL_BLEND);
1735                                 glDisable(GL_DEPTH_TEST);
1736                                 selCol[3] = 85;
1737                                 if (!sel_only) wireCol[3] = 85;
1738                         } else {
1739                                 continue;
1740                         }
1741                 } else {
1742                         selCol[3] = 255;
1743                         if (!sel_only) wireCol[3] = 255;
1744                 }
1745
1746                 if(scene->selectmode == SCE_SELECT_FACE) {
1747                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1748                 }       
1749                 else if( (me->drawflag & ME_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {     
1750                         if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
1751                                 glShadeModel(GL_SMOOTH);
1752                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
1753                                 glShadeModel(GL_FLAT);
1754                         } else {
1755                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
1756                         }
1757                 }
1758                 else {
1759                         if (!sel_only) {
1760                                 glColor4ubv(wireCol);
1761                                 draw_dm_edges(cageDM);
1762                         }
1763                 }
1764
1765                 if (pass==0) {
1766                         glDisable(GL_BLEND);
1767                         glEnable(GL_DEPTH_TEST);
1768                 }
1769         }
1770 }       
1771
1772 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em)
1773 {
1774         Mesh *me= ob->data;
1775         EditEdge *eed;
1776         EditFace *efa;
1777         float v1[3], v2[3], v3[3], v4[3];
1778         float fvec[3];
1779         char val[32]; /* Stores the measurement display text here */
1780         char conv_float[5]; /* Use a float conversion matching the grid size */
1781         float area, col[3]; /* area of the face,  color of the text to draw */
1782         
1783         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1784                 return;
1785
1786         /* make the precission of the pronted value proportionate to the gridsize */
1787         if ((v3d->grid) < 0.01)
1788                 strcpy(conv_float, "%.6f");
1789         else if ((v3d->grid) < 0.1)
1790                 strcpy(conv_float, "%.5f");
1791         else if ((v3d->grid) < 1.0)
1792                 strcpy(conv_float, "%.4f");
1793         else if ((v3d->grid) < 10.0)
1794                 strcpy(conv_float, "%.3f");
1795         else
1796                 strcpy(conv_float, "%.2f");
1797         
1798         
1799         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1800                 glDisable(GL_DEPTH_TEST);
1801
1802         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0);
1803         
1804         if(me->drawflag & ME_DRAW_EDGELEN) {
1805                 UI_GetThemeColor3fv(TH_TEXT, col);
1806                 /* make color a bit more red */
1807                 if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
1808                 else col[0]= col[0]*0.7 + 0.3;
1809                 glColor3fv(col);
1810                 
1811                 for(eed= em->edges.first; eed; eed= eed->next) {
1812                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1813                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1814                                 VECCOPY(v1, eed->v1->co);
1815                                 VECCOPY(v2, eed->v2->co);
1816                                 
1817                                 glRasterPos3f( 0.5*(v1[0]+v2[0]),  0.5*(v1[1]+v2[1]),  0.5*(v1[2]+v2[2]));
1818                                 
1819                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1820                                         Mat4MulVecfl(ob->obmat, v1);
1821                                         Mat4MulVecfl(ob->obmat, v2);
1822                                 }
1823                                 
1824                                 sprintf(val, conv_float, VecLenf(v1, v2));
1825                                 BMF_DrawString( G.fonts, val);
1826                         }
1827                 }
1828         }
1829
1830         if(me->drawflag & ME_DRAW_FACEAREA) {
1831 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1832                 
1833                 UI_GetThemeColor3fv(TH_TEXT, col);
1834                 /* make color a bit more green */
1835                 if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
1836                 else col[1]= col[1]*0.7 + 0.3;
1837                 glColor3fv(col);
1838                 
1839                 for(efa= em->faces.first; efa; efa= efa->next) {
1840                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1841                                 VECCOPY(v1, efa->v1->co);
1842                                 VECCOPY(v2, efa->v2->co);
1843                                 VECCOPY(v3, efa->v3->co);
1844                                 if (efa->v4) {
1845                                         VECCOPY(v4, efa->v4->co);
1846                                 }
1847                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1848                                         Mat4MulVecfl(ob->obmat, v1);
1849                                         Mat4MulVecfl(ob->obmat, v2);
1850                                         Mat4MulVecfl(ob->obmat, v3);
1851                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1852                                 }
1853                                 
1854                                 if (efa->v4)
1855                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1856                                 else
1857                                         area = AreaT3Dfl(v1, v2, v3);
1858
1859                                 sprintf(val, conv_float, area);
1860                                 glRasterPos3fv(efa->cent);
1861                                 BMF_DrawString( G.fonts, val);
1862                         }
1863                 }
1864         }
1865
1866         if(me->drawflag & ME_DRAW_EDGEANG) {
1867                 EditEdge *e1, *e2, *e3, *e4;
1868                 
1869                 UI_GetThemeColor3fv(TH_TEXT, col);
1870                 /* make color a bit more blue */
1871                 if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
1872                 else col[2]= col[2]*0.7 + 0.3;
1873                 glColor3fv(col);
1874                 
1875                 for(efa= em->faces.first; efa; efa= efa->next) {
1876                         VECCOPY(v1, efa->v1->co);
1877                         VECCOPY(v2, efa->v2->co);
1878                         VECCOPY(v3, efa->v3->co);
1879                         if(efa->v4) {
1880                                 VECCOPY(v4, efa->v4->co); 
1881                         }
1882                         else {
1883                                 VECCOPY(v4, v3);
1884                         }
1885                         if(v3d->flag & V3D_GLOBAL_STATS) {
1886                                 Mat4MulVecfl(ob->obmat, v1);
1887                                 Mat4MulVecfl(ob->obmat, v2);
1888                                 Mat4MulVecfl(ob->obmat, v3);
1889                                 Mat4MulVecfl(ob->obmat, v4);
1890                         }
1891                         
1892                         e1= efa->e1;
1893                         e2= efa->e2;
1894                         e3= efa->e3;
1895                         if(efa->e4) e4= efa->e4; else e4= e3;
1896                         
1897                         /* Calculate the angles */
1898                                 
1899                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1900                                 /* Vec 1 */
1901                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1902                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
1903                                 glRasterPos3fv(fvec);
1904                                 BMF_DrawString( G.fonts, val);
1905                         }
1906                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1907                                 /* Vec 2 */
1908                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
1909                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
1910                                 glRasterPos3fv(fvec);
1911                                 BMF_DrawString( G.fonts, val);
1912                         }
1913                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
1914                                 /* Vec 3 */
1915                                 if(efa->v4) 
1916                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
1917                                 else
1918                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
1919                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
1920                                 glRasterPos3fv(fvec);
1921                                 BMF_DrawString( G.fonts, val);
1922                         }
1923                                 /* Vec 4 */
1924                         if(efa->v4) {
1925                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
1926                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
1927                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
1928                                         glRasterPos3fv(fvec);
1929                                         BMF_DrawString( G.fonts, val);
1930                                 }
1931                         }
1932                 }
1933         }    
1934         
1935         if(v3d->zbuf) {
1936                 glEnable(GL_DEPTH_TEST);
1937                 bglPolygonOffset(rv3d->dist, 0.0);
1938         }
1939 }
1940
1941 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
1942 {
1943         EditFace *efa = EM_get_face_for_index(index);
1944
1945         if (efa->h==0) {
1946                 GPU_enable_material(efa->mat_nr+1, NULL);
1947                 return 1;
1948         }
1949         else
1950                 return 0;
1951 }
1952
1953 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
1954 {
1955         EditFace *efa = EM_get_face_for_index(index);
1956
1957         return (efa->h==0);
1958 }
1959
1960 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
1961 {
1962         Mesh *me = ob->data;
1963         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
1964         EditEdge *eed_act = NULL;
1965         EditVert *eve_act = NULL;
1966         
1967         if (em->selected.last) {
1968                 EditSelection *ese = em->selected.last;
1969                 /* face is handeled above */
1970                 /*if (ese->type == EDITFACE ) {
1971                         efa_act = (EditFace *)ese->data;
1972                 } else */ if ( ese->type == EDITEDGE ) {
1973                         eed_act = (EditEdge *)ese->data;
1974                 } else if ( ese->type == EDITVERT ) {
1975                         eve_act = (EditVert *)ese->data;
1976                 }
1977         }
1978         
1979         EM_init_index_arrays(em, 1, 1, 1);
1980
1981         if(dt>OB_WIRE) {
1982                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
1983                         if(draw_glsl_material(scene, ob, v3d, dt)) {
1984                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
1985
1986                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
1987                                         draw_em_fancy__setGLSLFaceOpts, NULL);
1988                                 GPU_disable_material();
1989
1990                                 glFrontFace(GL_CCW);
1991                         }
1992                         else {
1993                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
1994                         }
1995                 }
1996                 else {
1997                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
1998
1999                         glEnable(GL_LIGHTING);
2000                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2001
2002                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2003
2004                         glFrontFace(GL_CCW);
2005                         glDisable(GL_LIGHTING);
2006                 }
2007                         
2008                 // Setup for drawing wire over, disable zbuffer
2009                 // write to show selected edge wires better
2010                 UI_ThemeColor(TH_WIRE);
2011
2012                 bglPolygonOffset(rv3d->dist, 1.0);
2013                 glDepthMask(0);
2014         } 
2015         else {
2016                 if (cageDM!=finalDM) {
2017                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2018                         finalDM->drawEdges(finalDM, 1);
2019                 }
2020         }
2021         
2022         if((me->drawflag & (ME_DRAWFACES)) || FACESEL_PAINT_TEST) {     /* transp faces */
2023                 unsigned char col1[4], col2[4], col3[4];
2024                         
2025                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2026                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2027                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2028                 
2029                 glEnable(GL_BLEND);
2030                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2031                 
2032                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2033                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2034                         col1[3] = 0;
2035                 
2036                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2037
2038                 glDisable(GL_BLEND);
2039                 glDepthMask(1);         // restore write in zbuffer
2040         } else if (efa_act) {
2041                 /* even if draw faces is off it would be nice to draw the stipple face
2042                  * Make all other faces zero alpha except for the active
2043                  * */
2044                 unsigned char col1[4], col2[4], col3[4];
2045                 col1[3] = col2[3] = 0; /* dont draw */
2046                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2047                 
2048                 glEnable(GL_BLEND);
2049                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2050                 
2051                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2052
2053                 glDisable(GL_BLEND);
2054                 glDepthMask(1);         // restore write in zbuffer
2055                 
2056         }
2057
2058         /* here starts all fancy draw-extra over */
2059         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2060                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2061                 
2062                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2063                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2064                 
2065         } else {
2066                 if(me->drawflag & ME_DRAWSEAMS) {
2067                         UI_ThemeColor(TH_EDGE_SEAM);
2068                         glLineWidth(2);
2069         
2070                         draw_dm_edges_seams(cageDM);
2071         
2072                         glColor3ub(0,0,0);
2073                         glLineWidth(1);
2074                 }
2075                 
2076                 if(me->drawflag & ME_DRAWSHARP) {
2077                         UI_ThemeColor(TH_EDGE_SHARP);
2078                         glLineWidth(2);
2079         
2080                         draw_dm_edges_sharp(cageDM);
2081         
2082                         glColor3ub(0,0,0);
2083                         glLineWidth(1);
2084                 }
2085         
2086                 if(me->drawflag & ME_DRAWCREASES) {
2087                         draw_dm_creases(cageDM);
2088                 }
2089                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2090                         draw_dm_bweights(scene, cageDM);
2091                 }
2092         
2093                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2094         }
2095         if(em) {
2096 // XXX          retopo_matrix_update(v3d);
2097
2098                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2099
2100                 if(me->drawflag & ME_DRAWNORMALS) {
2101                         UI_ThemeColor(TH_NORMAL);
2102                         draw_dm_face_normals(scene, cageDM);
2103                 }
2104                 if(me->drawflag & ME_DRAW_VNORMALS) {
2105                         UI_ThemeColor(TH_NORMAL);
2106                         draw_dm_vert_normals(scene, cageDM);
2107                 }
2108
2109                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2110                         draw_em_measure_stats(v3d, rv3d, ob, em);
2111         }
2112
2113         if(dt>OB_WIRE) {
2114                 glDepthMask(1);
2115                 bglPolygonOffset(rv3d->dist, 0.0);
2116                 GPU_disable_material();
2117         }
2118
2119         EM_free_index_arrays();
2120 }
2121
2122 /* Mesh drawing routines */
2123
2124 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2125 {
2126         
2127         if(v3d->transp==0) {    // not when we draw the transparent pass
2128                 glLineWidth(2.0);
2129                 glDepthMask(0);
2130                 
2131                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2132                    drawFacesSolid() doesn't draw the transparent faces */
2133                 if(ob->dtx & OB_DRAWTRANSP) {
2134                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2135                         dm->drawFacesSolid(dm, GPU_enable_material);
2136                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2137                         GPU_disable_material();
2138                 }
2139                 else {
2140                         dm->drawEdges(dm, 0);
2141                 }
2142                                         
2143                 glLineWidth(1.0);
2144                 glDepthMask(1);
2145         }
2146 }
2147
2148 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2149 {
2150         *drawSmooth_r = 1;
2151         return 1;
2152 }
2153
2154 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2155 {
2156         Object *ob= base->object;
2157         Mesh *me = ob->data;
2158         Material *ma= give_current_material(ob, 1);
2159         int hasHaloMat = (ma && (ma->mode&MA_HALO));
2160         int draw_wire = 0;
2161         int totvert, totedge, totface;
2162         DispList *dl;
2163         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2164
2165         if(!dm)
2166                 return;
2167         
2168         if (ob->dtx&OB_DRAWWIRE) {
2169                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2170         }
2171         
2172         totvert = dm->getNumVerts(dm);
2173         totedge = dm->getNumEdges(dm);
2174         totface = dm->getNumFaces(dm);
2175         
2176         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2177         if(dt!=OB_SHADED)
2178                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2179
2180                 // Unwanted combination.
2181         if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
2182
2183         if(dt==OB_BOUNDBOX) {
2184                 draw_bounding_volume(scene, ob);
2185         }
2186         else if(hasHaloMat || (totface==0 && totedge==0)) {
2187                 glPointSize(1.5);
2188                 dm->drawVerts(dm);
2189                 glPointSize(1.0);
2190         }
2191         else if(dt==OB_WIRE || totface==0) {
2192                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2193         }
2194         else if(        (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
2195                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2196         {
2197                 int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
2198
2199                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
2200                         draw_mesh_object_outline(v3d, ob, dm);
2201                 }
2202
2203                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2204                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2205
2206                         dm->drawFacesGLSL(dm, GPU_enable_material);
2207 //                      if(get_ob_property(ob, "Text"))
2208 // XXX                          draw_mesh_text(ob, 1);
2209                         GPU_disable_material();
2210
2211                         glFrontFace(GL_CCW);
2212                 }
2213                 else {
2214                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2215                 }
2216
2217                 if(!faceselect) {
2218                         if(base->flag & SELECT)
2219                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2220                         else
2221                                 UI_ThemeColor(TH_WIRE);
2222
2223                         dm->drawLooseEdges(dm);
2224                 }
2225         }
2226         else if(dt==OB_SOLID) {
2227                 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2228                         draw_mesh_object_outline(v3d, ob, dm);
2229
2230                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2231
2232                 glEnable(GL_LIGHTING);
2233                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2234
2235                 dm->drawFacesSolid(dm, GPU_enable_material);
2236                 GPU_disable_material();
2237
2238                 glFrontFace(GL_CCW);
2239                 glDisable(GL_LIGHTING);
2240
2241                 if(base->flag & SELECT) {
2242                         UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2243                 } else {
2244                         UI_ThemeColor(TH_WIRE);
2245                 }
2246                 dm->drawLooseEdges(dm);
2247         }
2248         else if(dt==OB_SHADED) {
2249                 int do_draw= 1; /* to resolve all G.f settings below... */
2250                 
2251                 if(ob==OBACT) {
2252                         do_draw= 0;
2253                         if( (G.f & G_WEIGHTPAINT)) {
2254                                 /* enforce default material settings */
2255                                 GPU_enable_material(0, NULL);
2256                                 
2257                                 /* but set default spec */
2258                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2259                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2260                                 glColor3ub(120, 120, 120);
2261                                 glDisable(GL_COLOR_MATERIAL);
2262                                 /* diffuse */
2263                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2264                                 glEnable(GL_LIGHTING);
2265                                 glEnable(GL_COLOR_MATERIAL);
2266
2267                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2268                                 glDisable(GL_COLOR_MATERIAL);
2269                                 glDisable(GL_LIGHTING);
2270
2271                                 GPU_disable_material();
2272                         }
2273                         else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
2274                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2275                         }
2276                         else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
2277                                 glColor3f(1.0f, 1.0f, 1.0f);
2278                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2279                         }
2280                         else do_draw= 1;
2281                 }
2282                 if(do_draw) {
2283                         dl = ob->disp.first;
2284                         if (!dl || !dl->col1) {
2285                                 /* release and reload derivedmesh because it might be freed in
2286                                    shadeDispList due to a different datamask */
2287                                 dm->release(dm);
2288                                 shadeDispList(scene, base);
2289                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2290                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2291                         }
2292
2293                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2294                                 draw_mesh_object_outline(v3d, ob, dm);
2295                         }
2296
2297                                 /* False for dupliframe objects */
2298                         if (dl) {
2299                                 unsigned int *obCol1 = dl->col1;
2300                                 unsigned int *obCol2 = dl->col2;
2301
2302                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2303                         }
2304
2305                         if(base->flag & SELECT) {
2306                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2307                         } else {
2308                                 UI_ThemeColor(TH_WIRE);
2309                         }
2310                         dm->drawLooseEdges(dm);
2311                 }
2312         }
2313         
2314         /* set default draw color back for wire or for draw-extra later on */
2315         if (dt!=OB_WIRE) {
2316                 if(base->flag & SELECT) {
2317                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2318                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2319                         else if(ob->flag & OB_FROMGROUP) 
2320                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2321                         else if(flag!=DRAW_CONSTCOLOR)
2322                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2323                         else
2324                                 glColor3ub(80,80,80);
2325                 } else {
2326                         if (ob->flag & OB_FROMGROUP) 
2327                                 UI_ThemeColor(TH_GROUP);
2328                         else {
2329                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2330                                         glColor3ub(80,80,80);
2331                                 else
2332                                         UI_ThemeColor(TH_WIRE);
2333                         }
2334                 }
2335         }
2336         if (draw_wire) {
2337                         /* If drawing wire and drawtype is not OB_WIRE then we are
2338                                 * overlaying the wires.
2339                                 *
2340                                 * UPDATE bug #10290 - With this wire-only objects can draw
2341                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2342                                 * 
2343                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2344                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2345                                 */
2346                 if (dt!=OB_WIRE && draw_wire==2) {
2347                         bglPolygonOffset(rv3d->dist, 1.0);
2348                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2349                 }
2350                 
2351                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2352                 
2353                 if (dt!=OB_WIRE && draw_wire==2) {
2354                         glDepthMask(1);
2355                         bglPolygonOffset(rv3d->dist, 0.0);
2356                 }
2357         }
2358
2359         dm->release(dm);
2360 }
2361
2362 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2363 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2364 {
2365         Object *ob= base->object;
2366         Object *obedit= scene->obedit;
2367         Mesh *me= ob->data;
2368         EditMesh *em= me->edit_mesh;
2369         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2370         
2371         if(obedit && ob!=obedit && ob->data==obedit->data) {
2372                 if(ob_get_key(ob));
2373                 else drawlinked= 1;
2374         }
2375         
2376         if(ob==obedit || drawlinked) {
2377                 DerivedMesh *finalDM, *cageDM;
2378                 
2379                 if (obedit!=ob)
2380                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2381                 else
2382                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2383                                                         v3d->customdata_mask);
2384
2385                 if(dt>OB_WIRE) {
2386                         // no transp in editmode, the fancy draw over goes bad then
2387                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2388                         GPU_set_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2389                 }
2390
2391                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2392
2393                 if (obedit!=ob && finalDM)
2394                         finalDM->release(finalDM);
2395         }
2396 //      else if(!em && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2397 //              OBACT==ob && !sculpt_modifiers_active(ob)) {
2398 // XXX          sculptmode_draw_mesh(0);
2399 //      }
2400         else {
2401                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2402                 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2403                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2404                         check_alpha = check_material_alpha(base, me, glsl);
2405
2406                         if(dt==OB_SOLID || glsl) {
2407                                 GPU_set_object_materials(v3d, rv3d, scene, ob, glsl,
2408                                         (check_alpha)? &do_alpha_pass: NULL);
2409                         }
2410
2411                         draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
2412                         
2413                         if(me->totvert==0) retval= 1;
2414                 }
2415         }
2416         
2417         /* GPU_set_object_materials checked if this is needed */
2418         if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2419         
2420         return retval;
2421 }
2422
2423 /* ************** DRAW DISPLIST ****************** */
2424
2425 static int draw_index_wire= 1;
2426 static int index3_nors_incr= 1;
2427
2428 /* returns 1 when nothing was drawn */
2429 static int drawDispListwire(ListBase *dlbase)
2430 {
2431         DispList *dl;
2432         int parts, nr;
2433         float *data;
2434
2435         if(dlbase==NULL) return 1;
2436         
2437         glDisableClientState(GL_NORMAL_ARRAY);
2438         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2439
2440         for(dl= dlbase->first; dl; dl= dl->next) {
2441                 if(dl->parts==0 || dl->nr==0)
2442                         continue;
2443                 
2444                 data= dl->verts;
2445         
2446                 switch(dl->type) {
2447                 case DL_SEGM:
2448                         
2449                         glVertexPointer(3, GL_FLOAT, 0, data);
2450                         
2451                         for(parts=0; parts<dl->parts; parts++)
2452                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2453                                 
2454                         break;
2455                 case DL_POLY:
2456                         
2457                         glVertexPointer(3, GL_FLOAT, 0, data);
2458                         
2459                         for(parts=0; parts<dl->parts; parts++)
2460                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2461                         
2462                         break;
2463                 case DL_SURF:
2464                         
2465                         glVertexPointer(3, GL_FLOAT, 0, data);
2466                         
2467                         for(parts=0; parts<dl->parts; parts++) {
2468                                 if(dl->flag & DL_CYCL_U) 
2469                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2470                                 else
2471                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2472                         }
2473                         
2474                         for(nr=0; nr<dl->nr; nr++) {
2475                                 int ofs= 3*dl->nr;
2476                                 
2477                                 data= (  dl->verts )+3*nr;
2478                                 parts= dl->parts;
2479
2480                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2481                                 else glBegin(GL_LINE_STRIP);
2482                                 
2483                                 while(parts--) {
2484                                         glVertex3fv(data);
2485                                         data+=ofs;
2486                                 }
2487                                 glEnd();
2488                                 
2489                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2490 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2491 //                              if(dl->flag & DL_CYCL_V) 
2492 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2493 //                              else
2494 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2495                         }
2496                         break;
2497                         
2498                 case DL_INDEX3:
2499                         if(draw_index_wire) {
2500                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2501                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2502                         }
2503                         break;
2504                         
2505                 case DL_INDEX4:
2506                         if(draw_index_wire) {
2507                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2508                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2509                         }
2510                         break;
2511                 }
2512         }
2513         
2514         glEnableClientState(GL_NORMAL_ARRAY);
2515         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2516         
2517         return 0;
2518 }
2519
2520 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2521 {
2522         DispList *dl;
2523         GPUVertexAttribs gattribs;
2524         float *data, curcol[4];
2525         float *ndata;
2526         
2527         if(lb==NULL) return;
2528         
2529         /* for drawing wire */
2530         glGetFloatv(GL_CURRENT_COLOR, curcol);
2531
2532         glEnable(GL_LIGHTING);
2533         
2534         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2535         else glFrontFace(GL_CCW);
2536         
2537         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2538                 glShadeModel(GL_SMOOTH);
2539         }
2540         
2541         dl= lb->first;
2542         while(dl) {
2543                 data= dl->verts;
2544                 ndata= dl->nors;
2545
2546                 switch(dl->type) {
2547                 case DL_SEGM:
2548                         if(ob->type==OB_SURF) {
2549                                 int nr;
2550
2551                                 glDisable(GL_LIGHTING);
2552                                 glColor3fv(curcol);
2553                                 
2554                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2555                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2556
2557                                 glBegin(GL_LINE_STRIP);
2558                                 for(nr= dl->nr; nr; nr--, data+=3)
2559                                         glVertex3fv(data);
2560                                 glEnd();
2561
2562                                 glEnable(GL_LIGHTING);
2563                         }
2564                         break;
2565                 case DL_POLY:
2566                         if(ob->type==OB_SURF) {
2567                                 int nr;
2568                                 
2569                                 UI_ThemeColor(TH_WIRE);
2570                                 glDisable(GL_LIGHTING);
2571                                 
2572                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2573                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2574                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2575                                 
2576                                 glBegin(GL_LINE_LOOP);
2577                                 for(nr= dl->nr; nr; nr--, data+=3)
2578                                         glVertex3fv(data);
2579                                 glEnd();
2580                                 
2581                                 glEnable(GL_LIGHTING);
2582                                 break;
2583                         }
2584                 case DL_SURF:
2585                         
2586                         if(dl->index) {
2587                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2588                                 
2589                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2590                                 else glShadeModel(GL_FLAT);
2591                                 
2592                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2593                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2594                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2595                                 GPU_disable_material();
2596                         }                       
2597                         break;
2598
2599                 case DL_INDEX3:
2600                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2601                         
2602                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2603                         
2604                         /* voor polys only one normal needed */
2605                         if(index3_nors_incr==0) {
2606                                 glDisableClientState(GL_NORMAL_ARRAY);
2607                                 glNormal3fv(ndata);
2608                         }
2609                         else
2610                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2611                         
2612                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2613                         GPU_disable_material();
2614                         
2615                         if(index3_nors_incr==0)
2616                                 glEnableClientState(GL_NORMAL_ARRAY);
2617
2618                         break;
2619
2620                 case DL_INDEX4:
2621                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2622                         
2623                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2624                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2625                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2626
2627                         GPU_disable_material();
2628                         
2629                         break;
2630                 }
2631                 dl= dl->next;
2632         }
2633
2634         glShadeModel(GL_FLAT);
2635         glDisable(GL_LIGHTING);
2636         glFrontFace(GL_CCW);
2637 }
2638
2639 static void drawDispListshaded(ListBase *lb, Object *ob)
2640 {
2641         DispList *dl, *dlob;
2642         unsigned int *cdata;
2643
2644         if(lb==NULL) return;
2645
2646         glShadeModel(GL_SMOOTH);
2647         glDisableClientState(GL_NORMAL_ARRAY);
2648         glEnableClientState(GL_COLOR_ARRAY);
2649         
2650         dl= lb->first;
2651         dlob= ob->disp.first;
2652         while(dl && dlob) {
2653                 
2654                 cdata= dlob->col1;
2655                 if(cdata==NULL) break;
2656                 
2657                 switch(dl->type) {
2658                 case DL_SURF:
2659                         if(dl->index) {
2660                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2661                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2662                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2663                         }                       
2664                         break;
2665
2666                 case DL_INDEX3:
2667                         
2668                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2669                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2670                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2671                         break;
2672
2673                 case DL_INDEX4:
2674                         
2675                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2676                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2677                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2678                         break;
2679                 }
2680                 
2681                 dl= dl->next;
2682                 dlob= dlob->next;
2683         }
2684         
2685         glShadeModel(GL_FLAT);
2686         glEnableClientState(GL_NORMAL_ARRAY);
2687         glDisableClientState(GL_COLOR_ARRAY);
2688 }
2689
2690 /* returns 1 when nothing was drawn */
2691 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
2692 {
2693         Object *ob= base->object;
2694         ListBase *lb=0;
2695         DispList *dl;
2696         Curve *cu;
2697         int solid, retval= 0;
2698         
2699         solid= (dt > OB_WIRE);
2700
2701         switch(ob->type) {
2702         case OB_FONT:
2703         case OB_CURVE:
2704                 cu= ob->data;
2705                 
2706                 lb= &cu->disp;
2707                 
2708                 if(solid) {
2709                         dl= lb->first;
2710                         if(dl==NULL) return 1;
2711                         
2712                         if(dl->nors==0) addnormalsDispList(ob, lb);
2713                         index3_nors_incr= 0;
2714                         
2715                         if( displist_has_faces(lb)==0) {
2716                                 draw_index_wire= 0;
2717                                 drawDispListwire(lb);
2718                                 draw_index_wire= 1;
2719                         }
2720                         else {
2721                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2722                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2723                                         drawDispListsolid(lb, ob, 1);
2724                                 }
2725                                 else if(dt == OB_SHADED) {
2726                                         if(ob->disp.first==0) shadeDispList(scene, base);
2727                                         drawDispListshaded(lb, ob);
2728                                 }
2729                                 else {
2730                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2731                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2732                                         drawDispListsolid(lb, ob, 0);
2733                                 }
2734                                 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2735                                         cpack(0);
2736                                         draw_index_wire= 0;
2737                                         drawDispListwire(lb);
2738                                         draw_index_wire= 1;
2739                                 }
2740                         }
2741                         index3_nors_incr= 1;
2742                 }
2743                 else {
2744                         draw_index_wire= 0;
2745                         retval= drawDispListwire(lb);
2746                         draw_index_wire= 1;
2747                 }
2748                 break;
2749         case OB_SURF:
2750         
2751                 lb= &((Curve *)ob->data)->disp;
2752                 
2753                 if(solid) {
2754                         dl= lb->first;
2755                         if(dl==NULL) return 1;
2756                         
2757                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
2758                         
2759                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2760                                 GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2761                                 drawDispListsolid(lb, ob, 1);
2762                         }
2763                         else if(dt==OB_SHADED) {
2764                                 if(ob->disp.first==NULL) shadeDispList(scene, base);
2765                                 drawDispListshaded(lb, ob);
2766                         }
2767                         else {
2768                                 GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2769                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2770                         
2771                                 drawDispListsolid(lb, ob, 0);
2772                         }
2773                 }
2774                 else {
2775                         retval= drawDispListwire(lb);
2776                 }
2777                 break;
2778         case OB_MBALL:
2779                 
2780                 if( is_basis_mball(ob)) {
2781                         lb= &ob->disp;
2782                         if(lb->first==NULL) makeDispListMBall(scene, ob);
2783                         if(lb->first==NULL) return 1;
2784                         
2785                         if(solid) {
2786                                 
2787                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2788                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2789                                         drawDispListsolid(lb, ob, 1);
2790                                 }
2791                                 else if(dt == OB_SHADED) {
2792                                         dl= lb->first;
2793                                         if(dl && dl->col1==0) shadeDispList(scene, base);
2794                                         drawDispListshaded(lb, ob);
2795                                 }
2796                                 else {
2797                                         GPU_set_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2798                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2799                                 
2800                                         drawDispListsolid(lb, ob, 0);
2801                                 }
2802                         }
2803                         else{
2804                                 /* MetaBalls use DL_INDEX4 type of DispList */
2805                                 retval= drawDispListwire(lb);
2806                         }
2807                 }
2808                 break;
2809         }
2810         
2811         return retval;
2812 }
2813
2814 /* unified drawing of all new particle systems draw types except dupli ob & group       */
2815 /* mostly tries to use vertex arrays for speed                                                                          */
2816
2817 /* 1. check that everything is ok & updated */
2818 /* 2. start initialising things                         */
2819 /* 3. initialize according to draw type         */
2820 /* 4. allocate drawing data arrays                      */
2821 /* 5. start filling the arrays                          */
2822 /* 6. draw the arrays                                           */
2823 /* 7. clean up                                                          */
2824 static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int dt)
2825 {
2826         Object *ob=base->object;
2827         ParticleSystemModifierData *psmd;
2828         ParticleSettings *part;
2829         ParticleData *pars, *pa;
2830         ParticleKey state, *states=0;
2831         ParticleCacheKey *cache=0;
2832         Material *ma;
2833         Object *bb_ob=0;
2834         float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
2835         float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
2836         float cfra= bsystem_time(scene, ob,(float)CFRA,0.0);
2837         float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
2838         float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
2839         int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
2840         int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
2841         int select=ob->flag&SELECT, create_cdata=0;
2842         GLint polygonmode[2];
2843         char val[32];
2844
2845 /* 1. */
2846         if(psys==0)
2847                 return;
2848
2849         part=psys->part;
2850         pars=psys->particles;
2851
2852         if(part==0 || !psys_check_enabled(ob, psys))
2853                 return;
2854
2855         if(pars==0) return;
2856
2857         // XXX what logic is this?
2858         if(!scene->obedit && psys_in_edit_mode(scene, psys)
2859                 && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
2860                 return;
2861                 
2862         if(part->draw_as==PART_DRAW_NOT) return;
2863
2864 /* 2. */
2865         if(part->phystype==PART_PHYS_KEYED){
2866                 if(psys->flag & PSYS_FIRST_KEYED){
2867                         if(psys->flag&PSYS_KEYED){
2868                                 select=psys_count_keyed_targets(ob,psys);
2869                                 if(psys->totkeyed==0)
2870                                         return;
2871                         }
2872                 }
2873                 else
2874                         return;
2875         }
2876
2877         if(select){
2878                 select=0;
2879                 if(psys_get_current(ob)==psys)
2880                         select=1;
2881         }
2882
2883         psys->flag|=PSYS_DRAWING;
2884
2885         if(part->type==PART_HAIR && !psys->childcache)
2886                 totchild=0;
2887         else
2888                 totchild=psys->totchild*part->disp/100;
2889         
2890         ma= give_current_material(ob,part->omat);
2891
2892         if(ma) {
2893                 ma_r = ma->r;
2894                 ma_g = ma->g;
2895                 ma_b = ma->b;
2896         }
2897
2898         if(v3d->zbuf) glDepthMask(1);
2899
2900         if(select)
2901                 cpack(0xFFFFFF);
2902         else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
2903                 glColor3f(ma->r,ma->g,ma->b);
2904                 create_cdata = 1;
2905         }
2906         else
2907                 cpack(0);
2908
2909         psmd= psys_get_modifier(ob,psys);
2910
2911         timestep= psys_get_timestep(part);
2912
2913         wmLoadMatrix(rv3d->viewmat);
2914
2915         if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
2916                 float mat[4][4];
2917                 Mat4MulMat4(mat, psys->imat, ob->obmat);
2918                 wmMultMatrix(mat);
2919         }
2920
2921         totpart=psys->totpart;
2922         draw_as=part->draw_as;
2923
2924         if(part->flag&PART_GLOB_TIME)
2925                 cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
2926
2927         if(psys->pathcache){
2928                 path_possible=1;
2929                 keys_possible=1;
2930         }
2931         if(draw_as==PART_DRAW_PATH && path_possible==0)
2932                 draw_as=PART_DRAW_DOT;
2933
2934         if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
2935                 path_nbr=part->keys_step;
2936                 draw_keys=1;
2937         }
2938
2939 /* 3. */
2940         switch(draw_as){
2941                 case PART_DRAW_DOT:
2942                         if(part->draw_size)
2943                                 glPointSize(part->draw_size);
2944                         else
2945                                 glPointSize(2.0); /* default dot size */
2946                         break;
2947                 case PART_DRAW_CIRC:
2948                         /* calculate view aligned matrix: */
2949                         Mat4CpyMat4(imat, rv3d->viewinv);
2950                         Normalize(imat[0]);
2951                         Normalize(imat[1]);
2952                         /* no break! */
2953                 case PART_DRAW_CROSS:
2954                 case PART_DRAW_AXIS:
2955                         /* lets calculate the scale: */
2956                         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];
2957                         pixsize*= rv3d->pixsize;
2958                         if(part->draw_size==0.0)
2959                                 pixsize*=2.0;
2960                         else
2961                                 pixsize*=part->draw_size;
2962                         break;
2963                 case PART_DRAW_OB:
2964                         if(part->dup_ob==0)
2965                                 draw_as=PART_DRAW_DOT;
2966                         else
2967                                 draw_as=0;
2968                         break;
2969                 case PART_DRAW_GR:
2970                         if(part->dup_group==0)
2971                                 draw_as=PART_DRAW_DOT;
2972                         else
2973                                 draw_as=0;
2974                         break;
2975                 case PART_DRAW_BB:
2976                         if(v3d->camera==0 && part->bb_ob==0){
2977                                 printf("Billboards need an active camera or a target object!\n");
2978
2979                                 draw_as=part->draw_as=PART_DRAW_DOT;
2980
2981                                 if(part->draw_size)
2982                                         glPointSize(part->draw_size);
2983                                 else
2984                                         glPointSize(2.0); /* default dot size */
2985                         }
2986                         else if(part->bb_ob)
2987                                 bb_ob=part->bb_ob;
2988                         else
2989                                 bb_ob=v3d->camera;
2990
2991                         if(part->bb_align<PART_BB_VIEW)
2992                                 onevec[part->bb_align]=1.0f;
2993                         break;
2994                 case PART_DRAW_PATH:
2995                         break;
2996         }
2997         if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
2998                 Mat4CpyMat4(imat, rv3d->viewinv);
2999                 Normalize(imat[0]);
3000                 Normalize(imat[1]);
3001         }
3002
3003 /* 4. */
3004         if(draw_as && draw_as!=PART_DRAW_PATH){
3005                 if(draw_as!=PART_DRAW_CIRC){
3006                         switch(draw_as){
3007                                 case PART_DRAW_AXIS:
3008                                 case PART_DRAW_CROSS:
3009                                         if(draw_as!=PART_DRAW_CROSS || create_cdata)
3010                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
3011                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
3012                                         break;
3013                                 case PART_DRAW_LINE:
3014                                         if(create_cdata)
3015                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
3016                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
3017                                         break;
3018                                 case PART_DRAW_BB:
3019                                         if(create_cdata)
3020                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
3021                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3022                                         ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
3023                                         break;
3024                                 default:
3025                                         if(create_cdata)
3026                                                 cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
3027                                         vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
3028                         }
3029                 }
3030
3031                 if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
3032                         vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
3033
3034                 vd=vdata;
3035                 ved=vedata;
3036                 cd=cdata;
3037                 nd=ndata;
3038
3039                 psys->lattice= psys_get_lattice(scene, ob, psys);
3040         }
3041
3042         if(draw_as){
3043 /* 5. */
3044                 for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
3045                         if(a<totpart){
3046                                 if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
3047                 &nbs