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