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