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