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