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