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