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