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