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