Object tracking: various fixes and improvements
[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_alpha_pass(Base *base)
269 {
270         if(base->flag & OB_FROMDUPLI)
271                 return 0;
272
273         if(G.f & G_PICKSEL)
274                 return 0;
275         
276         return (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_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
1462                         MovieClip *clip, MovieTrackingObject *tracking_object, int flag, int *global_track_index)
1463 {
1464         MovieTracking *tracking= &clip->tracking;
1465         MovieTrackingTrack *track;
1466         float mat[4][4], imat[4][4];
1467         unsigned char col[4], scol[4];
1468         int tracknr= *global_track_index;
1469         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
1470
1471         UI_GetThemeColor4ubv(TH_TEXT, col);
1472         UI_GetThemeColor4ubv(TH_SELECT, scol);
1473
1474         BKE_get_tracking_mat(scene, base->object, mat);
1475
1476         glPushMatrix();
1477
1478         if(tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1479                 /* current ogl matrix is translated in camera space, bundles should
1480                    be rendered in world space, so camera matrix should be "removed"
1481                    from current ogl matrix */
1482                 invert_m4_m4(imat, base->object->obmat);
1483
1484                 glMultMatrixf(imat);
1485                 glMultMatrixf(mat);
1486         }
1487         else {
1488                 float obmat[4][4];
1489
1490                 BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
1491
1492                 invert_m4_m4(imat, obmat);
1493                 glMultMatrixf(imat);
1494         }
1495
1496         for (track= tracksbase->first; track; track= track->next) {
1497                 int selected= TRACK_SELECTED(track);
1498
1499                 if((track->flag&TRACK_HAS_BUNDLE)==0)
1500                         continue;
1501
1502                 if(flag&DRAW_PICKING)
1503                         glLoadName(base->selcol + (tracknr<<16));
1504
1505                 glPushMatrix();
1506                         glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
1507                         glScalef(v3d->bundle_size/0.05f, v3d->bundle_size/0.05f, v3d->bundle_size/0.05f);
1508
1509                         if(v3d->drawtype==OB_WIRE) {
1510                                 glDisable(GL_LIGHTING);
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                                 glEnable(GL_LIGHTING);
1523                         } else if(v3d->drawtype>OB_WIRE) {
1524                                 if(v3d->bundle_drawtype==OB_EMPTY_SPHERE) {
1525                                         /* selection outline */
1526                                         if(selected) {
1527                                                 if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1528                                                 else UI_ThemeColor(TH_SELECT);
1529
1530                                                 glLineWidth(2.f);
1531                                                 glDisable(GL_LIGHTING);
1532                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1533
1534                                                 draw_bundle_sphere();
1535
1536                                                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1537                                                 glEnable(GL_LIGHTING);
1538                                                 glLineWidth(1.f);
1539                                         }
1540
1541                                         if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1542                                         else UI_ThemeColor(TH_BUNDLE_SOLID);
1543
1544                                         draw_bundle_sphere();
1545                                 } else {
1546                                         glDisable(GL_LIGHTING);
1547
1548                                         if(selected) {
1549                                                 if(base==BASACT) UI_ThemeColor(TH_ACTIVE);
1550                                                 else UI_ThemeColor(TH_SELECT);
1551                                         } else {
1552                                                 if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color);
1553                                                 else UI_ThemeColor(TH_WIRE);
1554                                         }
1555
1556                                         drawaxes(0.05f, v3d->bundle_drawtype);
1557
1558                                         glEnable(GL_LIGHTING);
1559                                 }
1560                         }
1561
1562                 glPopMatrix();
1563
1564                 if((flag & DRAW_PICKING)==0 && (v3d->flag2&V3D_SHOW_BUNDLENAME)) {
1565                         float pos[3];
1566                         unsigned char tcol[4];
1567
1568                         if(selected) memcpy(tcol, scol, sizeof(tcol));
1569                         else memcpy(tcol, col, sizeof(tcol));
1570
1571                         mul_v3_m4v3(pos, mat, track->bundle_pos);
1572                         view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol);
1573                 }
1574
1575                 tracknr++;
1576         }
1577
1578         if((flag & DRAW_PICKING)==0) {
1579                 if((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) {
1580                         MovieTrackingReconstruction *reconstruction;
1581                         reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object);
1582
1583                         if(reconstruction->camnr) {
1584                                 MovieReconstructedCamera *camera= reconstruction->cameras;
1585                                 int a= 0;
1586
1587                                 glDisable(GL_LIGHTING);
1588                                 UI_ThemeColor(TH_CAMERA_PATH);
1589                                 glLineWidth(2.0f);
1590
1591                                 glBegin(GL_LINE_STRIP);
1592                                         for(a= 0; a<reconstruction->camnr; a++, camera++) {
1593                                                 glVertex3fv(camera->mat[3]);
1594                                         }
1595                                         glEnd();
1596
1597                                         glLineWidth(1.0f);
1598                                         glEnable(GL_LIGHTING);
1599                         }
1600                 }
1601         }
1602
1603         glPopMatrix();
1604
1605         *global_track_index= tracknr;
1606 }
1607
1608 static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag)
1609 {
1610         MovieTracking *tracking= &clip->tracking;
1611         MovieTrackingObject *tracking_object;
1612         float curcol[4];
1613         int global_track_index= 1;
1614
1615         if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
1616                 return;
1617
1618         if(v3d->flag2&V3D_RENDER_OVERRIDE)
1619                 return;
1620
1621         glGetFloatv(GL_CURRENT_COLOR, curcol);
1622
1623         glEnable(GL_LIGHTING);
1624         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1625         glEnable(GL_COLOR_MATERIAL);
1626         glShadeModel(GL_SMOOTH);
1627
1628         tracking_object= tracking->objects.first;
1629         while(tracking_object) {
1630                 draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object,
1631                                         flag, &global_track_index);
1632
1633                 tracking_object= tracking_object->next;
1634         }
1635
1636         /* restore */
1637         glShadeModel(GL_FLAT);
1638         glDisable(GL_COLOR_MATERIAL);
1639         glDisable(GL_LIGHTING);
1640
1641         glColor4fv(curcol);
1642
1643         if(flag&DRAW_PICKING)
1644                 glLoadName(base->selcol);
1645 }
1646
1647 /* flag similar to draw_object() */
1648 static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int flag)
1649 {
1650         /* a standing up pyramid with (0,0,0) as top */
1651         Camera *cam;
1652         Object *ob= base->object;
1653         float tvec[3];
1654         float vec[4][3], asp[2], shift[2], scale[3];
1655         int i;
1656         float drawsize;
1657         const short is_view= (rv3d->persp==RV3D_CAMOB && ob==v3d->camera);
1658         MovieClip *clip= object_get_movieclip(scene, base->object, 0);
1659
1660         /* draw data for movie clip set as active for scene */
1661         if(clip)
1662                 draw_viewport_reconstruction(scene, base, v3d, clip, flag);
1663
1664 #ifdef VIEW3D_CAMERA_BORDER_HACK
1665         if(is_view && !(G.f & G_PICKSEL)) {
1666                 glGetFloatv(GL_CURRENT_COLOR, view3d_camera_border_hack_col);
1667                 view3d_camera_border_hack_test= TRUE;
1668                 return;
1669         }
1670 #endif
1671
1672         cam= ob->data;
1673
1674         scale[0]= 1.0f / len_v3(ob->obmat[0]);
1675         scale[1]= 1.0f / len_v3(ob->obmat[1]);
1676         scale[2]= 1.0f / len_v3(ob->obmat[2]);
1677
1678         camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
1679                              asp, shift, &drawsize, vec);
1680
1681         glDisable(GL_LIGHTING);
1682         glDisable(GL_CULL_FACE);
1683
1684         /* camera frame */
1685         glBegin(GL_LINE_LOOP);
1686         glVertex3fv(vec[0]);
1687         glVertex3fv(vec[1]);
1688         glVertex3fv(vec[2]);
1689         glVertex3fv(vec[3]);
1690         glEnd();
1691
1692         if(is_view)
1693                 return;
1694
1695         zero_v3(tvec);
1696
1697         /* center point to camera frame */
1698         glBegin(GL_LINE_STRIP);
1699         glVertex3fv(vec[1]);
1700         glVertex3fv(tvec);
1701         glVertex3fv(vec[0]);
1702         glVertex3fv(vec[3]);
1703         glVertex3fv(tvec);
1704         glVertex3fv(vec[2]);
1705         glEnd();
1706
1707
1708         /* arrow on top */
1709         tvec[2]= vec[1][2]; /* copy the depth */
1710
1711
1712         /* draw an outline arrow for inactive cameras and filled
1713          * for active cameras. We actually draw both outline+filled
1714          * for active cameras so the wire can be seen side-on */        
1715         for (i=0;i<2;i++) {
1716                 if (i==0) glBegin(GL_LINE_LOOP);
1717                 else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
1718                 else break;
1719
1720                 tvec[0]= shift[0] + ((-0.7f * drawsize) * scale[0]);
1721                 tvec[1]= shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
1722                 glVertex3fv(tvec); /* left */
1723                 
1724                 tvec[0]= shift[0] + ((0.7f * drawsize) * scale[0]);
1725                 glVertex3fv(tvec); /* right */
1726                 
1727                 tvec[0]= shift[0];
1728                 tvec[1]= shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
1729                 glVertex3fv(tvec); /* top */
1730         
1731                 glEnd();
1732         }
1733
1734         if(flag==0) {
1735                 if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
1736                         float nobmat[4][4];
1737                         World *wrld;
1738         
1739                         /* draw in normalized object matrix space */
1740                         copy_m4_m4(nobmat, ob->obmat);
1741                         normalize_m4(nobmat);
1742
1743                         glPushMatrix();
1744                         glLoadMatrixf(rv3d->viewmat);
1745                         glMultMatrixf(nobmat);
1746
1747                         if(cam->flag & CAM_SHOWLIMITS) {
1748                                 draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
1749                                 /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
1750                                 draw_focus_cross(object_camera_dof_distance(ob), cam->drawsize);
1751                         }
1752
1753                         wrld= scene->world;
1754                         if(cam->flag & CAM_SHOWMIST) 
1755                                 if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
1756                                 
1757                         glPopMatrix();
1758                 }
1759         }
1760 }
1761
1762 /* flag similar to draw_object() */
1763 static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
1764                         Object *UNUSED(ob), int UNUSED(flag))
1765 {
1766         //Speaker *spk = ob->data;
1767
1768         float vec[3];
1769         int i, j;
1770
1771         glEnable(GL_BLEND);
1772
1773         for(j = 0; j < 3; j++) {
1774                 vec[2] = 0.25f * j -0.125f;
1775
1776                 glBegin(GL_LINE_LOOP);
1777                 for(i = 0; i < 16; i++) {
1778                         vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1779                         vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
1780                         glVertex3fv(vec);
1781                 }
1782                 glEnd();
1783         }
1784
1785         for(j = 0; j < 4; j++) {
1786                 vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
1787                 vec[1] = ((j % 2) * (j - 2)) * 0.5f;
1788                 glBegin(GL_LINE_STRIP);
1789                 for(i = 0; i < 3; i++) {
1790                         if(i == 1) {
1791                                 vec[0] *= 0.5f;
1792                                 vec[1] *= 0.5f;
1793                         }
1794
1795                         vec[2] = 0.25f * i -0.125f;
1796                         glVertex3fv(vec);
1797                 }
1798                 glEnd();
1799         }
1800
1801         glDisable(GL_BLEND);
1802 }
1803
1804 static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
1805 {
1806         BPoint *bp = lt->def;
1807         float *co = dl?dl->verts:NULL;
1808         int u, v, w;
1809
1810         UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
1811         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1812         bglBegin(GL_POINTS);
1813
1814         for(w=0; w<lt->pntsw; w++) {
1815                 int wxt = (w==0 || w==lt->pntsw-1);
1816                 for(v=0; v<lt->pntsv; v++) {
1817                         int vxt = (v==0 || v==lt->pntsv-1);
1818                         for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
1819                                 int uxt = (u==0 || u==lt->pntsu-1);
1820                                 if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
1821                                         if(bp->hide==0) {
1822                                                 if((bp->f1 & SELECT)==sel) {
1823                                                         bglVertex3fv(dl?co:bp->vec);
1824                                                 }
1825                                         }
1826                                 }
1827                         }
1828                 }
1829         }
1830         
1831         glPointSize(1.0);
1832         bglEnd();       
1833 }
1834
1835 void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
1836 {
1837         Object *obedit= vc->obedit;
1838         Lattice *lt= obedit->data;
1839         BPoint *bp = lt->editlatt->latt->def;
1840         DispList *dl = find_displist(&obedit->disp, DL_VERTS);
1841         float *co = dl?dl->verts:NULL;
1842         int i, N = lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
1843         short s[2] = {IS_CLIPPED, 0};
1844
1845         ED_view3d_local_clipping(vc->rv3d, obedit->obmat); /* for local clipping lookups */
1846
1847         for (i=0; i<N; i++, bp++, co+=3) {
1848                 if (bp->hide==0) {
1849                         view3d_project_short_clip(vc->ar, dl?co:bp->vec, s, 1);
1850                         if (s[0] != IS_CLIPPED)
1851                                 func(userData, bp, s[0], s[1]);
1852                 }
1853         }
1854 }
1855
1856 static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
1857 {
1858         int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
1859
1860         if(use_wcol) {
1861                 float col[3];
1862                 MDeformWeight *mdw= defvert_find_index (lt->dvert+index, use_wcol-1);
1863                 
1864                 weight_to_rgb(col, mdw?mdw->weight:0.0f);
1865                 glColor3fv(col);
1866
1867         }
1868         
1869         if (dl) {
1870                 glVertex3fv(&dl->verts[index*3]);
1871         } else {
1872                 glVertex3fv(lt->def[index].vec);
1873         }
1874 }
1875
1876 /* lattice color is hardcoded, now also shows weightgroup values in edit mode */
1877 static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
1878 {
1879         Lattice *lt= ob->data;
1880         DispList *dl;
1881         int u, v, w;
1882         int use_wcol= 0, is_edit= (lt->editlatt != NULL);
1883
1884         /* now we default make displist, this will modifiers work for non animated case */
1885         if(ob->disp.first==NULL)
1886                 lattice_calc_modifiers(scene, ob);
1887         dl= find_displist(&ob->disp, DL_VERTS);
1888         
1889         if(is_edit) {
1890                 lt= lt->editlatt->latt;
1891
1892                 cpack(0x004000);
1893                 
1894                 if(ob->defbase.first && lt->dvert) {
1895                         use_wcol= ob->actdef;
1896                         glShadeModel(GL_SMOOTH);
1897                 }
1898         }
1899         
1900         glBegin(GL_LINES);
1901         for(w=0; w<lt->pntsw; w++) {
1902                 int wxt = (w==0 || w==lt->pntsw-1);
1903                 for(v=0; v<lt->pntsv; v++) {
1904                         int vxt = (v==0 || v==lt->pntsv-1);
1905                         for(u=0; u<lt->pntsu; u++) {
1906                                 int uxt = (u==0 || u==lt->pntsu-1);
1907
1908                                 if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
1909                                         drawlattice__point(lt, dl, u, v, w-1, use_wcol);
1910                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1911                                 }
1912                                 if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1913                                         drawlattice__point(lt, dl, u, v-1, w, use_wcol);
1914                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1915                                 }
1916                                 if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
1917                                         drawlattice__point(lt, dl, u-1, v, w, use_wcol);
1918                                         drawlattice__point(lt, dl, u, v, w, use_wcol);
1919                                 }
1920                         }
1921                 }
1922         }               
1923         glEnd();
1924         
1925         /* restoration for weight colors */
1926         if(use_wcol)
1927                 glShadeModel(GL_FLAT);
1928
1929         if(is_edit) {
1930                 if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1931                 
1932                 lattice_draw_verts(lt, dl, 0);
1933                 lattice_draw_verts(lt, dl, 1);
1934                 
1935                 if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
1936         }
1937 }
1938
1939 /* ***************** ******************** */
1940
1941 /* Note! - foreach funcs should be called while drawing or directly after
1942  * if not, ED_view3d_init_mats_rv3d() can be used for selection tools
1943  * but would not give correct results with dupli's for eg. which dont
1944  * use the object matrix in the useual way */
1945 static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1946 {
1947         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index);
1948                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } *data = userData;
1949
1950         EditVert *eve = EM_get_vert_for_index(index);
1951
1952         if (eve->h==0) {
1953                 short s[2]= {IS_CLIPPED, 0};
1954
1955                 if (data->clipVerts != V3D_CLIP_TEST_OFF) {
1956                         view3d_project_short_clip(data->vc.ar, co, s, 1);
1957                 } else {
1958                         view3d_project_short_noclip(data->vc.ar, co, s);
1959                 }
1960
1961                 if (s[0]!=IS_CLIPPED)
1962                         data->func(data->userData, eve, s[0], s[1], index);
1963         }
1964 }
1965
1966 void mesh_foreachScreenVert(
1967         ViewContext *vc,
1968         void (*func)(void *userData, EditVert *eve, int x, int y, int index),
1969         void *userData, eV3DClipTest clipVerts)
1970 {
1971         struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index);
1972                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } data;
1973
1974         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
1975         
1976         data.vc= *vc;
1977         data.func = func;
1978         data.userData = userData;
1979         data.clipVerts = clipVerts;
1980
1981         if(clipVerts != V3D_CLIP_TEST_OFF)
1982                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
1983
1984         EM_init_index_arrays(vc->em, 1, 0, 0);
1985         dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
1986         EM_free_index_arrays();
1987
1988         dm->release(dm);
1989 }
1990
1991 /*  draw callback */
1992 static void drawSelectedVertices__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
1993 {
1994         MVert *mv = &((MVert *)userData)[index];
1995
1996         if(!(mv->flag & ME_HIDE)) {
1997                 const char sel= mv->flag & SELECT;
1998
1999                 // TODO define selected color
2000                 if(sel) {
2001                         glColor3f(1.0f, 1.0f, 0.0f);
2002                 }
2003                 else {
2004                         glColor3f(0.0f, 0.0f, 0.0f);
2005                 }
2006
2007                 glVertex3fv(co);
2008         }
2009 }
2010
2011 static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
2012 {
2013         glBegin(GL_POINTS);
2014         dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, me->mvert);
2015         glEnd();
2016 }
2017 static int is_co_in_region(ARegion *ar, const short co[2])
2018 {
2019         return ( (co[0] != IS_CLIPPED) && /* may be the only initialized value, check first */
2020                  (co[0] >= 0)          &&
2021                  (co[0] <  ar->winx)   &&
2022                  (co[1] >= 0)          &&
2023                  (co[1] <  ar->winy));
2024 }
2025 static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
2026 {
2027         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
2028                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } *data = userData;
2029         EditEdge *eed = EM_get_edge_for_index(index);
2030         short s[2][2];
2031
2032         if (eed->h==0) {
2033                 if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) {
2034                         view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
2035                         view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
2036                 }
2037                 else {
2038                         view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
2039                         view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
2040
2041                         if (data->clipVerts == V3D_CLIP_TEST_REGION) {
2042                                 if ( !is_co_in_region(data->vc.ar, s[0]) &&
2043                                      !is_co_in_region(data->vc.ar, s[1]))
2044                                 {
2045                                         return;
2046                                 }
2047                         }
2048                 }
2049
2050                 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
2051         }
2052 }
2053
2054 void mesh_foreachScreenEdge(
2055         ViewContext *vc,
2056         void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index),
2057         void *userData, eV3DClipTest clipVerts)
2058 {
2059         struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index);
2060                      void *userData; ViewContext vc; eV3DClipTest clipVerts; } data;
2061         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2062
2063         data.vc= *vc;
2064         data.func = func;
2065         data.userData = userData;
2066         data.clipVerts = clipVerts;
2067
2068         if(clipVerts != V3D_CLIP_TEST_OFF)
2069                 ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2070
2071         EM_init_index_arrays(vc->em, 0, 1, 0);
2072         dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
2073         EM_free_index_arrays();
2074
2075         dm->release(dm);
2076 }
2077
2078 static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2079 {
2080         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
2081         EditFace *efa = EM_get_face_for_index(index);
2082         short s[2];
2083
2084         if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
2085                 view3d_project_short_clip(data->vc.ar, cent, s, 1);
2086
2087                 if (s[0] != IS_CLIPPED) {
2088                         data->func(data->userData, efa, s[0], s[1], index);
2089                 }
2090         }
2091 }
2092
2093 void mesh_foreachScreenFace(
2094         ViewContext *vc,
2095         void (*func)(void *userData, EditFace *efa, int x, int y, int index),
2096         void *userData)
2097 {
2098         struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
2099         DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
2100
2101         data.vc= *vc;
2102         data.func = func;
2103         data.userData = userData;
2104
2105         //if(clipVerts)
2106         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2107
2108         EM_init_index_arrays(vc->em, 0, 0, 1);
2109         dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
2110         EM_free_index_arrays();
2111
2112         dm->release(dm);
2113 }
2114
2115 void nurbs_foreachScreenVert(
2116         ViewContext *vc,
2117         void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y),
2118         void *userData)
2119 {
2120         Curve *cu= vc->obedit->data;
2121         short s[2] = {IS_CLIPPED, 0};
2122         Nurb *nu;
2123         int i;
2124         ListBase *nurbs= curve_editnurbs(cu);
2125
2126         ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
2127
2128         for (nu= nurbs->first; nu; nu=nu->next) {
2129                 if(nu->type == CU_BEZIER) {
2130                         for (i=0; i<nu->pntsu; i++) {
2131                                 BezTriple *bezt = &nu->bezt[i];
2132
2133                                 if(bezt->hide==0) {
2134                                         
2135                                         if(cu->drawflag & CU_HIDE_HANDLES) {
2136                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2137                                                 if (s[0] != IS_CLIPPED)
2138                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2139                                         } else {
2140                                                 view3d_project_short_clip(vc->ar, bezt->vec[0], s, 1);
2141                                                 if (s[0] != IS_CLIPPED)
2142                                                         func(userData, nu, NULL, bezt, 0, s[0], s[1]);
2143                                                 view3d_project_short_clip(vc->ar, bezt->vec[1], s, 1);
2144                                                 if (s[0] != IS_CLIPPED)
2145                                                         func(userData, nu, NULL, bezt, 1, s[0], s[1]);
2146                                                 view3d_project_short_clip(vc->ar, bezt->vec[2], s, 1);
2147                                                 if (s[0] != IS_CLIPPED)
2148                                                         func(userData, nu, NULL, bezt, 2, s[0], s[1]);
2149                                         }
2150                                 }
2151                         }
2152                 }
2153                 else {
2154                         for (i=0; i<nu->pntsu*nu->pntsv; i++) {
2155                                 BPoint *bp = &nu->bp[i];
2156
2157                                 if(bp->hide==0) {
2158                                         view3d_project_short_clip(vc->ar, bp->vec, s, 1);
2159                                         if (s[0] != IS_CLIPPED)
2160                                                 func(userData, nu, bp, NULL, -1, s[0], s[1]);
2161                                 }
2162                         }
2163                 }
2164         }
2165 }
2166
2167 /* ************** DRAW MESH ****************** */
2168
2169 /* First section is all the "simple" draw routines, 
2170  * ones that just pass some sort of primitive to GL,
2171  * with perhaps various options to control lighting,
2172  * color, etc.
2173  *
2174  * These routines should not have user interface related
2175  * logic!!!
2176  */
2177
2178 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
2179 {
2180         ToolSettings *ts= ((Scene *)userData)->toolsettings;
2181         EditFace *efa = EM_get_face_for_index(index);
2182
2183         if (efa->h==0 && efa->fgonf!=EM_FGON) {
2184                 glVertex3fv(cent);
2185                 glVertex3f(     cent[0] + no[0]*ts->normalsize,
2186                                         cent[1] + no[1]*ts->normalsize,
2187                                         cent[2] + no[2]*ts->normalsize);
2188         }
2189 }
2190 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
2191 {
2192         glBegin(GL_LINES);
2193         dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
2194         glEnd();
2195 }
2196
2197 static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
2198 {
2199         EditFace *efa = EM_get_face_for_index(index);
2200         int sel = *((int*) userData);
2201
2202         if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
2203                 bglVertex3fv(cent);
2204         }
2205 }
2206 static void draw_dm_face_centers(DerivedMesh *dm, int sel)
2207 {
2208         bglBegin(GL_POINTS);
2209         dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
2210         bglEnd();
2211 }
2212
2213 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2214 {
2215         Scene *scene= (Scene *)userData;
2216         ToolSettings *ts= scene->toolsettings;
2217         EditVert *eve = EM_get_vert_for_index(index);
2218
2219         if (eve->h==0) {
2220                 glVertex3fv(co);
2221
2222                 if (no_f) {
2223                         glVertex3f(     co[0] + no_f[0]*ts->normalsize,
2224                                                 co[1] + no_f[1]*ts->normalsize,
2225                                                 co[2] + no_f[2]*ts->normalsize);
2226                 } else {
2227                         glVertex3f(     co[0] + no_s[0]*ts->normalsize/32767.0f,
2228                                                 co[1] + no_s[1]*ts->normalsize/32767.0f,
2229                                                 co[2] + no_s[2]*ts->normalsize/32767.0f);
2230                 }
2231         }
2232 }
2233 static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
2234 {
2235         glBegin(GL_LINES);
2236         dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
2237         glEnd();
2238 }
2239
2240         /* Draw verts with color set based on selection */
2241 static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2242 {
2243         struct { int sel; EditVert *eve_act; } * data = userData;
2244         EditVert *eve = EM_get_vert_for_index(index);
2245
2246         if (eve->h==0 && (eve->f&SELECT)==data->sel) {
2247                 /* draw active larger - need to stop/start point drawing for this :/ */
2248                 if (eve==data->eve_act) {
2249                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2250                         UI_ThemeColor4(TH_EDITMESH_ACTIVE);
2251                         
2252                         bglEnd();
2253                         
2254                         glPointSize(size);
2255                         bglBegin(GL_POINTS);
2256                         bglVertex3fv(co);
2257                         bglEnd();
2258                         
2259                         UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
2260                         glPointSize(size);
2261                         bglBegin(GL_POINTS);
2262                 } else {
2263                         bglVertex3fv(co);
2264                 }
2265         }
2266 }
2267
2268 static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
2269 {
2270         struct { int sel; EditVert *eve_act; } data;
2271         data.sel = sel;
2272         data.eve_act = eve_act;
2273
2274         bglBegin(GL_POINTS);
2275         dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
2276         bglEnd();
2277 }
2278
2279         /* Draw edges with color set based on selection */
2280 static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
2281 {
2282         EditEdge *eed = EM_get_edge_for_index(index);
2283         //unsigned char **cols = userData, *col;
2284         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
2285         unsigned char *col;
2286
2287         if (eed->h==0) {
2288                 if (eed==data->eed_act) {
2289                         glColor4ubv(data->actCol);
2290                 } else {
2291                         if (eed->f&SELECT) {
2292                                 col = data->selCol;
2293                         } else {
2294                                 col = data->baseCol;
2295                         }
2296                         /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
2297                         if (col[3]==0) return 0;
2298                         
2299                         glColor4ubv(col);
2300                 }
2301                 return 1;
2302         } else {
2303                 return 0;
2304         }
2305 }
2306 static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
2307 {
2308         struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
2309         
2310         data.baseCol = baseCol;
2311         data.selCol = selCol;
2312         data.actCol = actCol;
2313         data.eed_act = eed_act;
2314         dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
2315 }
2316
2317         /* Draw edges */
2318 static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
2319 {
2320         return EM_get_edge_for_index(index)->h==0;
2321 }
2322 static void draw_dm_edges(DerivedMesh *dm) 
2323 {
2324         dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
2325 }
2326
2327         /* Draw edges with color interpolated based on selection */
2328 static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
2329 {
2330         return EM_get_edge_for_index(index)->h==0;
2331 }
2332 static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
2333 {
2334         EditEdge *eed = EM_get_edge_for_index(index);
2335         unsigned char **cols = userData;
2336         unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
2337         unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
2338
2339         glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
2340                                 col0[1] + (col1[1]-col0[1])*t,
2341                                 col0[2] + (col1[2]-col0[2])*t,
2342                                 col0[3] + (col1[3]-col0[3])*t);
2343 }
2344
2345 static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
2346 {
2347         unsigned char *cols[2];
2348         cols[0]= baseCol;
2349         cols[1]= selCol;
2350         dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
2351 }
2352
2353         /* Draw only seam edges */
2354 static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
2355 {
2356         EditEdge *eed = EM_get_edge_for_index(index);
2357
2358         return (eed->h==0 && eed->seam);
2359 }
2360 static void draw_dm_edges_seams(DerivedMesh *dm)
2361 {
2362         dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
2363 }
2364
2365         /* Draw only sharp edges */
2366 static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
2367 {
2368         EditEdge *eed = EM_get_edge_for_index(index);
2369
2370         return (eed->h==0 && eed->sharp);
2371 }
2372 static void draw_dm_edges_sharp(DerivedMesh *dm)
2373 {
2374         dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
2375 }
2376
2377
2378         /* Draw faces with color set based on selection
2379          * return 2 for the active face so it renders with stipple enabled */
2380 static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
2381 {
2382         struct { unsigned char *cols[3]; EditFace *efa_act; int *orig_index; } * data = userData;
2383         EditFace *efa = EM_get_face_for_index(index);
2384         unsigned char *col;
2385         
2386         if (efa->h==0) {
2387                 if (efa == data->efa_act) {
2388                         glColor4ubv(data->cols[2]);
2389                         return 2; /* stipple */
2390                 } else {
2391                         col = data->cols[(efa->f&SELECT)?1:0];
2392                         if (col[3]==0) return 0;
2393                         glColor4ubv(col);
2394                         return 1;
2395                 }
2396         }
2397         return 0;
2398 }
2399
2400 static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
2401 {
2402         struct { unsigned char *cols[3]; EditFace *efa_act; int *orig_index; } *data = userData;
2403         EditFace *efa;
2404         EditFace *next_efa;
2405         unsigned char *col, *next_col;
2406
2407         if(!data->orig_index)
2408                 return 0;
2409
2410         efa= EM_get_face_for_index(data->orig_index[index]);
2411         next_efa= EM_get_face_for_index(data->orig_index[next_index]);
2412
2413         if(efa == next_efa)
2414                 return 1;
2415
2416         if(efa == data->efa_act || next_efa == data->efa_act)
2417                 return 0;
2418
2419         col = data->cols[(efa->f&SELECT)?1:0];
2420         next_col = data->cols[(next_efa->f&SELECT)?1:0];
2421
2422         if(col[3]==0 || next_col[3]==0)
2423                 return 0;
2424
2425         return col == next_col;
2426 }
2427
2428 /* also draws the active face */
2429 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
2430 {
2431         struct { unsigned char *cols[3]; EditFace *efa_act; int *orig_index; } data;
2432         data.cols[0] = baseCol;
2433         data.cols[1] = selCol;
2434         data.cols[2] = actCol;
2435         data.efa_act = efa_act;
2436         data.orig_index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
2437
2438         dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0);
2439 }
2440
2441 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
2442 {
2443         EditEdge *eed = EM_get_edge_for_index(index);
2444
2445         if (eed->h==0 && eed->crease != 0.0f) {
2446                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
2447                 return 1;
2448         } else {
2449                 return 0;
2450         }
2451 }
2452 static void draw_dm_creases(DerivedMesh *dm)
2453 {
2454         glLineWidth(3.0);
2455         dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
2456         glLineWidth(1.0);
2457 }
2458
2459 static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
2460 {
2461         EditEdge *eed = EM_get_edge_for_index(index);
2462
2463         if (eed->h==0 && eed->bweight != 0.0f) {
2464                 UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
2465                 return 1;
2466         } else {
2467                 return 0;
2468         }
2469 }
2470 static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2471 {
2472         EditVert *eve = EM_get_vert_for_index(index);
2473
2474         if (eve->h==0 && eve->bweight != 0.0f) {
2475                 UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
2476                 bglVertex3fv(co);
2477         }
2478 }
2479 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
2480 {
2481         ToolSettings *ts= scene->toolsettings;
2482
2483         if (ts->selectmode & SCE_SELECT_VERTEX) {
2484                 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
2485                 bglBegin(GL_POINTS);
2486                 dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
2487                 bglEnd();
2488         }
2489         else {
2490                 glLineWidth(3.0);
2491                 dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
2492                 glLineWidth(1.0);
2493         }
2494 }
2495
2496 /* Second section of routines: Combine first sets to form fancy
2497  * drawing routines (for example rendering twice to get overlays).
2498  *
2499  * Also includes routines that are basic drawing but are too
2500  * specialized to be split out (like drawing creases or measurements).
2501  */
2502
2503 /* EditMesh drawing routines*/
2504
2505 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
2506                                 DerivedMesh *cageDM, EditVert *eve_act)
2507 {
2508         ToolSettings *ts= scene->toolsettings;
2509         int sel;
2510
2511         if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
2512
2513         for (sel=0; sel<2; sel++) {
2514                 unsigned char col[4], fcol[4];
2515                 int pass;
2516
2517                 UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
2518                 UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
2519
2520                 for (pass=0; pass<2; pass++) {
2521                         float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
2522                         float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
2523
2524                         if (pass==0) {
2525                                 if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
2526                                         glDisable(GL_DEPTH_TEST);
2527                                                 
2528                                         glEnable(GL_BLEND);
2529                                 } else {
2530                                         continue;
2531                                 }
2532
2533                                 size = (size > 2.1f ? size/2.0f:size);
2534                                 fsize = (fsize > 2.1f ? fsize/2.0f:fsize);
2535                                 col[3] = fcol[3] = 100;
2536                         } else {
2537                                 col[3] = fcol[3] = 255;
2538                         }
2539                                 
2540                         if(ts->selectmode & SCE_SELECT_VERTEX) {
2541                                 glPointSize(size);
2542                                 glColor4ubv(col);
2543                                 draw_dm_verts(cageDM, sel, eve_act);
2544                         }
2545                         
2546                         if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
2547                                 glPointSize(fsize);
2548                                 glColor4ubv(fcol);
2549                                 draw_dm_face_centers(cageDM, sel);
2550                         }
2551                         
2552                         if (pass==0) {
2553                                 glDisable(GL_BLEND);
2554                                 glEnable(GL_DEPTH_TEST);
2555                         }
2556                 }
2557         }
2558
2559         if(v3d->zbuf) glDepthMask(1);
2560         glPointSize(1.0);
2561 }
2562
2563 static void draw_em_fancy_edges(Scene *scene, View3D *v3d,
2564                                 Mesh *me, DerivedMesh *cageDM, short sel_only,
2565                                 EditEdge *eed_act)
2566 {
2567         ToolSettings *ts= scene->toolsettings;
2568         int pass;
2569         unsigned char wireCol[4], selCol[4], actCol[4];
2570
2571         /* since this function does transparant... */
2572         UI_GetThemeColor4ubv(TH_EDGE_SELECT, selCol);
2573         UI_GetThemeColor4ubv(TH_WIRE, wireCol);
2574         UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, actCol);
2575         
2576         /* when sel only is used, dont render wire, only selected, this is used for
2577          * textured draw mode when the 'edges' option is disabled */
2578         if (sel_only)
2579                 wireCol[3] = 0;
2580
2581         for (pass=0; pass<2; pass++) {
2582                         /* show wires in transparant when no zbuf clipping for select */
2583                 if (pass==0) {
2584                         if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
2585                                 glEnable(GL_BLEND);
2586                                 glDisable(GL_DEPTH_TEST);
2587                                 selCol[3] = 85;
2588                                 if (!sel_only) wireCol[3] = 85;
2589                         } else {
2590                                 continue;
2591                         }
2592                 } else {
2593                         selCol[3] = 255;
2594                         if (!sel_only) wireCol[3] = 255;
2595                 }
2596
2597                 if(ts->selectmode == SCE_SELECT_FACE) {
2598                         draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2599                 }       
2600                 else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
2601                         if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
2602                                 glShadeModel(GL_SMOOTH);
2603                                 draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
2604                                 glShadeModel(GL_FLAT);
2605                         } else {
2606                                 draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
2607                         }
2608                 }
2609                 else {
2610                         if (!sel_only) {
2611                                 glColor4ubv(wireCol);
2612                                 draw_dm_edges(cageDM);
2613                         }
2614                 }
2615
2616                 if (pass==0) {
2617                         glDisable(GL_BLEND);
2618                         glEnable(GL_DEPTH_TEST);
2619                 }
2620         }
2621 }       
2622
2623 static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d,
2624                                   Object *ob, EditMesh *em, UnitSettings *unit)
2625 {
2626         Mesh *me= ob->data;
2627         EditEdge *eed;
2628         EditFace *efa;
2629         float v1[3], v2[3], v3[3], v4[3], vmid[3];
2630         float fvec[3];
2631         char val[32]; /* Stores the measurement display text here */
2632         const char *conv_float; /* Use a float conversion matching the grid size */
2633         unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
2634         float area; /* area of the face */
2635         float grid= unit->system ? unit->scale_length : v3d->grid;
2636         const int do_split= unit->flag & USER_UNIT_OPT_SPLIT;
2637         const int do_global= v3d->flag & V3D_GLOBAL_STATS;
2638         const int do_moving= G.moving;
2639
2640         /* make the precision of the pronted value proportionate to the gridsize */
2641
2642         if (grid < 0.01f)               conv_float= "%.6g";
2643         else if (grid < 0.1f)   conv_float= "%.5g";
2644         else if (grid < 1.0f)   conv_float= "%.4g";
2645         else if (grid < 10.0f)  conv_float= "%.3g";
2646         else                                    conv_float= "%.2g";
2647
2648         if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
2649                 glDisable(GL_DEPTH_TEST);
2650
2651         if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
2652         
2653         if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
2654                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
2655
2656                 for(eed= em->edges.first; eed; eed= eed->next) {
2657                         /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
2658                         if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
2659                                 copy_v3_v3(v1, eed->v1->co);
2660                                 copy_v3_v3(v2, eed->v2->co);
2661
2662                                 mid_v3_v3v3(vmid, v1, v2);
2663
2664                                 if(do_global) {
2665                                         mul_mat3_m4_v3(ob->obmat, v1);
2666                                         mul_mat3_m4_v3(ob->obmat, v2);
2667                                 }
2668                                 if(unit->system)
2669                                         bUnit_AsString(val, sizeof(val), len_v3v3(v1, v2)*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);
2670                                 else
2671                                         sprintf(val, conv_float, len_v3v3(v1, v2));
2672
2673                                 view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);
2674                         }
2675                 }
2676         }
2677
2678         if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
2679 // XXX          extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
2680                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
2681                 
2682                 for(efa= em->faces.first; efa; efa= efa->next) {
2683                         if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
2684                                 copy_v3_v3(v1, efa->v1->co);
2685                                 copy_v3_v3(v2, efa->v2->co);
2686                                 copy_v3_v3(v3, efa->v3->co);
2687                                 if (efa->v4) {
2688                                         copy_v3_v3(v4, efa->v4->co);
2689                                 }
2690                                 if(do_global) {
2691                                         mul_mat3_m4_v3(ob->obmat, v1);
2692                                         mul_mat3_m4_v3(ob->obmat, v2);
2693                                         mul_mat3_m4_v3(ob->obmat, v3);
2694                                         if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
2695                                 }
2696                                 
2697                                 if (efa->v4)
2698                                         area=  area_quad_v3(v1, v2, v3, v4);
2699                                 else
2700                                         area = area_tri_v3(v1, v2, v3);
2701
2702                                 if(unit->system)
2703                                         bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
2704                                 else
2705                                         sprintf(val, conv_float, area);
2706
2707                                 view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
2708                         }
2709                 }
2710         }
2711
2712         if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
2713                 EditEdge *e1, *e2, *e3, *e4;
2714                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2715                 for(efa= em->faces.first; efa; efa= efa->next) {
2716                         copy_v3_v3(v1, efa->v1->co);
2717                         copy_v3_v3(v2, efa->v2->co);
2718                         copy_v3_v3(v3, efa->v3->co);
2719                         if(efa->v4) {
2720                                 copy_v3_v3(v4, efa->v4->co); 
2721                         }
2722                         else {
2723                                 copy_v3_v3(v4, v3);
2724                         }
2725                         if(do_global) {
2726                                 mul_mat3_m4_v3(ob->obmat, v1);
2727                                 mul_mat3_m4_v3(ob->obmat, v2);
2728                                 mul_mat3_m4_v3(ob->obmat, v3);
2729                                 mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
2730                         }
2731                         
2732                         e1= efa->e1;
2733                         e2= efa->e2;
2734                         e3= efa->e3;
2735                         if(efa->e4) e4= efa->e4; else e4= e3;
2736                         
2737                         /* Calculate the angles */
2738                                 
2739                         if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
2740                                 /* Vec 1 */
2741                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
2742                                 interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
2743                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2744                         }
2745                         if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
2746                                 /* Vec 2 */
2747                                 sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
2748                                 interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
2749                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2750                         }
2751                         if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
2752                                 /* Vec 3 */
2753                                 if(efa->v4) 
2754                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
2755                                 else
2756                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
2757                                 interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
2758                                 view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2759                         }
2760                                 /* Vec 4 */
2761                         if(efa->v4) {
2762                                 if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
2763                                         sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
2764                                         interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
2765                                         view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
2766                                 }
2767                         }
2768                 }
2769         }
2770
2771         /* useful for debugging index vs shape key index */
2772 #if 0
2773         {
2774                 EditVert *eve;
2775                 int j;
2776                 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
2777                 for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
2778                         sprintf(val, "%d:%d", j, eve->keyindex);
2779                         view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
2780                 }
2781         }
2782 #endif
2783
2784         if(v3d->zbuf) {
2785                 glEnable(GL_DEPTH_TEST);
2786                 bglPolygonOffset(rv3d->dist, 0.0f);
2787         }
2788 }
2789
2790 static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
2791 {
2792         EditFace *efa = EM_get_face_for_index(index);
2793
2794         if (efa->h==0) {
2795                 GPU_enable_material(efa->mat_nr+1, NULL);
2796                 return 1;
2797         }
2798         else
2799                 return 0;
2800 }
2801
2802 static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
2803 {
2804         EditFace *efa = EM_get_face_for_index(index);
2805
2806         return (efa->h==0);
2807 }
2808
2809 static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
2810                           Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
2811 {
2812         Mesh *me = ob->data;
2813         EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
2814         EditEdge *eed_act = NULL;
2815         EditVert *eve_act = NULL;
2816         
2817         if (em->selected.last) {
2818                 EditSelection *ese = em->selected.last;
2819                 /* face is handeled above */
2820                 /*if (ese->type == EDITFACE ) {
2821                         efa_act = (EditFace *)ese->data;
2822                 } else */ if ( ese->type == EDITEDGE ) {
2823                         eed_act = (EditEdge *)ese->data;
2824                 } else if ( ese->type == EDITVERT ) {
2825                         eve_act = (EditVert *)ese->data;
2826                 }
2827         }
2828         
2829         EM_init_index_arrays(em, 1, 1, 1);
2830
2831         if(dt>OB_WIRE) {
2832                 if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2833                         if(draw_glsl_material(scene, ob, v3d, dt)) {
2834                                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2835
2836                                 finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
2837                                                              draw_em_fancy__setGLSLFaceOpts, em);
2838                                 GPU_disable_material();
2839
2840                                 glFrontFace(GL_CCW);
2841                         }
2842                         else {
2843                                 draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
2844                         }
2845                 }
2846                 else {
2847                         /* 3 floats for position,
2848                          * 3 for normal and times two because the faces may actually be quads instead of triangles */
2849                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
2850
2851                         glEnable(GL_LIGHTING);
2852                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
2853                         finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_enable_material, NULL, NULL, 0);
2854
2855                         glFrontFace(GL_CCW);
2856                         glDisable(GL_LIGHTING);
2857                 }
2858                         
2859                 // Setup for drawing wire over, disable zbuffer
2860                 // write to show selected edge wires better
2861                 UI_ThemeColor(TH_WIRE);
2862
2863                 bglPolygonOffset(rv3d->dist, 1.0);
2864                 glDepthMask(0);
2865         } 
2866         else {
2867                 if (cageDM!=finalDM) {
2868                         UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
2869                         finalDM->drawEdges(finalDM, 1, 0);
2870                 }
2871         }
2872         
2873         if(me->drawflag & ME_DRAWFACES) {       /* transp faces */
2874                 unsigned char col1[4], col2[4], col3[4];
2875                         
2876                 UI_GetThemeColor4ubv(TH_FACE, col1);
2877                 UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
2878                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2879                 
2880                 glEnable(GL_BLEND);
2881                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2882                 
2883                 /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
2884                 if CHECK_OB_DRAWTEXTURE(v3d, dt)
2885                         col1[3] = 0;
2886                 
2887                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2888
2889                 glDisable(GL_BLEND);
2890                 glDepthMask(1);         // restore write in zbuffer
2891         } else if (efa_act) {
2892                 /* even if draw faces is off it would be nice to draw the stipple face
2893                  * Make all other faces zero alpha except for the active
2894                  * */
2895                 unsigned char col1[4], col2[4], col3[4];
2896                 col1[3] = col2[3] = 0; /* dont draw */
2897                 UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
2898                 
2899                 glEnable(GL_BLEND);
2900                 glDepthMask(0);         // disable write in zbuffer, needed for nice transp
2901                 
2902                 draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
2903
2904                 glDisable(GL_BLEND);
2905                 glDepthMask(1);         // restore write in zbuffer
2906                 
2907         }
2908
2909         /* here starts all fancy draw-extra over */
2910         if((me->drawflag & ME_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
2911                 /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
2912                 
2913                 /* only draw selected edges otherwise there is no way of telling if a face is selected */
2914                 draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
2915                 
2916         } else {
2917                 if(me->drawflag & ME_DRAWSEAMS) {
2918                         UI_ThemeColor(TH_EDGE_SEAM);
2919                         glLineWidth(2);
2920         
2921                         draw_dm_edges_seams(cageDM);
2922         
2923                         glColor3ub(0,0,0);
2924                         glLineWidth(1);
2925                 }
2926                 
2927                 if(me->drawflag & ME_DRAWSHARP) {
2928                         UI_ThemeColor(TH_EDGE_SHARP);
2929                         glLineWidth(2);
2930         
2931                         draw_dm_edges_sharp(cageDM);
2932         
2933                         glColor3ub(0,0,0);
2934                         glLineWidth(1);
2935                 }
2936         
2937                 if(me->drawflag & ME_DRAWCREASES) {
2938                         draw_dm_creases(cageDM);
2939                 }
2940                 if(me->drawflag & ME_DRAWBWEIGHTS) {
2941                         draw_dm_bweights(scene, cageDM);
2942                 }
2943
2944                 draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
2945         }
2946         if(em) {
2947 // XXX          retopo_matrix_update(v3d);
2948
2949                 draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
2950
2951                 if(me->drawflag & ME_DRAWNORMALS) {
2952                         UI_ThemeColor(TH_NORMAL);
2953                         draw_dm_face_normals(scene, cageDM);
2954                 }
2955                 if(me->drawflag & ME_DRAW_VNORMALS) {
2956                         UI_ThemeColor(TH_VNORMAL);
2957                         draw_dm_vert_normals(scene, cageDM);
2958                 }
2959
2960                 if ( (me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG)) &&
2961                      !(v3d->flag2 & V3D_RENDER_OVERRIDE))
2962                 {
2963                         draw_em_measure_stats(v3d, rv3d, ob, em, &scene->unit);
2964                 }
2965         }
2966
2967         if(dt>OB_WIRE) {
2968                 glDepthMask(1);
2969                 bglPolygonOffset(rv3d->dist, 0.0);
2970                 GPU_disable_material();
2971         }
2972
2973         EM_free_index_arrays();
2974 }
2975
2976 /* Mesh drawing routines */
2977
2978 static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
2979 {
2980         
2981         if(v3d->transp==0) {    // not when we draw the transparent pass
2982                 glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
2983                 glDepthMask(0);
2984                 
2985                 /* if transparent, we cannot draw the edges for solid select... edges have no material info.
2986                    drawFacesSolid() doesn't draw the transparent faces */
2987                 if(ob->dtx & OB_DRAWTRANSP) {
2988                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
2989                         dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material);
2990                         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2991                         GPU_disable_material();
2992                 }
2993                 else {
2994                         dm->drawEdges(dm, 0, 1);
2995                 }
2996                                         
2997                 glLineWidth(1.0);
2998                 glDepthMask(1);
2999         }
3000 }
3001
3002 static int wpaint__setSolidDrawOptions(void *UNUSED(userData), int UNUSED(index), int *drawSmooth_r)
3003 {
3004         *drawSmooth_r = 1;
3005         return 1;
3006 }
3007
3008 static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag)
3009 {
3010         Object *ob= base->object;
3011         Mesh *me = ob->data;
3012         Material *ma= give_current_material(ob, 1);
3013         const short hasHaloMat = (ma && (ma->material_type == MA_TYPE_HALO));
3014         eWireDrawMode draw_wire= OBDRAW_WIRE_OFF;
3015         int /* totvert,*/ totedge, totface;
3016         DerivedMesh *dm= mesh_get_derived_final(scene, ob, scene->customdata_mask);
3017         ModifierData *md = NULL;
3018         const short is_obact= (ob == OBACT);
3019         int draw_flags = (is_obact && paint_facesel_test(ob)) ? DRAW_FACE_SELECT : 0;
3020
3021         if(!dm)
3022                 return;
3023
3024         /* check to draw dynamic paint colors */
3025         if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
3026         {
3027                 /* check if target has an active dpaint modifier        */
3028                 if(md && (md->mode & eModifierMode_Realtime))                                   
3029                 {
3030                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
3031                         /* if canvas is ready to preview vertex colors */
3032                         if (pmd->canvas && pmd->canvas->flags & MOD_DPAINT_PREVIEW_READY &&
3033                                 DM_get_face_data_layer(dm, CD_WEIGHT_MCOL)) {
3034                                 draw_flags |= DRAW_DYNAMIC_PAINT_PREVIEW;
3035                         }
3036                 }
3037         }
3038
3039         /* Unwanted combination */
3040         if (draw_flags & DRAW_FACE_SELECT) {
3041                 draw_wire= OBDRAW_WIRE_OFF;
3042         }
3043         else if (ob->dtx & OB_DRAWWIRE) {
3044                 draw_wire= OBDRAW_WIRE_ON_DEPTH; /* draw wire after solid using zoffset and depth buffer adjusment */
3045         }
3046         
3047         /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
3048         totedge = dm->getNumEdges(dm);
3049         totface = dm->getNumFaces(dm);
3050         
3051         /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
3052         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3053
3054         if(dt==OB_BOUNDBOX) {
3055                 if((v3d->flag2 & V3D_RENDER_OVERRIDE && v3d->drawtype >= OB_WIRE)==0)
3056                         draw_bounding_volume(scene, ob, ob->boundtype);
3057         }
3058         else if(hasHaloMat || (totface==0 && totedge==0)) {
3059                 glPointSize(1.5);
3060                 dm->drawVerts(dm);
3061                 glPointSize(1.0);
3062         }
3063         else if(dt==OB_WIRE || totface==0) {
3064                 draw_wire= OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff  */
3065         }
3066         else if ( (draw_flags & DRAW_FACE_SELECT || (is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
3067                   CHECK_OB_DRAWTEXTURE(v3d, dt))
3068         {
3069                 if ( (v3d->flag & V3D_SELECT_OUTLINE) &&
3070                      ((v3d->flag2 & V3D_RENDER_OVERRIDE)==0) &&
3071                      (base->flag & SELECT) &&
3072                      !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
3073                      (draw_wire == OBDRAW_WIRE_OFF))
3074                 {
3075                         draw_mesh_object_outline(v3d, ob, dm);
3076                 }
3077
3078                 if(draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
3079                         glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
3080
3081                         dm->drawFacesGLSL(dm, GPU_enable_material);
3082 //                      if(get_ob_property(ob, "Text"))
3083 // XXX                          draw_mesh_text(ob, 1);
3084                         GPU_disable_material();
3085
3086                         glFrontFace(GL_CCW);
3087                 }
3088                 else {
3089                         draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
3090                 }
3091
3092                 if(!(draw_flags & DRAW_FACE_SELECT)) {
3093                         if(base->flag & SELECT)
3094                                 UI_ThemeColor(is_obact ? TH_ACTIVE : TH_SELECT);
3095                         else
3096                                 UI_ThemeColor(TH_WIRE);
3097
3098                         if((v3d->flag2 & V3D_RENDER_OVERRIDE)==0)
3099                                 dm->drawLooseEdges(dm);
3100                 }
3101         }
3102         else if(dt==OB_SOLID) {
3103                 if(is_obact && ob->mode & OB_MODE_WEIGHT_PAINT) {
3104                         /* weight paint in solid mode, special case. focus on making the weights clear
3105                          * rather than the shading, this is also forced in wire view */
3106                         GPU_enable_material(0, NULL);
3107                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, GPU_enable_material, NULL, me->mface, 1);
3108                 
3109                         bglPolygonOffset(rv3d->dist, 1.0);
3110                         glDepthMask(0); // disable write in zbuffer, selected edge wires show better
3111
3112                         glEnable(GL_BLEND);
3113                         glColor4ub(255, 255, 255, 96);
3114                         glEnable(GL_LINE_STIPPLE);
3115                         glLineStipple(1, 0xAAAA);
3116
3117                         dm->drawEdges(dm, 1, 1);
3118
3119                         bglPolygonOffset(rv3d->dist, 0.0);
3120                         glDepthMask(1);
3121                         glDisable(GL_LINE_STIPPLE);
3122
3123                         GPU_disable_material();
3124                         
3125                         /* since we already draw wire as wp guide, dont draw over the top */
3126                         draw_wire= OBDRAW_WIRE_OFF;
3127                 }