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