Smoke:
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, full recode and added functions
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <string.h>
29 #include <math.h>
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include "MEM_guardedalloc.h"
36
37 #include "IMB_imbuf.h"
38
39
40 #include "MTC_matrixops.h"
41
42 #include "DNA_armature_types.h"
43 #include "DNA_boid_types.h"
44 #include "DNA_camera_types.h"
45 #include "DNA_curve_types.h"
46 #include "DNA_constraint_types.h" // for drawing constraint
47 #include "DNA_effect_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_meta_types.h"
54 #include "DNA_modifier_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_object_force.h"
57 #include "DNA_object_fluidsim.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_screen_types.h"
62 #include "DNA_smoke_types.h"
63 #include "DNA_userdef_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
66
67 #include "BLI_blenlib.h"
68 #include "BLI_arithb.h"
69 #include "BLI_editVert.h"
70 #include "BLI_edgehash.h"
71 #include "BLI_rand.h"
72
73 #include "BKE_anim.h"                   //for the where_on_path function
74 #include "BKE_curve.h"
75 #include "BKE_constraint.h" // for the get_constraint_target function
76 #include "BKE_DerivedMesh.h"
77 #include "BKE_deform.h"
78 #include "BKE_displist.h"
79 #include "BKE_effect.h"
80 #include "BKE_font.h"
81 #include "BKE_global.h"
82 #include "BKE_image.h"
83 #include "BKE_key.h"
84 #include "BKE_lattice.h"
85 #include "BKE_mesh.h"
86 #include "BKE_material.h"
87 #include "BKE_mball.h"
88 #include "BKE_modifier.h"
89 #include "BKE_object.h"
90 #include "BKE_paint.h"
91 #include "BKE_particle.h"
92 #include "BKE_property.h"
93 #include "BKE_smoke.h"
94 #include "BKE_unit.h"
95 #include "BKE_utildefines.h"
96 #include "smoke_API.h"
97
98 #include "BIF_gl.h"
99 #include "BIF_glutil.h"
100
101 #include "GPU_draw.h"
102 #include "GPU_material.h"
103 #include "GPU_extensions.h"
104
105 #include "ED_mesh.h"
106 #include "ED_particle.h"
107 #include "ED_screen.h"
108 #include "ED_types.h"
109 #include "ED_util.h"
110
111 #include "UI_resources.h"
112 #include "UI_interface_icons.h"
113
114 #include "WM_api.h"
115 #include "BLF_api.h"
116
117 #include "view3d_intern.h"      // own include
118
119
120 /* this condition has been made more complex since editmode can draw textures */
121 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
122 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
123         (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
124
125 #define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
126 (       (sce->toolsettings->selectmode & SCE_SELECT_FACE) && \
127         (vd->drawtype<=OB_SOLID) && \
128         (((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
129         )
130
131 static void draw_bounding_volume(Scene *scene, Object *ob);
132
133 static void drawcube_size(float size);
134 static void drawcircle_size(float size);
135 static void draw_empty_sphere(float size);
136 static void draw_empty_cone(float size);
137
138
139 /* ************* only use while object drawing ************** */
140 static void view3d_project_short_clip(ARegion *ar, float *vec, short *adr)
141 {
142         RegionView3D *rv3d= ar->regiondata;
143         float fx, fy, vec4[4];
144         
145         adr[0]= IS_CLIPPED;
146         
147         /* clipplanes in eye space */
148         if(rv3d->rflag & RV3D_CLIPPING) {
149                 VECCOPY(vec4, vec);
150                 Mat4MulVecfl(rv3d->viewmatob, vec4);
151                 if(view3d_test_clipping(rv3d, vec4))
152                         return;
153         }
154         
155         VECCOPY(vec4, vec);
156         vec4[3]= 1.0;
157         
158         Mat4MulVec4fl(rv3d->persmatob, vec4);
159         
160         /* clipplanes in window space */
161         if( vec4[3]>BL_NEAR_CLIP ) {    /* is the NEAR clipping cutoff for picking */
162                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
163                 
164                 if( fx>0 && fx<ar->winx) {
165                         
166                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
167                         
168                         if(fy>0.0 && fy< (float)ar->winy) {
169                                 adr[0]= (short)floor(fx); 
170                                 adr[1]= (short)floor(fy);
171                         }
172                 }
173         }
174 }
175
176 /* only use while object drawing */
177 static void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr)
178 {
179         RegionView3D *rv3d= ar->regiondata;
180         float fx, fy, vec4[4];
181         
182         adr[0]= IS_CLIPPED;
183         
184         VECCOPY(vec4, vec);
185         vec4[3]= 1.0;
186         
187         Mat4MulVec4fl(rv3d->persmatob, vec4);
188         
189         if( vec4[3]>BL_NEAR_CLIP ) {    /* is the NEAR clipping cutoff for picking */
190                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
191                 
192                 if( fx>-32700 && fx<32700) {
193                         
194                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
195                         
196                         if(fy>-32700.0 && fy<32700.0) {
197                                 adr[0]= (short)floor(fx); 
198                                 adr[1]= (short)floor(fy);
199                         }
200                 }
201         }
202 }
203
204 /* ************************ */
205
206 /* check for glsl drawing */
207
208 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
209 {
210         if(!GPU_extensions_minimum_support())
211                 return 0;
212         if(G.f & G_PICKSEL)
213                 return 0;
214         if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
215                 return 0;
216         if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
217                 return 0;
218         
219         return (scene->gm.matmode == 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, UnitSettings *unit)
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         float grid= unit->system ? unit->scale_length : v3d->grid;
1864         int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
1865         if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
1866                 return;
1867
1868         /* make the precission of the pronted value proportionate to the gridsize */
1869
1870         if (grid < 0.01f)
1871                 strcpy(conv_float, "%.6f");
1872         else if (grid < 0.1f)
1873                 strcpy(conv_float, "%.5f");
1874         else if (grid < 1.0f)
1875                 strcpy(conv_float, "%.4f");
1876         else if (grid < 10.0f)
1877                 strcpy(conv_float, "%.3f");
1878         else
1879                 strcpy(conv_float, "%.2f");
1880         
1881         
1882         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
1883                 glDisable(GL_DEPTH_TEST);
1884
1885         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
1886         
1887         if(me->drawflag & ME_DRAW_EDGELEN) {
1888                 UI_GetThemeColor3fv(TH_TEXT, col);
1889                 /* make color a bit more red */
1890                 if(col[0]> 0.5f) {col[1]*=0.7f; col[2]*= 0.7f;}
1891                 else col[0]= col[0]*0.7f + 0.3f;
1892                 glColor3fv(col);
1893                 
1894                 for(eed= em->edges.first; eed; eed= eed->next) {
1895                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
1896                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
1897                                 VECCOPY(v1, eed->v1->co);
1898                                 VECCOPY(v2, eed->v2->co);
1899                                 
1900                                 x= 0.5f*(v1[0]+v2[0]);
1901                                 y= 0.5f*(v1[1]+v2[1]);
1902                                 z= 0.5f*(v1[2]+v2[2]);
1903                                 
1904                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1905                                         Mat4MulVecfl(ob->obmat, v1);
1906                                         Mat4MulVecfl(ob->obmat, v2);
1907                                 }
1908                                 if(unit->system)
1909                                         bUnit_AsString(val, sizeof(val), VecLenf(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
1910                                 else
1911                                         sprintf(val, conv_float, VecLenf(v1, v2));
1912                                 
1913                                 view3d_object_text_draw_add(x, y, z, val, 0);
1914                         }
1915                 }
1916         }
1917
1918         if(me->drawflag & ME_DRAW_FACEAREA) {
1919 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
1920                 
1921                 UI_GetThemeColor3fv(TH_TEXT, col);
1922                 /* make color a bit more green */
1923                 if(col[1]> 0.5f) {col[0]*=0.7f; col[2]*= 0.7f;}
1924                 else col[1]= col[1]*0.7f + 0.3f;
1925                 glColor3fv(col);
1926                 
1927                 for(efa= em->faces.first; efa; efa= efa->next) {
1928                         if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
1929                                 VECCOPY(v1, efa->v1->co);
1930                                 VECCOPY(v2, efa->v2->co);
1931                                 VECCOPY(v3, efa->v3->co);
1932                                 if (efa->v4) {
1933                                         VECCOPY(v4, efa->v4->co);
1934                                 }
1935                                 if(v3d->flag & V3D_GLOBAL_STATS) {
1936                                         Mat4MulVecfl(ob->obmat, v1);
1937                                         Mat4MulVecfl(ob->obmat, v2);
1938                                         Mat4MulVecfl(ob->obmat, v3);
1939                                         if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
1940                                 }
1941                                 
1942                                 if (efa->v4)
1943                                         area=  AreaQ3Dfl(v1, v2, v3, v4);
1944                                 else
1945                                         area = AreaT3Dfl(v1, v2, v3);
1946
1947                                 if(unit->system)
1948                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
1949                                 else
1950                                         sprintf(val, conv_float, area);
1951
1952                                 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
1953                         }
1954                 }
1955         }
1956
1957         if(me->drawflag & ME_DRAW_EDGEANG) {
1958                 EditEdge *e1, *e2, *e3, *e4;
1959                 
1960                 UI_GetThemeColor3fv(TH_TEXT, col);
1961                 /* make color a bit more blue */
1962                 if(col[2]> 0.5f) {col[0]*=0.7f; col[1]*= 0.7f;}
1963                 else col[2]= col[2]*0.7f + 0.3f;
1964                 glColor3fv(col);
1965                 
1966                 for(efa= em->faces.first; efa; efa= efa->next) {
1967                         VECCOPY(v1, efa->v1->co);
1968                         VECCOPY(v2, efa->v2->co);
1969                         VECCOPY(v3, efa->v3->co);
1970                         if(efa->v4) {
1971                                 VECCOPY(v4, efa->v4->co); 
1972                         }
1973                         else {
1974                                 VECCOPY(v4, v3);
1975                         }
1976                         if(v3d->flag & V3D_GLOBAL_STATS) {
1977                                 Mat4MulVecfl(ob->obmat, v1);
1978                                 Mat4MulVecfl(ob->obmat, v2);
1979                                 Mat4MulVecfl(ob->obmat, v3);
1980                                 Mat4MulVecfl(ob->obmat, v4);
1981                         }
1982                         
1983                         e1= efa->e1;
1984                         e2= efa->e2;
1985                         e3= efa->e3;
1986                         if(efa->e4) e4= efa->e4; else e4= e3;
1987                         
1988                         /* Calculate the angles */
1989                                 
1990                         if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
1991                                 /* Vec 1 */
1992                                 sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
1993                                 VecLerpf(fvec, efa->cent, efa->v1->co, 0.8f);
1994                                 view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0);
1995                         }
1996                         if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
1997                                 /* Vec 2 */
1998                                 sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
1999                                 VecLerpf(fvec, efa->cent, efa->v2->co, 0.8f);
2000                                 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2001                         }
2002                         if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
2003                                 /* Vec 3 */
2004                                 if(efa->v4) 
2005                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
2006                                 else
2007                                         sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
2008                                 VecLerpf(fvec, efa->cent, efa->v3->co, 0.8f);
2009                                 view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2010                         }
2011                                 /* Vec 4 */
2012                         if(efa->v4) {
2013                                 if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
2014                                         sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
2015                                         VecLerpf(fvec, efa->cent, efa->v4->co, 0.8f);
2016                                         view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0);
2017                                 }
2018                         }
2019                 }
2020         }    
2021         
2022         if(v3d->zbuf) {
2023                 glEnable(GL_DEPTH_TEST);
2024                 bglPolygonOffset(rv3d->dist, 0.0f);
2025         }
2026 }
2027
2028 static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
2029 {
2030         EditFace *efa = EM_get_face_for_index(index);
2031
2032         if (efa->h==0) {
2033                 GPU_enable_material(efa->mat_nr+1, NULL);
2034                 return 1;
2035         }
2036         else
2037                 return 0;
2038 }
2039
2040 static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
2041 {
2042         EditFace *efa = EM_get_face_for_index(index);
2043
2044         return (efa->h==0);
2045 }
2046
2047 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2048 {
2049         Mesh *me = ob->data;
2050         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2051         EditEdge *eed_act = NULL;
2052         EditVert *eve_act = NULL;
2053         
2054         if (em->selected.last) {
2055                 EditSelection *ese = em->selected.last;
2056                 /* face is handeled above */
2057                 /*if (ese->type == EDITFACE ) {
2058                         efa_act = (EditFace *)ese->data;
2059                 } else */ if ( ese->type == EDITEDGE ) {
2060                         eed_act = (EditEdge *)ese->data;
2061                 } else if ( ese->type == EDITVERT ) {
2062                         eve_act = (EditVert *)ese->data;
2063                 }
2064         }
2065         
2066         EM_init_index_arrays(em, 1, 1, 1);
2067
2068         if(dt>OB_WIRE) {
2069                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2070                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2071                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2072
2073                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2074                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2075                                 GPU_disable_material();
2076
2077                                 glFrontFace(GL_CCW);
2078                         }
2079                         else {
2080                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2081                         }
2082                 }
2083                 else {
2084                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2085
2086                         glEnable(GL_LIGHTING);
2087                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2088
2089                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
2090
2091                         glFrontFace(GL_CCW);
2092                         glDisable(GL_LIGHTING);
2093                 }
2094                         
2095                 // Setup for drawing wire over, disable zbuffer
2096                 // write to show selected edge wires better
2097                 UI_ThemeColor(TH_WIRE);
2098
2099                 bglPolygonOffset(rv3d->dist, 1.0);
2100                 glDepthMask(0);
2101         } 
2102         else {
2103                 if (cageDM!=finalDM) {
2104                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2105                         finalDM->drawEdges(finalDM, 1);
2106                 }
2107         }
2108         
2109         if((me->drawflag & (ME_DRAWFACES)) || paint_facesel_test(ob)) { /* transp faces */
2110                 unsigned char col1[4], col2[4], col3[4];
2111                         
2112                 UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
2113                 UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
2114                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2115                 
2116                 glEnable(GL_BLEND);
2117                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2118                 
2119                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2120                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2121                         col1[3] = 0;
2122                 
2123                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2124
2125                 glDisable(GL_BLEND);
2126                 glDepthMask(1);         // restore write in zbuffer
2127         } else if (efa_act) {
2128                 /* even if draw faces is off it would be nice to draw the stipple face
2129                  * Make all other faces zero alpha except for the active
2130                  * */
2131                 unsigned char col1[4], col2[4], col3[4];
2132                 col1[3] = col2[3] = 0; /* dont draw */
2133                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
2134                 
2135                 glEnable(GL_BLEND);
2136                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2137                 
2138                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2139
2140                 glDisable(GL_BLEND);
2141                 glDepthMask(1);         // restore write in zbuffer
2142                 
2143         }
2144
2145         /* here starts all fancy draw-extra over */
2146         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2147                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2148                 
2149                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2150                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2151                 
2152         } else {
2153                 if(me->drawflag & ME_DRAWSEAMS) {
2154                         UI_ThemeColor(TH_EDGE_SEAM);
2155                         glLineWidth(2);
2156         
2157                         draw_dm_edges_seams(cageDM);
2158         
2159                         glColor3ub(0,0,0);
2160                         glLineWidth(1);
2161                 }
2162                 
2163                 if(me->drawflag & ME_DRAWSHARP) {
2164                         UI_ThemeColor(TH_EDGE_SHARP);
2165                         glLineWidth(2);
2166         
2167                         draw_dm_edges_sharp(cageDM);
2168         
2169                         glColor3ub(0,0,0);
2170                         glLineWidth(1);
2171                 }
2172         
2173                 if(me->drawflag & ME_DRAWCREASES) {
2174                         draw_dm_creases(cageDM);
2175                 }
2176                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2177                         draw_dm_bweights(scene, cageDM);
2178                 }
2179         
2180                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2181         }
2182         if(em) {
2183 // XXX          retopo_matrix_update(v3d);
2184
2185                 draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
2186
2187                 if(me->drawflag & ME_DRAWNORMALS) {
2188                         UI_ThemeColor(TH_NORMAL);
2189                         draw_dm_face_normals(scene, cageDM);
2190                 }
2191                 if(me->drawflag & ME_DRAW_VNORMALS) {
2192                         UI_ThemeColor(TH_NORMAL);
2193                         draw_dm_vert_normals(scene, cageDM);
2194                 }
2195
2196                 if(me->drawflag & (ME_DRAW_EDGELEN|ME_DRAW_FACEAREA|ME_DRAW_EDGEANG))
2197                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2198         }
2199
2200         if(dt>OB_WIRE) {
2201                 glDepthMask(1);
2202                 bglPolygonOffset(rv3d->dist, 0.0);
2203                 GPU_disable_material();
2204         }
2205
2206         EM_free_index_arrays();
2207 }
2208
2209 /* Mesh drawing routines */
2210
2211 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2212 {
2213         
2214         if(v3d->transp==0) {    // not when we draw the transparent pass
2215                 glLineWidth(2.0);
2216                 glDepthMask(0);
2217                 
2218                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2219                    drawFacesSolid() doesn't draw the transparent faces */
2220                 if(ob->dtx & OB_DRAWTRANSP) {
2221                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2222                         dm->drawFacesSolid(dm, GPU_enable_material);
2223                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2224                         GPU_disable_material();
2225                 }
2226                 else {
2227                         dm->drawEdges(dm, 0);
2228                 }
2229                                         
2230                 glLineWidth(1.0);
2231                 glDepthMask(1);
2232         }
2233 }
2234
2235 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
2236 {
2237         *drawSmooth_r = 1;
2238         return 1;
2239 }
2240
2241 static void draw_mesh_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2242 {
2243         Object *ob= base->object;
2244         Mesh *me = ob->data;
2245         Material *ma= give_current_material(ob, 1);
2246         int hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2247         int draw_wire = 0;
2248         int totvert, totedge, totface;
2249         DispList *dl;
2250         DerivedMesh *dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2251
2252         if(!dm)
2253                 return;
2254         
2255         if (ob->dtx&OB_DRAWWIRE) {
2256                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2257         }
2258         
2259         totvert = dm->getNumVerts(dm);
2260         totedge = dm->getNumEdges(dm);
2261         totface = dm->getNumFaces(dm);
2262         
2263         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2264         if(dt!=OB_SHADED)
2265                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2266
2267                 // Unwanted combination.
2268         if (ob==OBACT && paint_facesel_test(ob)) draw_wire = 0;
2269
2270         if(dt==OB_BOUNDBOX) {
2271                 draw_bounding_volume(scene, ob);
2272         }
2273         else if(hasHaloMat || (totface==0 && totedge==0)) {
2274                 glPointSize(1.5);
2275                 dm->drawVerts(dm);
2276                 glPointSize(1.0);
2277         }
2278         else if(dt==OB_WIRE || totface==0) {
2279                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2280         }
2281         else if(        (ob==OBACT && (ob->mode & OB_MODE_TEXTURE_PAINT || paint_facesel_test(ob))) ||
2282                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2283         {
2284                 int faceselect= (ob==OBACT && paint_facesel_test(ob));
2285
2286                 if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || paint_facesel_test(ob)) && !draw_wire) {
2287                         draw_mesh_object_outline(v3d, ob, dm);
2288                 }
2289
2290                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2291                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2292
2293                         dm->drawFacesGLSL(dm, GPU_enable_material);
2294 //                      if(get_ob_property(ob, "Text"))
2295 // XXX                          draw_mesh_text(ob, 1);
2296                         GPU_disable_material();
2297
2298                         glFrontFace(GL_CCW);
2299                 }
2300                 else {
2301                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, faceselect);
2302                 }
2303
2304                 if(!faceselect) {
2305                         if(base->flag & SELECT)
2306                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2307                         else
2308                                 UI_ThemeColor(TH_WIRE);
2309
2310                         dm->drawLooseEdges(dm);
2311                 }
2312         }
2313         else if(dt==OB_SOLID) {
2314                 if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
2315                         draw_mesh_object_outline(v3d, ob, dm);
2316
2317                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2318
2319                 glEnable(GL_LIGHTING);
2320                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2321
2322                 dm->drawFacesSolid(dm, GPU_enable_material);
2323                 GPU_disable_material();
2324
2325                 glFrontFace(GL_CCW);
2326                 glDisable(GL_LIGHTING);
2327
2328                 if(base->flag & SELECT) {
2329                         UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2330                 } else {
2331                         UI_ThemeColor(TH_WIRE);
2332                 }
2333                 dm->drawLooseEdges(dm);
2334         }
2335         else if(dt==OB_SHADED) {
2336                 int do_draw= 1; /* to resolve all G.f settings below... */
2337                 
2338                 if(ob==OBACT) {
2339                         do_draw= 0;
2340                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2341                                 /* enforce default material settings */
2342                                 GPU_enable_material(0, NULL);
2343                                 
2344                                 /* but set default spec */
2345                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2346                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2347                                 glColor3ub(120, 120, 120);
2348                                 glDisable(GL_COLOR_MATERIAL);
2349                                 /* diffuse */
2350                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2351                                 glEnable(GL_LIGHTING);
2352                                 glEnable(GL_COLOR_MATERIAL);
2353
2354                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
2355                                 glDisable(GL_COLOR_MATERIAL);
2356                                 glDisable(GL_LIGHTING);
2357
2358                                 GPU_disable_material();
2359                         }
2360                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2361                                 if(me->mcol)
2362                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
2363                                 else {
2364                                         glColor3f(1.0f, 1.0f, 1.0f);
2365                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
2366                                 }
2367                         }
2368                         else do_draw= 1;
2369                 }
2370                 if(do_draw) {
2371                         dl = ob->disp.first;
2372                         if (!dl || !dl->col1) {
2373                                 /* release and reload derivedmesh because it might be freed in
2374                                    shadeDispList due to a different datamask */
2375                                 dm->release(dm);
2376                                 shadeDispList(scene, base);
2377                                 dl = find_displist(&ob->disp, DL_VERTCOL);
2378                                 dm= mesh_get_derived_final(scene, ob, v3d->customdata_mask);
2379                         }
2380
2381                         if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
2382                                 draw_mesh_object_outline(v3d, ob, dm);
2383                         }
2384
2385                                 /* False for dupliframe objects */
2386                         if (dl) {
2387                                 unsigned int *obCol1 = dl->col1;
2388                                 unsigned int *obCol2 = dl->col2;
2389
2390                                 dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
2391                         }
2392
2393                         if(base->flag & SELECT) {
2394                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2395                         } else {
2396                                 UI_ThemeColor(TH_WIRE);
2397                         }
2398                         dm->drawLooseEdges(dm);
2399                 }
2400         }
2401         
2402         /* set default draw color back for wire or for draw-extra later on */
2403         if (dt!=OB_WIRE) {
2404                 if(base->flag & SELECT) {
2405                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2406                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2407                         else if(ob->flag & OB_FROMGROUP) 
2408                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2409                         else if(flag!=DRAW_CONSTCOLOR)
2410                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2411                         else
2412                                 glColor3ub(80,80,80);
2413                 } else {
2414                         if (ob->flag & OB_FROMGROUP) 
2415                                 UI_ThemeColor(TH_GROUP);
2416                         else {
2417                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2418                                         glColor3ub(80,80,80);
2419                                 else
2420                                         UI_ThemeColor(TH_WIRE);
2421                         }
2422                 }
2423         }
2424         if (draw_wire) {
2425                         /* If drawing wire and drawtype is not OB_WIRE then we are
2426                                 * overlaying the wires.
2427                                 *
2428                                 * UPDATE bug #10290 - With this wire-only objects can draw
2429                                 * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2430                                 * 
2431                                 * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2432                                 * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2433                                 */
2434                 if (dt!=OB_WIRE && draw_wire==2) {
2435                         bglPolygonOffset(rv3d->dist, 1.0);
2436                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2437                 }
2438                 
2439                 dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
2440                 
2441                 if (dt!=OB_WIRE && draw_wire==2) {
2442                         glDepthMask(1);
2443                         bglPolygonOffset(rv3d->dist, 0.0);
2444                 }
2445         }
2446
2447         dm->release(dm);
2448 }
2449
2450 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2451 static int draw_mesh_object(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2452 {
2453         Object *ob= base->object;
2454         Object *obedit= scene->obedit;
2455         Mesh *me= ob->data;
2456         EditMesh *em= me->edit_mesh;
2457         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
2458         
2459         if(obedit && ob!=obedit && ob->data==obedit->data) {
2460                 if(ob_get_key(ob));
2461                 else drawlinked= 1;
2462         }
2463         
2464         if(ob==obedit || drawlinked) {
2465                 DerivedMesh *finalDM, *cageDM;
2466                 
2467                 if (obedit!=ob)
2468                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2469                 else
2470                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2471                                                         v3d->customdata_mask);
2472
2473                 if(dt>OB_WIRE) {
2474                         // no transp in editmode, the fancy draw over goes bad then
2475                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2476                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
2477                 }
2478
2479                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
2480
2481                 GPU_end_object_materials();
2482
2483                 if (obedit!=ob && finalDM)
2484                         finalDM->release(finalDM);
2485         }
2486 //      else if(!em && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
2487 //              OBACT==ob && !sculpt_modifiers_active(ob)) {
2488 // XXX          sculptmode_draw_mesh(0);
2489 //      }
2490         else {
2491                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
2492                 if(me->totface<=4 || boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
2493                         glsl = draw_glsl_material(scene, ob, v3d, dt);
2494                         check_alpha = check_material_alpha(base, me, glsl);
2495
2496                         if(dt==OB_SOLID || glsl) {
2497                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
2498                                         (check_alpha)? &do_alpha_pass: NULL);
2499                         }
2500
2501                         draw_mesh_fancy(scene, v3d, rv3d, base, dt, flag);
2502
2503                         GPU_end_object_materials();
2504                         
2505                         if(me->totvert==0) retval= 1;
2506                 }
2507         }
2508         
2509         /* GPU_begin_object_materials checked if this is needed */
2510         if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
2511         
2512         return retval;
2513 }
2514
2515 /* ************** DRAW DISPLIST ****************** */
2516
2517 static int draw_index_wire= 1;
2518 static int index3_nors_incr= 1;
2519
2520 /* returns 1 when nothing was drawn */
2521 static int drawDispListwire(ListBase *dlbase)
2522 {
2523         DispList *dl;
2524         int parts, nr;
2525         float *data;
2526
2527         if(dlbase==NULL) return 1;
2528         
2529         glDisableClientState(GL_NORMAL_ARRAY);
2530         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2531
2532         for(dl= dlbase->first; dl; dl= dl->next) {
2533                 if(dl->parts==0 || dl->nr==0)
2534                         continue;
2535                 
2536                 data= dl->verts;
2537         
2538                 switch(dl->type) {
2539                 case DL_SEGM:
2540                         
2541                         glVertexPointer(3, GL_FLOAT, 0, data);
2542                         
2543                         for(parts=0; parts<dl->parts; parts++)
2544                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2545                                 
2546                         break;
2547                 case DL_POLY:
2548                         
2549                         glVertexPointer(3, GL_FLOAT, 0, data);
2550                         
2551                         for(parts=0; parts<dl->parts; parts++)
2552                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2553                         
2554                         break;
2555                 case DL_SURF:
2556                         
2557                         glVertexPointer(3, GL_FLOAT, 0, data);
2558                         
2559                         for(parts=0; parts<dl->parts; parts++) {
2560                                 if(dl->flag & DL_CYCL_U) 
2561                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
2562                                 else
2563                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
2564                         }
2565                         
2566                         for(nr=0; nr<dl->nr; nr++) {
2567                                 int ofs= 3*dl->nr;
2568                                 
2569                                 data= (  dl->verts )+3*nr;
2570                                 parts= dl->parts;
2571
2572                                 if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
2573                                 else glBegin(GL_LINE_STRIP);
2574                                 
2575                                 while(parts--) {
2576                                         glVertex3fv(data);
2577                                         data+=ofs;
2578                                 }
2579                                 glEnd();
2580                                 
2581                                 /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
2582 //                              glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
2583 //                              if(dl->flag & DL_CYCL_V) 
2584 //                                      glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
2585 //                              else
2586 //                                      glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
2587                         }
2588                         break;
2589                         
2590                 case DL_INDEX3:
2591                         if(draw_index_wire) {
2592                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2593                                 glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2594                         }
2595                         break;
2596                         
2597                 case DL_INDEX4:
2598                         if(draw_index_wire) {
2599                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2600                                 glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2601                         }
2602                         break;
2603                 }
2604         }
2605         
2606         glEnableClientState(GL_NORMAL_ARRAY);
2607         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
2608         
2609         return 0;
2610 }
2611
2612 static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
2613 {
2614         DispList *dl;
2615         GPUVertexAttribs gattribs;
2616         float *data, curcol[4];
2617         float *ndata;
2618         
2619         if(lb==NULL) return;
2620         
2621         /* for drawing wire */
2622         glGetFloatv(GL_CURRENT_COLOR, curcol);
2623
2624         glEnable(GL_LIGHTING);
2625         
2626         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
2627         else glFrontFace(GL_CCW);
2628         
2629         if(ob->type==OB_MBALL) {        // mball always smooth shaded
2630                 glShadeModel(GL_SMOOTH);
2631         }
2632         
2633         dl= lb->first;
2634         while(dl) {
2635                 data= dl->verts;
2636                 ndata= dl->nors;
2637
2638                 switch(dl->type) {
2639                 case DL_SEGM:
2640                         if(ob->type==OB_SURF) {
2641                                 int nr;
2642
2643                                 glDisable(GL_LIGHTING);
2644                                 glColor3fv(curcol);
2645                                 
2646                                 // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2647                                 // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
2648
2649                                 glBegin(GL_LINE_STRIP);
2650                                 for(nr= dl->nr; nr; nr--, data+=3)
2651                                         glVertex3fv(data);
2652                                 glEnd();
2653
2654                                 glEnable(GL_LIGHTING);
2655                         }
2656                         break;
2657                 case DL_POLY:
2658                         if(ob->type==OB_SURF) {
2659                                 int nr;
2660                                 
2661                                 UI_ThemeColor(TH_WIRE);
2662                                 glDisable(GL_LIGHTING);
2663                                 
2664                                 /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
2665                                 //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2666                                 //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
2667                                 
2668                                 glBegin(GL_LINE_LOOP);
2669                                 for(nr= dl->nr; nr; nr--, data+=3)
2670                                         glVertex3fv(data);
2671                                 glEnd();
2672                                 
2673                                 glEnable(GL_LIGHTING);
2674                                 break;
2675                         }
2676                 case DL_SURF:
2677                         
2678                         if(dl->index) {
2679                                 GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2680                                 
2681                                 if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
2682                                 else glShadeModel(GL_FLAT);
2683                                 
2684                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2685                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2686                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2687                         }                       
2688                         break;
2689
2690                 case DL_INDEX3:
2691                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2692                         
2693                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2694                         
2695                         /* voor polys only one normal needed */
2696                         if(index3_nors_incr==0) {
2697                                 glDisableClientState(GL_NORMAL_ARRAY);
2698                                 glNormal3fv(ndata);
2699                         }
2700                         else
2701                                 glNormalPointer(GL_FLOAT, 0, dl->nors);
2702                         
2703                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2704                         
2705                         if(index3_nors_incr==0)
2706                                 glEnableClientState(GL_NORMAL_ARRAY);
2707
2708                         break;
2709
2710                 case DL_INDEX4:
2711                         GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
2712                         
2713                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2714                         glNormalPointer(GL_FLOAT, 0, dl->nors);
2715                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2716
2717                         break;
2718                 }
2719                 dl= dl->next;
2720         }
2721
2722         glShadeModel(GL_FLAT);
2723         glDisable(GL_LIGHTING);
2724         glFrontFace(GL_CCW);
2725 }
2726
2727 static void drawDispListshaded(ListBase *lb, Object *ob)
2728 {
2729         DispList *dl, *dlob;
2730         unsigned int *cdata;
2731
2732         if(lb==NULL) return;
2733
2734         glShadeModel(GL_SMOOTH);
2735         glDisableClientState(GL_NORMAL_ARRAY);
2736         glEnableClientState(GL_COLOR_ARRAY);
2737         
2738         dl= lb->first;
2739         dlob= ob->disp.first;
2740         while(dl && dlob) {
2741                 
2742                 cdata= dlob->col1;
2743                 if(cdata==NULL) break;
2744                 
2745                 switch(dl->type) {
2746                 case DL_SURF:
2747                         if(dl->index) {
2748                                 glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2749                                 glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2750                                 glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
2751                         }                       
2752                         break;
2753
2754                 case DL_INDEX3:
2755                         
2756                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2757                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2758                         glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
2759                         break;
2760
2761                 case DL_INDEX4:
2762                         
2763                         glVertexPointer(3, GL_FLOAT, 0, dl->verts);
2764                         glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
2765                         glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
2766                         break;
2767                 }
2768                 
2769                 dl= dl->next;
2770                 dlob= dlob->next;
2771         }
2772         
2773         glShadeModel(GL_FLAT);
2774         glEnableClientState(GL_NORMAL_ARRAY);
2775         glDisableClientState(GL_COLOR_ARRAY);
2776 }
2777
2778 /* returns 1 when nothing was drawn */
2779 static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt)
2780 {
2781         Object *ob= base->object;
2782         ListBase *lb=0;
2783         DispList *dl;
2784         Curve *cu;
2785         int solid, retval= 0;
2786         
2787         solid= (dt > OB_WIRE);
2788
2789         switch(ob->type) {
2790         case OB_FONT:
2791         case OB_CURVE:
2792                 cu= ob->data;
2793                 
2794                 lb= &cu->disp;
2795                 
2796                 if(solid) {
2797                         dl= lb->first;
2798                         if(dl==NULL) return 1;
2799                         
2800                         if(dl->nors==0) addnormalsDispList(ob, lb);
2801                         index3_nors_incr= 0;
2802                         
2803                         if( displist_has_faces(lb)==0) {
2804                                 draw_index_wire= 0;
2805                                 drawDispListwire(lb);
2806                                 draw_index_wire= 1;
2807                         }
2808                         else {
2809                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2810                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2811                                         drawDispListsolid(lb, ob, 1);
2812                                         GPU_end_object_materials();
2813                                 }
2814                                 else if(dt == OB_SHADED) {
2815                                         if(ob->disp.first==0) shadeDispList(scene, base);
2816                                         drawDispListshaded(lb, ob);
2817                                 }
2818                                 else {
2819                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2820                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2821                                         drawDispListsolid(lb, ob, 0);
2822                                         GPU_end_object_materials();
2823                                 }
2824                                 if(cu->editnurb && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
2825                                         cpack(0);
2826                                         draw_index_wire= 0;
2827                                         drawDispListwire(lb);
2828                                         draw_index_wire= 1;
2829                                 }
2830                         }
2831                         index3_nors_incr= 1;
2832                 }
2833                 else {
2834                         draw_index_wire= 0;
2835                         retval= drawDispListwire(lb);
2836                         draw_index_wire= 1;
2837                 }
2838                 break;
2839         case OB_SURF:
2840         
2841                 lb= &((Curve *)ob->data)->disp;
2842                 
2843                 if(solid) {
2844                         dl= lb->first;
2845                         if(dl==NULL) return 1;
2846                         
2847                         if(dl->nors==NULL) addnormalsDispList(ob, lb);
2848                         
2849                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2850                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2851                                 drawDispListsolid(lb, ob, 1);
2852                                 GPU_end_object_materials();
2853                         }
2854                         else if(dt==OB_SHADED) {
2855                                 if(ob->disp.first==NULL) shadeDispList(scene, base);
2856                                 drawDispListshaded(lb, ob);
2857                         }
2858                         else {
2859                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2860                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2861                                 drawDispListsolid(lb, ob, 0);
2862                                 GPU_end_object_materials();
2863                         }
2864                 }
2865                 else {
2866                         retval= drawDispListwire(lb);
2867                 }
2868                 break;
2869         case OB_MBALL:
2870                 
2871                 if( is_basis_mball(ob)) {
2872                         lb= &ob->disp;
2873                         if(lb->first==NULL) makeDispListMBall(scene, ob);
2874                         if(lb->first==NULL) return 1;
2875                         
2876                         if(solid) {
2877                                 
2878                                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2879                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
2880                                         drawDispListsolid(lb, ob, 1);
2881                                         GPU_end_object_materials();
2882                                 }
2883                                 else if(dt == OB_SHADED) {
2884                                         dl= lb->first;
2885                                         if(dl && dl->col1==0) shadeDispList(scene, base);
2886                                         drawDispListshaded(lb, ob);
2887                                 }
2888                                 else {
2889                                         GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
2890                                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
2891                                         drawDispListsolid(lb, ob, 0);
2892                                         GPU_end_object_materials();
2893                                 }
2894                         }
2895                         else{
2896                                 /* MetaBalls use DL_INDEX4 type of DispList */
2897                                 retval= drawDispListwire(lb);
2898                         }
2899                 }
2900                 break;
2901         }
2902         
2903         return retval;
2904 }
2905
2906 /* *********** text drawing for particles ************* */
2907 static ListBase pstrings= {NULL, NULL};
2908
2909 typedef struct ViewParticleString {
2910         struct ViewParticleString *next, *prev;
2911         float vec[3], col[4];
2912         char str[128]; 
2913         short mval[2];
2914         short xoffs;
2915 } ViewParticleString;
2916
2917
2918 void view3d_particle_text_draw_add(float x, float y, float z, char *str, short xoffs)
2919 {
2920         ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString");
2921
2922         BLI_addtail(&pstrings, vos);
2923         BLI_strncpy(vos->str, str, 128);
2924         vos->vec[0]= x;
2925         vos->vec[1]= y;
2926         vos->vec[2]= z;
2927         glGetFloatv(GL_CURRENT_COLOR, vos->col);
2928         vos->xoffs= xoffs;
2929 }
2930
2931 static void view3d_particle_text_draw(View3D *v3d, ARegion *ar)
2932 {
2933         ViewObjectString *vos;
2934         int tot= 0;
2935         
2936         /* project first and test */
2937         for(vos= pstrings.first; vos; vos= vos->next) {
2938                 project_short(ar, vos->vec, vos->mval);
2939                 if(vos->mval[0]!=IS_CLIPPED)
2940                         tot++;
2941         }
2942         
2943         if(tot) {
2944                 RegionView3D *rv3d= ar->regiondata;
2945                 int a;
2946                 
2947                 if(rv3d->rflag & RV3D_CLIPPING)
2948                         for(a=0; a<6; a++)
2949                                 glDisable(GL_CLIP_PLANE0+a);
2950                 
2951                 wmPushMatrix();
2952                 ED_region_pixelspace(ar);
2953                 
2954                 if(v3d->zbuf) glDepthMask(0);
2955
2956                 for(vos= pstrings.first; vos; vos= vos->next) {
2957                         if(vos->mval[0]!=IS_CLIPPED) {
2958                                 glColor3fv(vos->col);
2959                                 BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 2.0, vos->str);
2960                         }
2961                 }
2962                 
2963                 if(v3d->zbuf) glDepthMask(1);
2964                 
2965                 wmPopMatrix();
2966
2967                 if(rv3d->rflag & RV3D_CLIPPING)
2968                         for(a=0; a<6; a++)
2969                                 glEnable(GL_CLIP_PLANE0+a);
2970         }
2971         
2972         if(pstrings.first) 
2973                 BLI_freelistN(&pstrings);
2974 }
2975 typedef struct ParticleDrawData {
2976         float *vdata, *vd;
2977         float *ndata, *nd;
2978         float *cdata, *cd;
2979         float *vedata, *ved;
2980         float *ma_r, *ma_g, *ma_b;
2981 } ParticleDrawData;
2982 static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
2983 {
2984         float vec[3], vec2[3];
2985         float *vd = pdd->vd;
2986         float *cd = pdd->cd;
2987         float ma_r=0.0f;
2988         float ma_g=0.0f;
2989         float ma_b=0.0f;
2990
2991         if(pdd->ma_r) {
2992                 ma_r = *pdd->ma_r;
2993                 ma_g = *pdd->ma_g;
2994                 ma_b = *pdd->ma_b;
2995         }
2996
2997         switch(draw_as){
2998                 case PART_DRAW_DOT:
2999                 {
3000                         if(vd) {
3001                                 VECCOPY(vd,state->co) pdd->vd+=3;
3002                         }
3003                         if(cd) {
3004                                 cd[0]=ma_r;
3005                                 cd[1]=ma_g;
3006                                 cd[2]=ma_b;
3007                                 pdd->cd+=3;
3008                         }
3009                         break;
3010                 }
3011                 case PART_DRAW_CROSS:
3012                 case PART_DRAW_AXIS:
3013                 {
3014                         vec[0]=2.0f*pixsize;
3015                         vec[1]=vec[2]=0.0;
3016                         QuatMulVecf(state->rot,vec);
3017                         if(draw_as==PART_DRAW_AXIS) {
3018                                 cd[1]=cd[2]=cd[4]=cd[5]=0.0;
3019                                 cd[0]=cd[3]=1.0;
3020                                 cd[6]=cd[8]=cd[9]=cd[11]=0.0;
3021                                 cd[7]=cd[10]=1.0;
3022                                 cd[13]=cd[12]=cd[15]=cd[16]=0.0;
3023                                 cd[14]=cd[17]=1.0;
3024                                 cd+=18;
3025
3026                                 VECCOPY(vec2,state->co);
3027                         }
3028                         else {
3029                                 if(cd) {
3030                                         cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
3031                                         cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
3032                                         cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
3033                                         pdd->cd+=18;
3034                                 }
3035                                 VECSUB(vec2,state->co,vec);
3036                         }
3037
3038                         VECADD(vec,state->co,vec);
3039                         VECCOPY(pdd->vd,vec); pdd->vd+=3;
3040                         VECCOPY(pdd->vd,vec2); pdd->vd+=3;
3041                                 
3042                         vec[1]=2.0f*pixsize;
3043                         vec[0]=vec[2]=0.0;
3044                         QuatMulVecf(state->rot,vec);
3045                         if(draw_as==PART_DRAW_AXIS){
3046                                 VECCOPY(vec2,state->co);
3047                         }               
3048                         else VECSUB(vec2,state->co,vec);
3049
3050                         VECADD(vec,state->co,vec);
3051                         VECCOPY(pdd->vd,vec); pdd->vd+=3;
3052                         VECCOPY(pdd->vd,vec2); pdd->vd+=3;
3053