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