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