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