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