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