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