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