Merged 40338-40364
[blender.git] / source / blender / editors / space_view3d / drawobject.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, full recode and added functions
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_view3d/drawobject.c
29  *  \ingroup spview3d
30  */
31
32
33 #include <string.h>
34 #include <math.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_camera_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_constraint_types.h" // for drawing constraint
41 #include "DNA_lamp_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_smoke_types.h"
48 #include "DNA_speaker_types.h"
49 #include "DNA_world_types.h"
50 #include "DNA_armature_types.h"
51
52 #include "BLI_blenlib.h"
53 #include "BLI_math.h"
54 #include "BLI_editVert.h"
55 #include "BLI_edgehash.h"
56 #include "BLI_rand.h"
57 #include "BLI_utildefines.h"
58
59 #include "BKE_anim.h"                   //for the where_on_path function
60 #include "BKE_constraint.h" // for the get_constraint_target function
61 #include "BKE_curve.h"
62 #include "BKE_DerivedMesh.h"
63 #include "BKE_deform.h"
64 #include "BKE_displist.h"
65 #include "BKE_font.h"
66 #include "BKE_global.h"
67 #include "BKE_image.h"
68 #include "BKE_key.h"
69 #include "BKE_lattice.h"
70 #include "BKE_mesh.h"
71 #include "BKE_material.h"
72 #include "BKE_mball.h"
73 #include "BKE_modifier.h"
74 #include "BKE_object.h"
75 #include "BKE_paint.h"
76 #include "BKE_particle.h"
77 #include "BKE_pointcache.h"
78 #include "BKE_unit.h"
79
80 #include "smoke_API.h"
81
82 #include "IMB_imbuf.h"
83 #include "IMB_imbuf_types.h"
84
85 #include "BIF_gl.h"
86 #include "BIF_glutil.h"
87
88 #include "GPU_draw.h"
89 #include "GPU_extensions.h"
90
91 #include "ED_mesh.h"
92 #include "ED_particle.h"
93 #include "ED_screen.h"
94 #include "ED_sculpt.h"
95 #include "ED_types.h"
96 #include "ED_curve.h" /* for curve_editnurbs */
97
98 #include "UI_resources.h"
99
100 #include "WM_api.h"
101 #include "wm_subwindow.h"
102 #include "BLF_api.h"
103
104 #include "view3d_intern.h"      // own include
105
106
107 /* this condition has been made more complex since editmode can draw textures */
108 #define CHECK_OB_DRAWTEXTURE(vd, dt) \
109 ((vd->drawtype==OB_TEXTURE && dt>OB_SOLID) || \
110         (vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
111
112 static void draw_bounding_volume(Scene *scene, Object *ob);
113
114 static void drawcube_size(float size);
115 static void drawcircle_size(float size);
116 static void draw_empty_sphere(float size);
117 static void draw_empty_cone(float size);
118
119 static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
120 {
121         if((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
122                 return 0;
123
124         if(G.f & G_BACKBUFSEL)
125                 return 0;
126
127         if((vd->flag & V3D_ZBUF_SELECT) == 0)
128                 return 1;
129
130         /* if its drawing textures with zbuf sel, then dont draw dots */
131         if(dt==OB_TEXTURE && vd->drawtype==OB_TEXTURE)
132                 return 0;
133
134         if(vd->drawtype>=OB_SOLID && vd->flag2 & V3D_SOLID_TEX)
135                 return 0;
136
137         return 1;
138 }
139
140 /* ************* only use while object drawing **************
141  * or after running ED_view3d_init_mats_rv3d
142  * */
143 static void view3d_project_short_clip(ARegion *ar, const float vec[3], short *adr, int local)
144 {
145         RegionView3D *rv3d= ar->regiondata;
146         float fx, fy, vec4[4];
147         
148         adr[0]= IS_CLIPPED;
149         
150         /* clipplanes in eye space */
151         if(rv3d->rflag & RV3D_CLIPPING) {
152                 if(ED_view3d_test_clipping(rv3d, vec, local))
153                         return;
154         }
155         
156         copy_v3_v3(vec4, vec);
157         vec4[3]= 1.0;
158         
159         mul_m4_v4(rv3d->persmatob, vec4);
160         
161         /* clipplanes in window space */
162         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
163                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
164                 
165                 if( fx>0 && fx<ar->winx) {
166                         
167                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
168                         
169                         if(fy > 0.0f && fy < (float)ar->winy) {
170                                 adr[0]= (short)floorf(fx);
171                                 adr[1]= (short)floorf(fy);
172                         }
173                 }
174         }
175 }
176
177 /* only use while object drawing */
178 static void view3d_project_short_noclip(ARegion *ar, const float vec[3], short *adr)
179 {
180         RegionView3D *rv3d= ar->regiondata;
181         float fx, fy, vec4[4];
182         
183         adr[0]= IS_CLIPPED;
184         
185         copy_v3_v3(vec4, vec);
186         vec4[3]= 1.0;
187         
188         mul_m4_v4(rv3d->persmatob, vec4);
189         
190         if( vec4[3] > (float)BL_NEAR_CLIP ) {   /* is the NEAR clipping cutoff for picking */
191                 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
192                 
193                 if( fx>-32700 && fx<32700) {
194                         
195                         fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
196                         
197                         if(fy > -32700.0f && fy < 32700.0f) {
198                                 adr[0]= (short)floorf(fx);
199                                 adr[1]= (short)floorf(fy);
200                         }
201                 }
202         }
203 }
204
205 /* ************************ */
206
207 /* check for glsl drawing */
208
209 int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
210 {
211         if(!GPU_glsl_support())
212                 return 0;
213         if(G.f & G_PICKSEL)
214                 return 0;
215         if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
216                 return 0;
217         if(ob==OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
218                 return 0;
219         
220         return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
221 }
222
223 static int check_material_alpha(Base *base, Mesh *me, int glsl)
224 {
225         if(base->flag & OB_FROMDUPLI)
226                 return 0;
227
228         if(G.f & G_PICKSEL)
229                 return 0;
230                         
231         if(me->edit_mesh)
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 cn 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 vec[8][4], facx, facy, depth, aspx, aspy, caspx, caspy, shx, shy;
1377         int i;
1378         float drawsize;
1379         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1380
1381         const float scax= 1.0f / len_v3(ob->obmat[0]);
1382         const float scay= 1.0f / len_v3(ob->obmat[1]);
1383         const float scaz= 1.0f / len_v3(ob->obmat[2]);
1384
1385 #ifdef VIEW3D_CAMERA_BORDER_HACK
1386         if(is_view && !(G.f & G_PICKSEL)) {
1387                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1388                 view3d_camera_border_hack_test= TRUE;
1389                 return;
1390         }
1391 #endif
1392
1393         cam= ob->data;
1394         aspx= (float) scene->r.xsch*scene->r.xasp;
1395         aspy= (float) scene->r.ysch*scene->r.yasp;
1396
1397         if(aspx < aspy) {
1398                 caspx= aspx / aspy;
1399                 caspy= 1.0;
1400         }
1401         else {
1402                 caspx= 1.0;
1403                 caspy= aspy / aspx;
1404         }
1405         
1406         glDisable(GL_LIGHTING);
1407         glDisable(GL_CULL_FACE);
1408         
1409         if(cam->type==CAM_ORTHO) {
1410                 facx= 0.5f * cam->ortho_scale * caspx * scax;
1411                 facy= 0.5f * cam->ortho_scale * caspy * scay;
1412                 shx= cam->shiftx * cam->ortho_scale * scax;
1413                 shy= cam->shifty * cam->ortho_scale * scay;
1414                 depth= is_view ? -((cam->clipsta * scaz) + 0.1f) : - cam->drawsize * cam->ortho_scale * scaz;
1415                 
1416                 drawsize= 0.5f * cam->ortho_scale;
1417         }
1418         else {
1419                 /* that way it's always visible - clipsta+0.1 */
1420                 float fac;
1421                 drawsize= cam->drawsize / ((scax + scay + scaz) / 3.0f);
1422
1423                 if(is_view) {
1424                         /* fixed depth, variable size (avoids exceeding clipping range) */
1425                         depth = -(cam->clipsta + 0.1f);
1426                         fac = depth / (cam->lens/-16.0f * scaz);
1427                 }
1428                 else {
1429                         /* fixed size, variable depth (stays a reasonable size in the 3D view) */
1430                         depth= drawsize * cam->lens/-16.0f * scaz;
1431                         fac= drawsize;
1432                 }
1433
1434                 facx= fac * caspx * scax;
1435                 facy= fac * caspy * scay;
1436                 shx= cam->shiftx*fac*2 * scax;
1437                 shy= cam->shifty*fac*2 * scay;
1438         }
1439         
1440         vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.0;
1441         vec[1][0]= shx + facx; vec[1][1]= shy + facy; vec[1][2]= depth;
1442         vec[2][0]= shx + facx; vec[2][1]= shy - facy; vec[2][2]= depth;
1443         vec[3][0]= shx - facx; vec[3][1]= shy - facy; vec[3][2]= depth;
1444         vec[4][0]= shx - facx; vec[4][1]= shy + facy; vec[4][2]= depth;
1445
1446         /* camera frame */
1447         glBegin(GL_LINE_LOOP);
1448                 glVertex3fv(vec[1]); 
1449                 glVertex3fv(vec[2]); 
1450                 glVertex3fv(vec[3]); 
1451                 glVertex3fv(vec[4]);
1452         glEnd();
1453
1454         if(is_view)
1455                 return;
1456
1457         /* center point to camera frame */
1458         glBegin(GL_LINE_STRIP);
1459                 glVertex3fv(vec[2]); 
1460                 glVertex3fv(vec[0]);
1461                 glVertex3fv(vec[1]);
1462                 glVertex3fv(vec[4]);
1463                 glVertex3fv(vec[0]);
1464                 glVertex3fv(vec[3]); 
1465         glEnd();
1466
1467
1468         /* arrow on top */
1469         vec[0][2]= depth;
1470
1471
1472         /* draw an outline arrow for inactive cameras and filled
1473          * for active cameras. We actually draw both outline+filled
1474          * for active cameras so the wire can be seen side-on */        
1475         for (i=0;i<2;i++) {
1476                 if (i==0) glBegin(GL_LINE_LOOP);
1477                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1478                 else break;
1479
1480                 vec[0][0]= shx + ((-0.7f * drawsize) * scax);
1481                 vec[0][1]= shy + ((drawsize * (caspy + 0.1f)) * scay);
1482                 glVertex3fv(vec[0]); /* left */
1483                 
1484                 vec[0][0]= shx + ((0.7f * drawsize) * scax);
1485                 glVertex3fv(vec[0]); /* right */
1486                 
1487                 vec[0][0]= shx;
1488                 vec[0][1]= shy + ((1.1f * drawsize * (caspy + 0.7f)) * scay);
1489                 glVertex3fv(vec[0]); /* top */
1490         
1491                 glEnd();
1492         }
1493
1494         if(flag==0) {
1495                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1496                         float nobmat[4][4];
1497                         World *wrld;
1498         
1499                         /* draw in normalized object matrix space */
1500                         copy_m4_m4(nobmat, ob->obmat);
1501                         normalize_m4(nobmat);
1502
1503                         glPushMatrix();
1504                         glLoadMatrixf(rv3d->viewmat);
1505                         glMultMatrixf(nobmat);
1506
1507                         if(cam->flag & CAM_SHOWLIMITS) {
1508                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1509                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1510                                 draw_focus_cross(dof_camera(ob), cam->drawsize);
1511                         }
1512
1513                         wrld= scene->world;
1514                         if(cam->flag & CAM_SHOWMIST) 
1515                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1516                                 
1517                         glPopMatrix();
1518                 }
1519         }
1520 }
1521
1522 /* flag similar to draw_object() */
1523 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), Object *UNUSED(ob), int UNUSED(flag))
1524 {
1525         //Speaker *spk = ob->data;
1526
1527         float vec[3];
1528         int i, j;
1529
1530         glEnable(GL_BLEND);
1531
1532         for(j = 0; j < 3; j++) {
1533                 vec[2] = 0.25f * j -0.125f;
1534
1535                 glBegin(GL_LINE_LOOP);
1536                 for(i = 0; i < 16; i++) {
1537                         vec[0] = cosf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1538                         vec[1] = sinf(M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1539                         glVertex3fv(vec);
1540                 }
1541                 glEnd();
1542         }
1543
1544         for(j = 0; j < 4; j++) {
1545                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1546                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1547                 glBegin(GL_LINE_STRIP);
1548                 for(i = 0; i < 3; i++) {
1549                         if(i == 1) {
1550                                 vec[0] *= 0.5f;
1551                                 vec[1] *= 0.5f;
1552                         }
1553
1554                         vec[2] = 0.25f * i -0.125f;
1555                         glVertex3fv(vec);
1556                 }
1557                 glEnd();
1558         }
1559
1560         glDisable(GL_BLEND);
1561 }
1562
1563 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1564 {
1565         BPoint *bp = lt->def;
1566         float *co = dl?dl->verts:NULL;
1567         int u, v, w;
1568
1569         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1570         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1571         bglBegin(GL_POINTS);
1572
1573         for(w=0; w<lt->pntsw; w++) {
1574                 int wxt = (w==0 || w==lt->pntsw-1);
1575                 for(v=0; v<lt->pntsv; v++) {
1576                         int vxt = (v==0 || v==lt->pntsv-1);
1577                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1578                                 int uxt = (u==0 || u==lt->pntsu-1);
1579                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1580                                         if(bp->hide==0) {
1581                                                 if((bp->f1 & SELECT)==sel) {
1582                                                         bglVertex3fv(dl?co:bp->vec);
1583                                                 }
1584                                         }
1585                                 }
1586                         }
1587                 }
1588         }
1589         
1590         glPointSize(1.0);
1591         bglEnd();       
1592 }
1593
1594 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1595 {
1596         Object *obedit= vc->obedit;
1597         Lattice *lt= obedit->data;
1598         BPoint *bp = lt->editlatt->latt->def;
1599         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1600         float *co = dl?dl->verts:NULL;
1601         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1602         short s[2] = {IS_CLIPPED, 0};
1603
1604         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1605
1606         for (i=0; i<N; i++, bp++, co+=3) {
1607                 if (bp->hide==0) {
1608                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1609                         if (s[0] != IS_CLIPPED)
1610                                 func(userData, bp, s[0], s[1]);
1611                 }
1612         }
1613 }
1614
1615 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1616 {
1617         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1618
1619         if(use_wcol) {
1620                 float col[3];
1621                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1622                 
1623                 weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
1624                 glColor3fv(col);
1625
1626         }
1627         
1628         if (dl) {
1629                 glVertex3fv(&dl->verts[index*3]);
1630         } else {
1631                 glVertex3fv(lt->def[index].vec);
1632         }
1633 }
1634
1635 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1636 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1637 {
1638         Lattice *lt= ob->data;
1639         DispList *dl;
1640         int u, v, w;
1641         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1642
1643         /* now we default make displist, this will modifiers work for non animated case */
1644         if(ob->disp.first==NULL)
1645                 lattice_calc_modifiers(scene, ob);
1646         dl= find_displist(&ob->disp, DL_VERTS);
1647         
1648         if(is_edit) {
1649                 lt= lt->editlatt->latt;
1650
1651                 cpack(0x004000);
1652                 
1653                 if(ob->defbase.first && lt->dvert) {
1654                         use_wcol= ob->actdef;
1655                         glShadeModel(GL_SMOOTH);
1656                 }
1657         }
1658         
1659         glBegin(GL_LINES);
1660         for(w=0; w<lt->pntsw; w++) {
1661                 int wxt = (w==0 || w==lt->pntsw-1);
1662                 for(v=0; v<lt->pntsv; v++) {
1663                         int vxt = (v==0 || v==lt->pntsv-1);
1664                         for(u=0; u<lt->pntsu; u++) {
1665                                 int uxt = (u==0 || u==lt->pntsu-1);
1666
1667                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1668                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1669                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1670                                 }
1671                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1672                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1673                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1674                                 }
1675                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1676                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1677                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1678                                 }
1679                         }
1680                 }
1681         }               
1682         glEnd();
1683         
1684         /* restoration for weight colors */
1685         if(use_wcol)
1686                 glShadeModel(GL_FLAT);
1687
1688         if(is_edit) {
1689                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1690                 
1691                 lattice_draw_verts(lt, dl, 0);
1692                 lattice_draw_verts(lt, dl, 1);
1693                 
1694                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1695         }
1696 }
1697
1698 /* ***************** ******************** */
1699
1700 /* Note! - foreach funcs should be called while drawing or directly after
1701  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1702  * but would not give correct results with dupli's for eg. which dont
1703  * use the object matrix in the useual way */
1704 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1705 {
1706         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
1707         EditVert *eve = EM_get_vert_for_index(index);
1708
1709         if (eve->h==0) {
1710                 short s[2]= {IS_CLIPPED, 0};
1711
1712                 if (data->clipVerts) {
1713                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1714                 } else {
1715                         view3d_project_short_noclip(data->vc.ar, co, s);
1716                 }
1717
1718                 if (s[0]!=IS_CLIPPED)
1719                         data->func(data->userData, eve, s[0], s[1], index);
1720         }
1721 }
1722
1723 void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
1724 {
1725         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
1726         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1727         
1728         data.vc= *vc;
1729         data.func = func;
1730         data.userData = userData;
1731         data.clipVerts = clipVerts;
1732
1733         if(clipVerts)
1734                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1735
1736         EM_init_index_arrays(vc->em, 1, 0, 0);
1737         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1738         EM_free_index_arrays();
1739
1740         dm->release(dm);
1741 }
1742
1743 /*  draw callback */
1744 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1745 {
1746         MVert *mv = &((MVert *)userData)[index];
1747
1748         if(!(mv->flag & ME_HIDE)) {
1749                 const char sel= mv->flag & SELECT;
1750
1751                 // TODO define selected color
1752                 if(sel) {
1753                         glColor3f(1.0f, 1.0f, 0.0f);
1754                 }
1755                 else {
1756                         glColor3f(0.0f, 0.0f, 0.0f);
1757                 }
1758
1759                 glVertex3fv(co);
1760         }
1761 }
1762
1763 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) {
1764         glBegin(GL_POINTS);
1765         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
1766         glEnd();
1767 }
1768 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
1769 {
1770         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;
1771         EditEdge *eed = EM_get_edge_for_index(index);
1772         short s[2][2];
1773
1774         if (eed->h==0) {
1775                 if (data->clipVerts==1) {
1776                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
1777                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
1778                 } else {
1779                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
1780                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
1781
1782                         if (data->clipVerts==2) {
1783                                 if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
1784                                         if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->vc.ar->winx && s[1][1]<data->vc.ar->winy)) 
1785                                                 return;
1786                         }
1787                 }
1788
1789                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
1790         }
1791 }
1792
1793 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)
1794 {
1795         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
1796         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1797
1798         data.vc= *vc;
1799         data.func = func;
1800         data.userData = userData;
1801         data.clipVerts = clipVerts;
1802
1803         if(clipVerts)
1804                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1805
1806         EM_init_index_arrays(vc->em, 0, 1, 0);
1807         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
1808         EM_free_index_arrays();
1809
1810         dm->release(dm);
1811 }
1812
1813 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1814 {
1815         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
1816         EditFace *efa = EM_get_face_for_index(index);
1817         short s[2];
1818
1819         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
1820                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
1821
1822                 data->func(data->userData, efa, s[0], s[1], index);
1823         }
1824 }
1825
1826 void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
1827 {
1828         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
1829         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1830
1831         data.vc= *vc;
1832         data.func = func;
1833         data.userData = userData;
1834
1835         //if(clipVerts)
1836         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1837
1838         EM_init_index_arrays(vc->em, 0, 0, 1);
1839         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
1840         EM_free_index_arrays();
1841
1842         dm->release(dm);
1843 }
1844
1845 void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
1846 {
1847         Curve *cu= vc->obedit->data;
1848         short s[2] = {IS_CLIPPED, 0};
1849         Nurb *nu;
1850         int i;
1851         ListBase *nurbs= curve_editnurbs(cu);
1852
1853         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1854
1855         for (nu= nurbs->first; nu; nu=nu->next) {
1856                 if(nu->type == CU_BEZIER) {
1857                         for (i=0; i<nu->pntsu; i++) {
1858                                 BezTriple *bezt = &nu->bezt[i];
1859
1860                                 if(bezt->hide==0) {
1861                                         
1862                                         if(cu->drawflag & CU_HIDE_HANDLES) {
1863                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1864                                                 if (s[0] != IS_CLIPPED)
1865                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1866                                         } else {
1867                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
1868                                                 if (s[0] != IS_CLIPPED)
1869                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
1870                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
1871                                                 if (s[0] != IS_CLIPPED)
1872                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
1873                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
1874                                                 if (s[0] != IS_CLIPPED)
1875                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
1876                                         }
1877                                 }
1878                         }
1879                 }
1880                 else {
1881                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
1882                                 BPoint *bp = &nu->bp[i];
1883
1884                                 if(bp->hide==0) {
1885                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
1886                                         if (s[0] != IS_CLIPPED)
1887                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
1888                                 }
1889                         }
1890                 }
1891         }
1892 }
1893
1894 /* ************** DRAW MESH ****************** */
1895
1896 /* First section is all the "simple" draw routines, 
1897  * ones that just pass some sort of primitive to GL,
1898  * with perhaps various options to control lighting,
1899  * color, etc.
1900  *
1901  * These routines should not have user interface related
1902  * logic!!!
1903  */
1904
1905 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
1906 {
1907         ToolSettings *ts= ((Scene *)userData)->toolsettings;
1908         EditFace *efa = EM_get_face_for_index(index);
1909
1910         if (efa->h==0 && efa->fgonf!=EM_FGON) {
1911                 glVertex3fv(cent);
1912                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
1913                                         cent[1] + no[1]*ts->normalsize,
1914                                         cent[2] + no[2]*ts->normalsize);
1915         }
1916 }
1917 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
1918 {
1919         glBegin(GL_LINES);
1920         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
1921         glEnd();
1922 }
1923
1924 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
1925 {
1926         EditFace *efa = EM_get_face_for_index(index);
1927         int sel = *((int*) userData);
1928
1929         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
1930                 bglVertex3fv(cent);
1931         }
1932 }
1933 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
1934 {
1935         bglBegin(GL_POINTS);
1936         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
1937         bglEnd();
1938 }
1939
1940 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1941 {
1942         Scene *scene= (Scene *)userData;
1943         ToolSettings *ts= scene->toolsettings;
1944         EditVert *eve = EM_get_vert_for_index(index);
1945
1946         if (eve->h==0) {
1947                 glVertex3fv(co);
1948
1949                 if (no_f) {
1950                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
1951                                                 co[1] + no_f[1]*ts->normalsize,
1952                                                 co[2] + no_f[2]*ts->normalsize);
1953                 } else {
1954                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
1955                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
1956                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
1957                 }
1958         }
1959 }
1960 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
1961 {
1962         glBegin(GL_LINES);
1963         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
1964         glEnd();
1965 }
1966
1967         /* Draw verts with color set based on selection */
1968 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1969 {
1970         struct { int sel; EditVert *eve_act; } * data = userData;
1971         EditVert *eve = EM_get_vert_for_index(index);
1972
1973         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
1974                 /* draw active larger - need to stop/start point drawing for this :/ */
1975                 if (eve==data->eve_act) {
1976                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
1977                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
1978                         
1979                         bglEnd();
1980                         
1981                         glPointSize(size);
1982                         bglBegin(GL_POINTS);
1983                         bglVertex3fv(co);
1984                         bglEnd();
1985                         
1986                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
1987                         glPointSize(size);
1988                         bglBegin(GL_POINTS);
1989                 } else {
1990                         bglVertex3fv(co);
1991                 }
1992         }
1993 }
1994
1995 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
1996 {
1997         struct { int sel; EditVert *eve_act; } data;
1998         data.sel = sel;
1999         data.eve_act = eve_act;
2000
2001         bglBegin(GL_POINTS);
2002         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2003         bglEnd();
2004 }
2005
2006         /* Draw edges with color set based on selection */
2007 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2008 {
2009         EditEdge *eed = EM_get_edge_for_index(index);
2010         //unsigned char **cols = userData, *col;
2011         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
2012         unsigned char *col;
2013
2014         if (eed->h==0) {
2015                 if (eed==data->eed_act) {
2016                         glColor4ubv(data->actCol);
2017                 } else {
2018                         if (eed->f&SELECT) {
2019                                 col = data->selCol;
2020                         } else {
2021                                 col = data->baseCol;
2022                         }
2023                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2024                         if (col[3]==0) return 0;
2025                         
2026                         glColor4ubv(col);
2027                 }
2028                 return 1;
2029         } else {
2030                 return 0;
2031         }
2032 }
2033 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
2034 {
2035         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
2036         
2037         data.baseCol = baseCol;
2038         data.selCol = selCol;
2039         data.actCol = actCol;
2040         data.eed_act = eed_act;
2041         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2042 }
2043
2044         /* Draw edges */
2045 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2046 {
2047         return EM_get_edge_for_index(index)->h==0;
2048 }
2049 static void draw_dm_edges(DerivedMesh *dm) 
2050 {
2051         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2052 }
2053
2054         /* Draw edges with color interpolated based on selection */
2055 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2056 {
2057         return EM_get_edge_for_index(index)->h==0;
2058 }
2059 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2060 {
2061         EditEdge *eed = EM_get_edge_for_index(index);
2062         unsigned char **cols = userData;
2063         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2064         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2065
2066         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2067                                 col0[1] + (col1[1]-col0[1])*t,
2068                                 col0[2] + (col1[2]-col0[2])*t,
2069                                 col0[3] + (col1[3]-col0[3])*t);
2070 }
2071
2072 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2073 {
2074         unsigned char *cols[2];
2075         cols[0]= baseCol;
2076         cols[1]= selCol;
2077         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2078 }
2079
2080         /* Draw only seam edges */
2081 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2082 {
2083         EditEdge *eed = EM_get_edge_for_index(index);
2084
2085         return (eed->h==0 && eed->seam);
2086 }
2087 static void draw_dm_edges_seams(DerivedMesh *dm)
2088 {
2089         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2090 }
2091
2092         /* Draw only sharp edges */
2093 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2094 {
2095         EditEdge *eed = EM_get_edge_for_index(index);
2096
2097         return (eed->h==0 && eed->sharp);
2098 }
2099 static void draw_dm_edges_sharp(DerivedMesh *dm)
2100 {
2101         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2102 }
2103
2104
2105         /* Draw faces with color set based on selection
2106          * return 2 for the active face so it renders with stipple enabled */
2107 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2108 {
2109         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2110         EditFace *efa = EM_get_face_for_index(index);
2111         unsigned char *col;
2112         
2113         if (efa->h==0) {
2114                 if (efa == data->efa_act) {
2115                         glColor4ubv(data->cols[2]);
2116                         return 2; /* stipple */
2117                 } else {
2118                         col = data->cols[(efa->f&SELECT)?1:0];
2119                         if (col[3]==0) return 0;
2120                         glColor4ubv(col);
2121                         return 1;
2122                 }
2123         }
2124         return 0;
2125 }
2126
2127 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2128 {
2129         struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
2130         EditFace *efa = EM_get_face_for_index(index);
2131         EditFace *next_efa = EM_get_face_for_index(next_index);
2132         unsigned char *col, *next_col;
2133
2134         if(efa == next_efa)
2135                 return 1;
2136
2137         if(efa == data->efa_act || next_efa == data->efa_act)
2138                 return 0;
2139
2140         col = data->cols[(efa->f&SELECT)?1:0];
2141         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2142
2143         if(col[3]==0 || next_col[3]==0)
2144                 return 0;
2145
2146         return col == next_col;
2147 }
2148
2149 /* also draws the active face */
2150 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2151 {
2152         struct { unsigned char *cols[3]; EditFace *efa_act; } data;
2153         data.cols[0] = baseCol;
2154         data.cols[1] = selCol;
2155         data.cols[2] = actCol;
2156         data.efa_act = efa_act;
2157
2158         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
2159 }
2160
2161 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2162 {
2163         EditEdge *eed = EM_get_edge_for_index(index);
2164
2165         if (eed->h==0 && eed->crease != 0.0f) {
2166                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2167                 return 1;
2168         } else {
2169                 return 0;
2170         }
2171 }
2172 static void draw_dm_creases(DerivedMesh *dm)
2173 {
2174         glLineWidth(3.0);
2175         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2176         glLineWidth(1.0);
2177 }
2178
2179 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2180 {
2181         EditEdge *eed = EM_get_edge_for_index(index);
2182
2183         if (eed->h==0 && eed->bweight != 0.0f) {
2184                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2185                 return 1;
2186         } else {
2187                 return 0;
2188         }
2189 }
2190 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2191 {
2192         EditVert *eve = EM_get_vert_for_index(index);
2193
2194         if (eve->h==0 && eve->bweight != 0.0f) {
2195                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2196                 bglVertex3fv(co);
2197         }
2198 }
2199 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2200 {
2201         ToolSettings *ts= scene->toolsettings;
2202
2203         if (ts->selectmode & SCE_SELECT_VERTEX) {
2204                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2205                 bglBegin(GL_POINTS);
2206                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2207                 bglEnd();
2208         }
2209         else {
2210                 glLineWidth(3.0);
2211                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2212                 glLineWidth(1.0);
2213         }
2214 }
2215
2216 /* Second section of routines: Combine first sets to form fancy
2217  * drawing routines (for example rendering twice to get overlays).
2218  *
2219  * Also includes routines that are basic drawing but are too
2220  * specialized to be split out (like drawing creases or measurements).
2221  */
2222
2223 /* EditMesh drawing routines*/
2224
2225 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
2226 {
2227         ToolSettings *ts= scene->toolsettings;
2228         int sel;
2229
2230         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2231
2232         for (sel=0; sel<2; sel++) {
2233                 unsigned char col[4], fcol[4];
2234                 int pass;
2235
2236                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2237                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2238
2239                 for (pass=0; pass<2; pass++) {
2240                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2241                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2242
2243                         if (pass==0) {
2244                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2245                                         glDisable(GL_DEPTH_TEST);
2246                                                 
2247                                         glEnable(GL_BLEND);
2248                                 } else {
2249                                         continue;
2250                                 }
2251
2252                                 size = (size > 2.1f ? size/2.0f:size);
2253                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2254                                 col[3] = fcol[3] = 100;
2255                         } else {
2256                                 col[3] = fcol[3] = 255;
2257                         }
2258                                 
2259                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2260                                 glPointSize(size);
2261                                 glColor4ubv(col);
2262                                 draw_dm_verts(cageDM, sel, eve_act);
2263                         }
2264                         
2265                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2266                                 glPointSize(fsize);
2267                                 glColor4ubv(fcol);
2268                                 draw_dm_face_centers(cageDM, sel);
2269                         }
2270                         
2271                         if (pass==0) {
2272                                 glDisable(GL_BLEND);
2273                                 glEnable(GL_DEPTH_TEST);
2274                         }
2275                 }
2276         }
2277
2278         if(v3d->zbuf) glDepthMask(1);
2279         glPointSize(1.0);
2280 }
2281
2282 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
2283 {
2284         ToolSettings *ts= scene->toolsettings;
2285         int pass;
2286         unsigned char wireCol[4], selCol[4], actCol[4];
2287
2288         /* since this function does transparant... */
2289         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2290         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2291         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2292         
2293         /* when sel only is used, dont render wire, only selected, this is used for
2294          * textured draw mode when the 'edges' option is disabled */
2295         if (sel_only)
2296                 wireCol[3] = 0;
2297
2298         for (pass=0; pass<2; pass++) {
2299                         /* show wires in transparant when no zbuf clipping for select */
2300                 if (pass==0) {
2301                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2302                                 glEnable(GL_BLEND);
2303                                 glDisable(GL_DEPTH_TEST);
2304                                 selCol[3] = 85;
2305                                 if (!sel_only) wireCol[3] = 85;
2306                         } else {
2307                                 continue;
2308                         }
2309                 } else {
2310                         selCol[3] = 255;
2311                         if (!sel_only) wireCol[3] = 255;
2312                 }
2313
2314                 if(ts->selectmode == SCE_SELECT_FACE) {
2315                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2316                 }       
2317                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2318                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2319                                 glShadeModel(GL_SMOOTH);
2320                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2321                                 glShadeModel(GL_FLAT);
2322                         } else {
2323                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2324                         }
2325                 }
2326                 else {
2327                         if (!sel_only) {
2328                                 glColor4ubv(wireCol);
2329                                 draw_dm_edges(cageDM);
2330                         }
2331                 }
2332
2333                 if (pass==0) {
2334                         glDisable(GL_BLEND);
2335                         glEnable(GL_DEPTH_TEST);
2336                 }
2337         }
2338 }       
2339
2340 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
2341 {
2342         Mesh *me= ob->data;
2343         EditEdge *eed;
2344         EditFace *efa;
2345         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2346         float fvec[3];
2347         char val[32]; /* Stores the measurement display text here */
2348         const char *conv_float; /* Use a float conversion matching the grid size */
2349         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2350         float area; /* area of the face */
2351         float grid= unit->system ? unit->scale_length : v3d->grid;
2352         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2353         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2354         const int do_moving= G.moving;
2355
2356         /* make the precision of the pronted value proportionate to the gridsize */
2357
2358         if (grid < 0.01f)               conv_float= "%.6g";
2359         else if (grid < 0.1f)   conv_float= "%.5g";
2360         else if (grid < 1.0f)   conv_float= "%.4g";
2361         else if (grid < 10.0f)  conv_float= "%.3g";
2362         else                                    conv_float= "%.2g";
2363
2364         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2365                 glDisable(GL_DEPTH_TEST);
2366
2367         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2368         
2369         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2370                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2371
2372                 for(eed= em->edges.first; eed; eed= eed->next) {
2373                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2374                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2375                                 copy_v3_v3(v1, eed->v1->co);
2376                                 copy_v3_v3(v2, eed->v2->co);
2377
2378                                 interp_v3_v3v3(vmid, v1, v2, 0.5f);
2379
2380                                 if(do_global) {
2381                                         mul_mat3_m4_v3(ob->obmat, v1);
2382                                         mul_mat3_m4_v3(ob->obmat, v2);
2383                                 }
2384                                 if(unit->system)
2385                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2386                                 else
2387                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2388
2389                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2390                         }
2391                 }
2392         }
2393
2394         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2395 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2396                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2397                 
2398                 for(efa= em->faces.first; efa; efa= efa->next) {
2399                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2400                                 copy_v3_v3(v1, efa->v1->co);
2401                                 copy_v3_v3(v2, efa->v2->co);
2402                                 copy_v3_v3(v3, efa->v3->co);
2403                                 if (efa->v4) {
2404                                         copy_v3_v3(v4, efa->v4->co);
2405                                 }
2406                                 if(do_global) {
2407                                         mul_mat3_m4_v3(ob->obmat, v1);
2408                                         mul_mat3_m4_v3(ob->obmat, v2);
2409                                         mul_mat3_m4_v3(ob->obmat, v3);
2410                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2411                                 }
2412                                 
2413                                 if (efa->v4)
2414                                         area=  area_quad_v3(v1, v2, v3, v4);
2415                                 else
2416                                         area = area_tri_v3(v1, v2, v3);
2417
2418                                 if(unit->system)
2419                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2420                                 else
2421                                         sprintf(val, conv_float, area);
2422
2423                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2424                         }
2425                 }
2426         }
2427
2428         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2429                 EditEdge *e1, *e2, *e3, *e4;
2430                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2431                 for(efa= em->faces.first; efa; efa= efa->next) {
2432                         copy_v3_v3(v1, efa->v1->co);
2433                         copy_v3_v3(v2, efa->v2->co);
2434                         copy_v3_v3(v3, efa->v3->co);
2435                         if(efa->v4) {
2436                                 copy_v3_v3(v4, efa->v4->co); 
2437                         }
2438                         else {
2439                                 copy_v3_v3(v4, v3);
2440                         }
2441                         if(do_global) {
2442                                 mul_mat3_m4_v3(ob->obmat, v1);
2443                                 mul_mat3_m4_v3(ob->obmat, v2);
2444                                 mul_mat3_m4_v3(ob->obmat, v3);
2445                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2446                         }
2447                         
2448                         e1= efa->e1;
2449                         e2= efa->e2;
2450                         e3= efa->e3;
2451                         if(efa->e4) e4= efa->e4; else e4= e3;
2452                         
2453                         /* Calculate the angles */
2454                                 
2455                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2456                                 /* Vec 1 */
2457                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2458                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2459                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2460                         }
2461                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2462                                 /* Vec 2 */
2463                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2464                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2465                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2466                         }
2467                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2468                                 /* Vec 3 */
2469                                 if(efa->v4) 
2470                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2471                                 else
2472                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2473                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2474                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2475                         }
2476                                 /* Vec 4 */
2477                         if(efa->v4) {
2478                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2479                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2480                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2481                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2482                                 }
2483                         }
2484                 }
2485         }
2486
2487         /* useful for debugging index vs shape key index */
2488 #if 0
2489         {
2490                 EditVert *eve;
2491                 int j;
2492                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2493                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2494                         sprintf(val, "%d:%d", j, eve->keyindex);
2495                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2496                 }
2497         }
2498 #endif
2499
2500         if(v3d->zbuf) {
2501                 glEnable(GL_DEPTH_TEST);
2502                 bglPolygonOffset(rv3d->dist, 0.0f);
2503         }
2504 }
2505
2506 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2507 {
2508         EditFace *efa = EM_get_face_for_index(index);
2509
2510         if (efa->h==0) {
2511                 GPU_enable_material(efa->mat_nr+1, NULL);
2512                 return 1;
2513         }
2514         else
2515                 return 0;
2516 }
2517
2518 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2519 {
2520         EditFace *efa = EM_get_face_for_index(index);
2521
2522         return (efa->h==0);
2523 }
2524
2525 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2526 {
2527         Mesh *me = ob->data;
2528         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2529         EditEdge *eed_act = NULL;
2530         EditVert *eve_act = NULL;
2531         
2532         if (em->selected.last) {
2533                 EditSelection *ese = em->selected.last;
2534                 /* face is handeled above */
2535                 /*if (ese->type == EDITFACE ) {
2536                         efa_act = (EditFace *)ese->data;
2537                 } else */ if ( ese->type == EDITEDGE ) {
2538                         eed_act = (EditEdge *)ese->data;
2539                 } else if ( ese->type == EDITVERT ) {
2540                         eve_act = (EditVert *)ese->data;
2541                 }
2542         }
2543         
2544         EM_init_index_arrays(em, 1, 1, 1);
2545
2546         if(dt>OB_WIRE) {
2547                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2548                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2549                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2550
2551                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2552                                         draw_em_fancy__setGLSLFaceOpts, NULL);
2553                                 GPU_disable_material();
2554
2555                                 glFrontFace(GL_CCW);
2556                         }
2557                         else {
2558                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2559                         }
2560                 }
2561                 else {
2562                         /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
2563                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2564
2565                         glEnable(GL_LIGHTING);
2566                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2567
2568                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
2569
2570                         glFrontFace(GL_CCW);
2571                         glDisable(GL_LIGHTING);
2572                 }
2573                         
2574                 // Setup for drawing wire over, disable zbuffer
2575                 // write to show selected edge wires better
2576                 UI_ThemeColor(TH_WIRE);
2577
2578                 bglPolygonOffset(rv3d->dist, 1.0);
2579                 glDepthMask(0);
2580         } 
2581         else {
2582                 if (cageDM!=finalDM) {
2583                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2584                         finalDM->drawEdges(finalDM, 1, 0);
2585                 }
2586         }
2587         
2588         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2589                 unsigned char col1[4], col2[4], col3[4];
2590                         
2591                 UI_GetThemeColor4ubv(TH_FACE, col1);
2592                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2593                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2594                 
2595                 glEnable(GL_BLEND);
2596                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2597                 
2598                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2599                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2600                         col1[3] = 0;
2601                 
2602                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2603
2604                 glDisable(GL_BLEND);
2605                 glDepthMask(1);         // restore write in zbuffer
2606         } else if (efa_act) {
2607                 /* even if draw faces is off it would be nice to draw the stipple face
2608                  * Make all other faces zero alpha except for the active
2609                  * */
2610                 unsigned char col1[4], col2[4], col3[4];
2611                 col1[3] = col2[3] = 0; /* dont draw */
2612                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2613                 
2614                 glEnable(GL_BLEND);
2615                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2616                 
2617                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2618
2619                 glDisable(GL_BLEND);
2620                 glDepthMask(1);         // restore write in zbuffer
2621                 
2622         }
2623
2624         /* here starts all fancy draw-extra over */
2625         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2626                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2627                 
2628                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2629                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2630                 
2631         } else {
2632                 if(me->drawflag & ME_DRAWSEAMS) {
2633                         UI_ThemeColor(TH_EDGE_SEAM);
2634                         glLineWidth(2);
2635         
2636                         draw_dm_edges_seams(cageDM);
2637         
2638                         glColor3ub(0,0,0);
2639                         glLineWidth(1);
2640                 }
2641                 
2642                 if(me->drawflag & ME_DRAWSHARP) {
2643                         UI_ThemeColor(TH_EDGE_SHARP);
2644                         glLineWidth(2);
2645         
2646                         draw_dm_edges_sharp(cageDM);
2647         
2648                         glColor3ub(0,0,0);
2649                         glLineWidth(1);
2650                 }
2651         
2652                 if(me->drawflag & ME_DRAWCREASES) {
2653                         draw_dm_creases(cageDM);
2654                 }
2655                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2656                         draw_dm_bweights(scene, cageDM);
2657                 }
2658         
2659                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2660         }
2661         if(em) {
2662 // XXX          retopo_matrix_update(v3d);
2663
2664                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2665
2666                 if(me->drawflag & ME_DRAWNORMALS) {
2667                         UI_ThemeColor(TH_NORMAL);
2668                         draw_dm_face_normals(scene, cageDM);
2669                 }
2670                 if(me->drawflag & ME_DRAW_VNORMALS) {
2671                         UI_ThemeColor(TH_VNORMAL);
2672                         draw_dm_vert_normals(scene, cageDM);
2673                 }
2674
2675                 if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
2676                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2677         }
2678
2679         if(dt>OB_WIRE) {
2680                 glDepthMask(1);
2681                 bglPolygonOffset(rv3d->dist, 0.0);
2682                 GPU_disable_material();
2683         }
2684
2685         EM_free_index_arrays();
2686 }
2687
2688 /* Mesh drawing routines */
2689
2690 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2691 {
2692         
2693         if(v3d->transp==0) {    // not when we draw the transparent pass
2694                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2695                 glDepthMask(0);
2696                 
2697                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2698                    drawFacesSolid() doesn't draw the transparent faces */
2699                 if(ob->dtx & OB_DRAWTRANSP) {
2700                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2701                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2702                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2703                         GPU_disable_material();
2704                 }
2705                 else {
2706                         dm->drawEdges(dm, 0, 1);
2707                 }
2708                                         
2709                 glLineWidth(1.0);
2710                 glDepthMask(1);
2711         }
2712 }
2713
2714 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
2715 {
2716         *drawSmooth_r = 1;
2717         return 1;
2718 }
2719
2720 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2721 {
2722         Object *ob= base->object;
2723         Mesh *me = ob->data;
2724         Material *ma= give_current_material(ob, 1);
2725         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
2726         const short is_paint_sel= (ob==OBACT && paint_facesel_test(ob));
2727         int draw_wire = 0;
2728         int /* totvert,*/ totedge, totface;
2729         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
2730
2731         if(!dm)
2732                 return;
2733         
2734         if (ob->dtx&OB_DRAWWIRE) {
2735                 draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
2736         }
2737         
2738         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
2739         totedge = dm->getNumEdges(dm);
2740         totface = dm->getNumFaces(dm);
2741         
2742         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
2743         if(dt!=OB_SHADED)
2744                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2745
2746                 // Unwanted combination.
2747         if (is_paint_sel) draw_wire = 0;
2748
2749         if(dt==OB_BOUNDBOX) {
2750                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
2751                         draw_bounding_volume(scene, ob);
2752         }
2753         else if(hasHaloMat || (totface==0 && totedge==0)) {
2754                 glPointSize(1.5);
2755                 dm->drawVerts(dm);
2756                 glPointSize(1.0);
2757         }
2758         else if(dt==OB_WIRE || totface==0) {
2759                 draw_wire = 1; /* draw wire only, no depth buffer stuff  */
2760         }
2761         else if(        (is_paint_sel || (ob==OBACT && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
2762                                 CHECK_OB_DRAWTEXTURE(v3d, dt))
2763         {
2764                 if ((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !(G.f&G_PICKSEL || is_paint_sel) && !draw_wire) {
2765                         draw_mesh_object_outline(v3d, ob, dm);
2766                 }
2767
2768                 if(draw_glsl_material(scene, ob, v3d, dt)) {
2769                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2770
2771                         dm->drawFacesGLSL(dm, GPU_enable_material);
2772 //                      if(get_ob_property(ob, "Text"))
2773 // XXX                          draw_mesh_text(ob, 1);
2774                         GPU_disable_material();
2775
2776                         glFrontFace(GL_CCW);
2777                 }
2778                 else {
2779                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, is_paint_sel);
2780                 }
2781
2782                 if(!is_paint_sel) {
2783                         if(base->flag & SELECT)
2784                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2785                         else
2786                                 UI_ThemeColor(TH_WIRE);
2787
2788                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2789                                 dm->drawLooseEdges(dm);
2790                 }
2791         }
2792         else if(dt==OB_SOLID) {
2793                 if(ob==OBACT && ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2794                         /* weight paint in solid mode, special case. focus on making the weights clear
2795                          * rather than the shading, this is also forced in wire view */
2796                         GPU_enable_material(0, NULL);
2797                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2798                 
2799                         bglPolygonOffset(rv3d->dist, 1.0);
2800                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2801
2802                         glEnable(GL_BLEND);
2803                         glColor4ub(255, 255, 255, 96);
2804                         glEnable(GL_LINE_STIPPLE);
2805                         glLineStipple(1, 0xAAAA);
2806
2807                         dm->drawEdges(dm, 1, 1);
2808
2809                         bglPolygonOffset(rv3d->dist, 0.0);
2810                         glDepthMask(1);
2811                         glDisable(GL_LINE_STIPPLE);
2812
2813                         GPU_disable_material();
2814                         
2815                         /* since we already draw wire as wp guide, dont draw over the top */
2816                         draw_wire= 0;
2817                 }
2818                 else {
2819                         Paint *p;
2820
2821                         if((v3d->flag&V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) && (base->flag&SELECT) && !draw_wire && !ob->sculpt)
2822                                 draw_mesh_object_outline(v3d, ob, dm);
2823
2824                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
2825
2826                         glEnable(GL_LIGHTING);
2827                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2828
2829                         if(ob->sculpt && (p=paint_get_active(scene))) {
2830                                 float planes[4][4];
2831                                 float (*fpl)[4] = NULL;
2832                                 int fast= (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
2833
2834                                 if(ob->sculpt->partial_redraw) {
2835                                         if(ar->do_draw & RGN_DRAW_PARTIAL) {
2836                                                 sculpt_get_redraw_planes(planes, ar, rv3d, ob);
2837                                                 fpl = planes;
2838                                                 ob->sculpt->partial_redraw = 0;
2839                                         }
2840                                 }
2841
2842                                 dm->drawFacesSolid(dm, fpl, fast, GPU_enable_material);
2843                         }
2844                         else
2845                                 dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2846
2847                         GPU_disable_material();
2848
2849                         glFrontFace(GL_CCW);
2850                         glDisable(GL_LIGHTING);
2851
2852                         if(base->flag & SELECT) {
2853                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2854                         } else {
2855                                 UI_ThemeColor(TH_WIRE);
2856                         }
2857                         if(!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
2858                                 dm->drawLooseEdges(dm);
2859                 }
2860         }
2861         else if(dt==OB_SHADED) {
2862                 if(ob==OBACT) {
2863                         if(ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
2864                                 /* enforce default material settings */
2865                                 GPU_enable_material(0, NULL);
2866                                 
2867                                 /* but set default spec */
2868                                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2869                                 glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
2870                                 glColor3ub(120, 120, 120);
2871                                 glDisable(GL_COLOR_MATERIAL);
2872                                 /* diffuse */
2873                                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2874                                 glEnable(GL_LIGHTING);
2875                                 glEnable(GL_COLOR_MATERIAL);
2876
2877                                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
2878                                 glDisable(GL_COLOR_MATERIAL);
2879                                 glDisable(GL_LIGHTING);
2880
2881                                 GPU_disable_material();
2882                         }
2883                         else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
2884                                 if(me->mcol)
2885                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material, NULL);
2886                                 else {
2887                                         glColor3f(1.0f, 1.0f, 1.0f);
2888                                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material, NULL);
2889                                 }
2890                         }
2891                 }
2892         }
2893         
2894         /* set default draw color back for wire or for draw-extra later on */
2895         if (dt!=OB_WIRE) {
2896                 if(base->flag & SELECT) {
2897                         if(ob==OBACT && ob->flag & OB_FROMGROUP) 
2898                                 UI_ThemeColor(TH_GROUP_ACTIVE);
2899                         else if(ob->flag & OB_FROMGROUP) 
2900                                 UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
2901                         else if(flag!=DRAW_CONSTCOLOR)
2902                                 UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
2903                         else
2904                                 glColor3ub(80,80,80);
2905                 } else {
2906                         if (ob->flag & OB_FROMGROUP) 
2907                                 UI_ThemeColor(TH_GROUP);
2908                         else {
2909                                 if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
2910                                         glColor3ub(80,80,80);
2911                                 else
2912                                         UI_ThemeColor(TH_WIRE);
2913                         }
2914                 }
2915         }
2916         if (draw_wire) {
2917
2918                 /* When using wireframe object traw in particle edit mode
2919                  * the mesh gets in the way of seeing the particles, fade the wire color
2920                  * with the background. */
2921                 if(ob==OBACT && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
2922                         float col_wire[4], col_bg[4], col[3];
2923
2924                         UI_GetThemeColor3fv(TH_BACK, col_bg);
2925                         glGetFloatv(GL_CURRENT_COLOR, col_wire);
2926                         interp_v3_v3v3(col, col_bg, col_wire, 0.15);
2927                         glColor3fv(col);
2928                 }
2929
2930                 /* If drawing wire and drawtype is not OB_WIRE then we are
2931                  * overlaying the wires.
2932                  *
2933                  * UPDATE bug #10290 - With this wire-only objects can draw
2934                  * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
2935                  *
2936                  * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
2937                  * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
2938                  */
2939                 if (dt!=OB_WIRE && draw_wire==2) {
2940                         bglPolygonOffset(rv3d->dist, 1.0);
2941                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
2942                 }
2943                 
2944                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_SOLID)==0)
2945                         dm->drawEdges(dm, (dt==OB_WIRE || totface==0), me->drawflag & ME_ALLEDGES);
2946
2947                 if (dt!=OB_WIRE && draw_wire==2) {
2948                         glDepthMask(1);
2949                         bglPolygonOffset(rv3d->dist, 0.0);
2950                 }
2951         }
2952         
2953         if(paint_vertsel_test(ob)) {
2954                 
2955                 glColor3f(0.0f, 0.0f, 0.0f);
2956                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
2957                 
2958                 drawSelectedVertices(dm, ob->data);
2959                 
2960                 glPointSize(1.0f);
2961         }
2962         dm->release(dm);
2963 }
2964
2965 /* returns 1 if nothing was drawn, for detecting to draw an object center */
2966 static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
2967 {
2968         Object *ob= base->object;
2969         Object *obedit= scene->obedit;
2970         Mesh *me= ob->data;
2971         EditMesh *em= me->edit_mesh;
2972         int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
2973
2974         /* If we are drawing shadows and any of the materials don't cast a shadow,
2975          * then don't draw the object */
2976         if (v3d->flag2 & V3D_RENDER_SHADOW) {
2977                 for(i=0; i<ob->totcol; ++i) {
2978                         Material *ma= give_current_material(ob, i);
2979                         if (ma && !(ma->mode & MA_SHADBUF)) {
2980                                 return 1;
2981                         }
2982                 }
2983         }
2984         
2985         if(obedit && ob!=obedit && ob->data==obedit->data) {
2986                 if(ob_get_key(ob) || ob_get_key(obedit));
2987                 else if(ob->modifiers.first || obedit->modifiers.first);
2988                 else drawlinked= 1;
2989         }
2990         
2991         if(ob==obedit || drawlinked) {
2992                 DerivedMesh *finalDM, *cageDM;
2993                 
2994                 if (obedit!=ob)
2995                         finalDM = cageDM = editmesh_get_derived_base(ob, em);
2996                 else
2997                         cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
2998                                                                                         scene->customdata_mask);
2999
3000                 if(dt>OB_WIRE) {
3001                         // no transp in editmode, the fancy draw over goes bad then
3002                         glsl = draw_glsl_material(scene, ob, v3d, dt);
3003                         GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
3004                 }
3005
3006                 draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt);
3007
3008                 GPU_end_object_materials();
3009
3010                 if (obedit!=ob && finalDM)
3011                         finalDM->release(finalDM);
3012         }
3013         else {
3014                 /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
3015                 if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
3016                         glsl = draw_glsl_material(scene, ob, v3d, dt);
3017                         check_alpha = check_material_alpha(base, me, glsl);
3018
3019                         if(dt==OB_SOLID || glsl) {
3020                                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
3021                                         (check_alpha)? &do_alpha_pass: NULL);
3022                         }
3023
3024                         draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag);
3025
3026                         GPU_end_object_materials();
3027                         
3028                         if(me->totvert==0) retval= 1;
3029                 }
3030         }
3031         
3032         /* GPU_begin_object_materials checked if this is needed */
3033         if(do_alpha_pass) {
3034                 if(ob->dtx & OB_DRAWXRAY) {
3035                         add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
3036                 }
3037                 else {
3038                         add_view3d_after(&v3d->afterdraw_transp, base, flag);
3039                 }
3040         }
3041         else if(ob->dtx & OB_DRAWXRAY && ob->dtx & OB_DRAWTRANSP) {
3042                 /* special case xray+transp when alpha is 1.0, without this the object vanishes */
3043                 if(v3d->xray == 0 && v3d->transp == 0) {
3044                         add_view3d_after(&v3d->afterdraw_xray, base, flag);
3045                 }
3046         }
3047         
3048         return retval;
3049 }
3050
3051 /* ************** DRAW DISPLIST ****************** */
3052
3053 static int draw_index_wire= 1;
3054 static int index3_nors_incr= 1;
3055
3056 /* returns 1 when nothing was drawn */
3057 static int drawDispListwire(ListBase *dlbase)
3058 {
3059         DispList *dl;
3060         int parts, nr;
3061         float *data;
3062
3063         if(dlbase==NULL) return 1;
3064         
3065         glEnableClientState(GL_VERTEX_ARRAY);
3066         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
3067
3068         for(dl= dlbase->first; dl; dl= dl->next) {
3069                 if(dl->parts==0 || dl->nr==0)
3070                         continue;
3071                 
3072                 data= dl->verts;
3073         
3074                 switch(dl->type) {
3075                 case DL_SEGM:
3076                         
3077                         glVertexPointer(3, GL_FLOAT, 0, data);
3078                         
3079                         for(parts=0; parts<dl->parts; parts++)
3080                                 glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3081                                 
3082                         break;
3083                 case DL_POLY:
3084                         
3085                         glVertexPointer(3, GL_FLOAT, 0, data);
3086                         
3087                         for(parts=0; parts<dl->parts; parts++)
3088                                 glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3089                         
3090                         break;
3091                 case DL_SURF:
3092                         
3093                         glVertexPointer(3, GL_FLOAT, 0, data);
3094                         
3095                         for(parts=0; parts<dl->parts; parts++) {
3096                                 if(dl->flag & DL_CYCL_U) 
3097                                         glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
3098                                 else
3099                                         glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
3100                         }
3101                    &nb