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