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