c33f8723231d6c8c0d33f7276aefaddbb1b839e1
[blender-staging.git] / source / blender / editors / space_view3d / view3d_draw.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <math.h>
32
33 #include "DNA_action_types.h"
34 #include "DNA_armature_types.h"
35 #include "DNA_camera_types.h"
36 #include "DNA_customdata_types.h"
37 #include "DNA_group_types.h"
38 #include "DNA_key_types.h"
39 #include "DNA_lamp_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_userdef_types.h"
45 #include "DNA_view3d_types.h"
46 #include "DNA_world_types.h"
47
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_math.h"
52 #include "BLI_rand.h"
53
54 #include "BKE_anim.h"
55 #include "BKE_context.h"
56 #include "BKE_customdata.h"
57 #include "BKE_image.h"
58 #include "BKE_ipo.h"
59 #include "BKE_key.h"
60 #include "BKE_object.h"
61 #include "BKE_global.h"
62 #include "BKE_paint.h"
63 #include "BKE_scene.h"
64 #include "BKE_screen.h"
65 #include "BKE_utildefines.h"
66 #include "BKE_unit.h"
67
68 #include "RE_pipeline.h"        // make_stars
69
70 #include "IMB_imbuf_types.h"
71 #include "IMB_imbuf.h"
72
73 #include "BIF_gl.h"
74 #include "BIF_glutil.h"
75
76 #include "WM_api.h"
77 #include "BLF_api.h"
78
79 #include "ED_armature.h"
80 #include "ED_keyframing.h"
81 #include "ED_gpencil.h"
82 #include "ED_mesh.h"
83 #include "ED_screen.h"
84 #include "ED_space_api.h"
85 #include "ED_util.h"
86 #include "ED_transform.h"
87 #include "ED_types.h"
88
89 #include "UI_interface.h"
90 #include "UI_interface_icons.h"
91 #include "UI_resources.h"
92 #include "UI_view2d.h"
93
94 #include "GPU_draw.h"
95 #include "GPU_material.h"
96
97 #include "view3d_intern.h"      // own include
98
99
100
101 static void star_stuff_init_func(void)
102 {
103         cpack(-1);
104         glPointSize(1.0);
105         glBegin(GL_POINTS);
106 }
107 static void star_stuff_vertex_func(float* i)
108 {
109         glVertex3fv(i);
110 }
111 static void star_stuff_term_func(void)
112 {
113         glEnd();
114 }
115
116 void circf(float x, float y, float rad)
117 {
118         GLUquadricObj *qobj = gluNewQuadric(); 
119         
120         gluQuadricDrawStyle(qobj, GLU_FILL); 
121         
122         glPushMatrix(); 
123         
124         glTranslatef(x,  y, 0.); 
125         
126         gluDisk( qobj, 0.0,  rad, 32, 1); 
127         
128         glPopMatrix(); 
129         
130         gluDeleteQuadric(qobj);
131 }
132
133 void circ(float x, float y, float rad)
134 {
135         GLUquadricObj *qobj = gluNewQuadric(); 
136         
137         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
138         
139         glPushMatrix(); 
140         
141         glTranslatef(x,  y, 0.); 
142         
143         gluDisk( qobj, 0.0,  rad, 32, 1); 
144         
145         glPopMatrix(); 
146         
147         gluDeleteQuadric(qobj);
148 }
149
150
151 /* ********* custom clipping *********** */
152
153 static void view3d_draw_clipping(RegionView3D *rv3d)
154 {
155         BoundBox *bb= rv3d->clipbb;
156         
157         if(bb) {
158                 UI_ThemeColorShade(TH_BACK, -8);
159                 
160                 glBegin(GL_QUADS);
161                 
162                 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]);
163                 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]);
164                 glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]);
165                 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]);
166                 glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]);
167                 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]);
168                 
169                 glEnd();
170         }
171 }
172
173 void view3d_set_clipping(RegionView3D *rv3d)
174 {
175         double plane[4];
176         int a, tot=4;
177         
178         if(rv3d->viewlock) tot= 6;
179         
180         for(a=0; a<tot; a++) {
181                 QUATCOPY(plane, rv3d->clip[a]);
182                 glClipPlane(GL_CLIP_PLANE0+a, plane);
183                 glEnable(GL_CLIP_PLANE0+a);
184         }
185 }
186
187 void view3d_clr_clipping(void)
188 {
189         int a;
190         
191         for(a=0; a<6; a++) {
192                 glDisable(GL_CLIP_PLANE0+a);
193         }
194 }
195
196 static int test_clipping(float *vec, float clip[][4])
197 {
198         float view[3];
199         VECCOPY(view, vec);
200         
201         if(0.0f < clip[0][3] + INPR(view, clip[0]))
202                 if(0.0f < clip[1][3] + INPR(view, clip[1]))
203                         if(0.0f < clip[2][3] + INPR(view, clip[2]))
204                                 if(0.0f < clip[3][3] + INPR(view, clip[3]))
205                                         return 0;
206
207         return 1;
208 }
209
210 /* for 'local' ED_view3d_local_clipping must run first
211  * then all comparisons can be done in localspace */
212 int view3d_test_clipping(RegionView3D *rv3d, float *vec, int local)
213 {
214         return test_clipping(vec, local ? rv3d->clip_local : rv3d->clip);
215 }
216
217 /* ********* end custom clipping *********** */
218
219
220 static void drawgrid_draw(ARegion *ar, float wx, float wy, float x, float y, float dx)
221 {
222         float fx, fy;
223         
224         x+= (wx); 
225         y+= (wy);
226         fx= x/dx;
227         fx= x-dx*floor(fx);
228         
229         while(fx< ar->winx) {
230                 fdrawline(fx,  0.0,  fx,  (float)ar->winy); 
231                 fx+= dx; 
232         }
233
234         fy= y/dx;
235         fy= y-dx*floor(fy);
236         
237
238         while(fy< ar->winy) {
239                 fdrawline(0.0,  fy,  (float)ar->winx,  fy); 
240                 fy+= dx;
241         }
242
243 }
244
245 #define GRID_MIN_PX 6.0f
246
247 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, char **grid_unit)
248 {
249         /* extern short bgpicmode; */
250         RegionView3D *rv3d= ar->regiondata;
251         float wx, wy, x, y, fw, fx, fy, dx;
252         float vec4[4];
253         char col[3], col2[3];
254         
255         *grid_unit= NULL;
256
257         vec4[0]=vec4[1]=vec4[2]=0.0; 
258         vec4[3]= 1.0;
259         mul_m4_v4(rv3d->persmat, vec4);
260         fx= vec4[0]; 
261         fy= vec4[1]; 
262         fw= vec4[3];
263
264         wx= (ar->winx/2.0);     /* because of rounding errors, grid at wrong location */
265         wy= (ar->winy/2.0);
266
267         x= (wx)*fx/fw;
268         y= (wy)*fy/fw;
269
270         vec4[0]=vec4[1]= (unit->system) ? 1.0 : v3d->grid;
271
272         vec4[2]= 0.0;
273         vec4[3]= 1.0;
274         mul_m4_v4(rv3d->persmat, vec4);
275         fx= vec4[0]; 
276         fy= vec4[1]; 
277         fw= vec4[3];
278
279         dx= fabs(x-(wx)*fx/fw);
280         if(dx==0) dx= fabs(y-(wy)*fy/fw);
281         
282         glDepthMask(0);         // disable write in zbuffer
283
284         /* check zoom out */
285         UI_ThemeColor(TH_GRID);
286         
287         if(unit->system) {
288                 /* Use GRID_MIN_PX*2 for units because very very small grid
289                  * items are less useful when dealing with units */
290                 void *usys;
291                 int len, i;
292                 double scalar;
293                 float dx_scalar;
294                 float blend_fac;
295
296                 bUnit_GetSystem(&usys, &len, unit->system, B_UNIT_LENGTH);
297
298                 if(usys) {
299                         i= len;
300                         while(i--) {
301                                 scalar= bUnit_GetScaler(usys, i);
302
303                                 dx_scalar = dx * scalar * unit->scale_length;
304                                 if (dx_scalar < (GRID_MIN_PX*2))
305                                         continue;
306
307                                 /* Store the smallest drawn grid size units name so users know how big each grid cell is */
308                                 if(*grid_unit==NULL) {
309                                         *grid_unit= bUnit_GetNameDisplay(usys, i);
310                                         rv3d->gridview= (scalar * unit->scale_length);
311                                 }
312                                 blend_fac= 1-((GRID_MIN_PX*2)/dx_scalar);
313
314                                 /* tweak to have the fade a bit nicer */
315                                 blend_fac= (blend_fac * blend_fac) * 2.0f;
316                                 CLAMP(blend_fac, 0.3f, 1.0f);
317
318
319                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, blend_fac);
320
321                                 drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
322                         }
323                 }
324         }
325         else {
326                 short sublines = v3d->gridsubdiv;
327
328                 if(dx<GRID_MIN_PX) {
329                         rv3d->gridview*= sublines;
330                         dx*= sublines;
331                         
332                         if(dx<GRID_MIN_PX) {
333                                 rv3d->gridview*= sublines;
334                                 dx*= sublines;
335
336                                 if(dx<GRID_MIN_PX) {
337                                         rv3d->gridview*= sublines;
338                                         dx*=sublines;
339                                         if(dx<GRID_MIN_PX);
340                                         else {
341                                                 UI_ThemeColor(TH_GRID);
342                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
343                                         }
344                                 }
345                                 else {  // start blending out
346                                         UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6));
347                                         drawgrid_draw(ar, wx, wy, x, y, dx);
348
349                                         UI_ThemeColor(TH_GRID);
350                                         drawgrid_draw(ar, wx, wy, x, y, sublines*dx);
351                                 }
352                         }
353                         else {  // start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX*10))
354                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6));
355                                 drawgrid_draw(ar, wx, wy, x, y, dx);
356
357                                 UI_ThemeColor(TH_GRID);
358                                 drawgrid_draw(ar, wx, wy, x, y, sublines*dx);
359                         }
360                 }
361                 else {
362                         if(dx>(GRID_MIN_PX*10)) {               // start blending in
363                                 rv3d->gridview/= sublines;
364                                 dx/= sublines;
365                                 if(dx>(GRID_MIN_PX*10)) {               // start blending in
366                                         rv3d->gridview/= sublines;
367                                         dx/= sublines;
368                                         if(dx>(GRID_MIN_PX*10)) {
369                                                 UI_ThemeColor(TH_GRID);
370                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
371                                         }
372                                         else {
373                                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6));
374                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
375                                                 UI_ThemeColor(TH_GRID);
376                                                 drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
377                                         }
378                                 }
379                                 else {
380                                         UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6));
381                                         drawgrid_draw(ar, wx, wy, x, y, dx);
382                                         UI_ThemeColor(TH_GRID);
383                                         drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
384                                 }
385                         }
386                         else {
387                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*6));
388                                 drawgrid_draw(ar, wx, wy, x, y, dx);
389                                 UI_ThemeColor(TH_GRID);
390                                 drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
391                         }
392                 }
393         }
394
395
396         x+= (wx); 
397         y+= (wy);
398         UI_GetThemeColor3ubv(TH_GRID, col);
399
400         setlinestyle(0);
401         
402         /* center cross */
403         if( ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) 
404                 UI_make_axis_color(col, col2, 'y');
405         else UI_make_axis_color(col, col2, 'x');
406         glColor3ubv((GLubyte *)col2);
407         
408         fdrawline(0.0,  y,  (float)ar->winx,  y); 
409         
410         if( ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) 
411                 UI_make_axis_color(col, col2, 'y');
412         else UI_make_axis_color(col, col2, 'z');
413         glColor3ubv((GLubyte *)col2);
414
415         fdrawline(x, 0.0, x, (float)ar->winy); 
416
417         glDepthMask(1);         // enable write in zbuffer
418 }
419 #undef GRID_MIN_PX
420
421 static void drawfloor(Scene *scene, View3D *v3d)
422 {
423         float vert[3], grid;
424         int a, gridlines, emphasise;
425         char col[3], col2[3];
426         short draw_line = 0;
427         
428         vert[2]= 0.0;
429         
430         if(v3d->gridlines<3) return;
431         
432         if(v3d->zbuf && scene->obedit) glDepthMask(0);  // for zbuffer-select
433         
434         gridlines= v3d->gridlines/2;
435         grid= gridlines*v3d->grid;
436         
437         UI_GetThemeColor3ubv(TH_GRID, col);
438         UI_GetThemeColor3ubv(TH_BACK, col2);
439         
440         /* emphasise division lines lighter instead of darker, if background is darker than grid */
441         if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 )
442                 emphasise = 20;
443         else
444                 emphasise = -10;
445         
446         /* draw the Y axis and/or grid lines */
447         for(a= -gridlines;a<=gridlines;a++) {
448                 if(a==0) {
449                         /* check for the 'show Y axis' preference */
450                         if (v3d->gridflag & V3D_SHOW_Y) { 
451                                 UI_make_axis_color(col, col2, 'y');
452                                 glColor3ubv((GLubyte *)col2);
453                                 
454                                 draw_line = 1;
455                         } else if (v3d->gridflag & V3D_SHOW_FLOOR) {
456                                 UI_ThemeColorShade(TH_GRID, emphasise);
457                         } else {
458                                 draw_line = 0;
459                         }
460                 } else {
461                         /* check for the 'show grid floor' preference */
462                         if (v3d->gridflag & V3D_SHOW_FLOOR) {
463                                 if( (a % 10)==0) {
464                                         UI_ThemeColorShade(TH_GRID, emphasise);
465                                 }
466                                 else UI_ThemeColorShade(TH_GRID, 10);
467                                 
468                                 draw_line = 1;
469                         } else {
470                                 draw_line = 0;
471                         }
472                 }
473                 
474                 if (draw_line) {
475                         glBegin(GL_LINE_STRIP);
476                 vert[0]= a*v3d->grid;
477                 vert[1]= grid;
478                 glVertex3fv(vert);
479                 vert[1]= -grid;
480                 glVertex3fv(vert);
481                         glEnd();
482                 }
483         }
484         
485         /* draw the X axis and/or grid lines */
486         for(a= -gridlines;a<=gridlines;a++) {
487                 if(a==0) {
488                         /* check for the 'show X axis' preference */
489                         if (v3d->gridflag & V3D_SHOW_X) { 
490                                 UI_make_axis_color(col, col2, 'x');
491                                 glColor3ubv((GLubyte *)col2);
492                                 
493                                 draw_line = 1;
494                         } else if (v3d->gridflag & V3D_SHOW_FLOOR) {
495                                 UI_ThemeColorShade(TH_GRID, emphasise);
496                         } else {
497                                 draw_line = 0;
498                         }
499                 } else {
500                         /* check for the 'show grid floor' preference */
501                         if (v3d->gridflag & V3D_SHOW_FLOOR) {
502                                 if( (a % 10)==0) {
503                                         UI_ThemeColorShade(TH_GRID, emphasise);
504                                 }
505                                 else UI_ThemeColorShade(TH_GRID, 10);
506                                 
507                                 draw_line = 1;
508                         } else {
509                                 draw_line = 0;
510                         }
511                 }
512                 
513                 if (draw_line) {
514                         glBegin(GL_LINE_STRIP);
515                 vert[1]= a*v3d->grid;
516                 vert[0]= grid;
517                 glVertex3fv(vert );
518                 vert[0]= -grid;
519                 glVertex3fv(vert);
520                         glEnd();
521                 }
522         }
523         
524         /* draw the Z axis line */      
525         /* check for the 'show Z axis' preference */
526         if (v3d->gridflag & V3D_SHOW_Z) {
527                 UI_make_axis_color(col, col2, 'z');
528                 glColor3ubv((GLubyte *)col2);
529                 
530                 glBegin(GL_LINE_STRIP);
531                 vert[0]= 0;
532                 vert[1]= 0;
533                 vert[2]= grid;
534                 glVertex3fv(vert );
535                 vert[2]= -grid;
536                 glVertex3fv(vert);
537                 glEnd();
538         }
539         
540         if(v3d->zbuf && scene->obedit) glDepthMask(1);  
541         
542 }
543
544 static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
545 {
546         short mx,my,co[2];
547         int flag;
548         
549         /* we dont want the clipping for cursor */
550         flag= v3d->flag;
551         v3d->flag= 0;
552         project_short(ar, give_cursor(scene, v3d), co);
553         v3d->flag= flag;
554         
555         mx = co[0];
556         my = co[1];
557         
558         if(mx!=IS_CLIPPED) {
559                 setlinestyle(0); 
560                 cpack(0xFF);
561                 circ((float)mx, (float)my, 10.0);
562                 setlinestyle(4); 
563                 cpack(0xFFFFFF);
564                 circ((float)mx, (float)my, 10.0);
565                 setlinestyle(0);
566                 cpack(0x0);
567                 
568                 sdrawline(mx-20, my, mx-5, my);
569                 sdrawline(mx+5, my, mx+20, my);
570                 sdrawline(mx, my-20, mx, my-5);
571                 sdrawline(mx, my+5, mx, my+20);
572         }
573 }
574
575 /* Draw a live substitute of the view icon, which is always shown */
576 static void draw_view_axis(RegionView3D *rv3d)
577 {
578         const float k = U.rvisize;   /* axis size */
579         const float toll = 0.5;      /* used to see when view is quasi-orthogonal */
580         const float start = k + 1.0; /* axis center in screen coordinates, x=y */
581         float ydisp = 0.0;          /* vertical displacement to allow obj info text */
582         
583         /* rvibright ranges approx. from original axis icon color to gizmo color */
584         float bright = U.rvibright / 15.0f;
585         
586         unsigned char col[3];
587         unsigned char gridcol[3];
588         float colf[3];
589         
590         float vec[4];
591         float dx, dy;
592         float h, s, v;
593         
594         /* thickness of lines is proportional to k */
595         /*      (log(k)-1) gives a more suitable thickness, but fps decreased by about 3 fps */
596         glLineWidth(k / 10);
597         //glLineWidth(log(k)-1); // a bit slow
598         
599         UI_GetThemeColor3ubv(TH_GRID, (char *)gridcol);
600         
601         /* X */
602         vec[0] = vec[3] = 1;
603         vec[1] = vec[2] = 0;
604         mul_qt_v3(rv3d->viewquat, vec);
605         
606         UI_make_axis_color((char *)gridcol, (char *)col, 'x');
607         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
608         s = s<0.5 ? s+0.5 : 1.0;
609         v = 0.3;
610         v = (v<1.0-(bright) ? v+bright : 1.0);
611         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
612         glColor3fv(colf);
613         
614         dx = vec[0] * k;
615         dy = vec[1] * k;
616         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
617         if (fabs(dx) > toll || fabs(dy) > toll) {
618                 BLF_draw_default(start + dx + 2, start + dy + ydisp + 2, 0.0f, "x");
619         }
620         
621         /* Y */
622         vec[1] = vec[3] = 1;
623         vec[0] = vec[2] = 0;
624         mul_qt_v3(rv3d->viewquat, vec);
625         
626         UI_make_axis_color((char *)gridcol, (char *)col, 'y');
627         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
628         s = s<0.5 ? s+0.5 : 1.0;
629         v = 0.3;
630         v = (v<1.0-(bright) ? v+bright : 1.0);
631         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
632         glColor3fv(colf);
633         
634         dx = vec[0] * k;
635         dy = vec[1] * k;
636         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
637         if (fabs(dx) > toll || fabs(dy) > toll) {
638                 BLF_draw_default(start + dx + 2, start + dy + ydisp + 2, 0.0f, "y");
639         }
640         
641         /* Z */
642         vec[2] = vec[3] = 1;
643         vec[1] = vec[0] = 0;
644         mul_qt_v3(rv3d->viewquat, vec);
645         
646         UI_make_axis_color((char *)gridcol, (char *)col, 'z');
647         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
648         s = s<0.5 ? s+0.5 : 1.0;
649         v = 0.5;
650         v = (v<1.0-(bright) ? v+bright : 1.0);
651         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
652         glColor3fv(colf);
653         
654         dx = vec[0] * k;
655         dy = vec[1] * k;
656         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
657         if (fabs(dx) > toll || fabs(dy) > toll) {
658                 BLF_draw_default(start + dx + 2, start + dy + ydisp + 2, 0.0f, "z");
659         }
660         
661         /* restore line-width */
662         glLineWidth(1.0);
663 }
664
665
666 static void draw_view_icon(RegionView3D *rv3d)
667 {
668         BIFIconID icon;
669         
670         if( ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) 
671                 icon= ICON_AXIS_TOP;
672         else if( ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) 
673                 icon= ICON_AXIS_FRONT;
674         else if( ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) 
675                 icon= ICON_AXIS_SIDE;
676         else return ;
677         
678         glEnable(GL_BLEND);
679         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
680         
681         UI_icon_draw(5.0, 5.0, icon);
682         
683         glDisable(GL_BLEND);
684 }
685
686 static char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
687 {
688         char *name = NULL;
689         
690         switch (rv3d->view) {
691                 case RV3D_VIEW_FRONT:
692                         if (rv3d->persp == RV3D_ORTHO) name = "Front Ortho";
693                         else name = "Front Persp";
694                         break;
695                 case RV3D_VIEW_BACK:
696                         if (rv3d->persp == RV3D_ORTHO) name = "Back Ortho";
697                         else name = "Back Persp";
698                         break;
699                 case RV3D_VIEW_TOP:
700                         if (rv3d->persp == RV3D_ORTHO) name = "Top Ortho";
701                         else name = "Top Persp";
702                         break;
703                 case RV3D_VIEW_BOTTOM:
704                         if (rv3d->persp == RV3D_ORTHO) name = "Bottom Ortho";
705                         else name = "Bottom Persp";
706                         break;
707                 case RV3D_VIEW_RIGHT:
708                         if (rv3d->persp == RV3D_ORTHO) name = "Right Ortho";
709                         else name = "Right Persp";
710                         break;
711                 case RV3D_VIEW_LEFT:
712                         if (rv3d->persp == RV3D_ORTHO) name = "Left Ortho";
713                         else name = "Left Persp";
714                         break;
715                         
716                 default:
717                         if (rv3d->persp==RV3D_CAMOB) {
718                                 if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
719                                         Camera *cam;
720                                         cam = v3d->camera->data;
721                                         name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
722                                 } else {
723                                         name = "Object as Camera";
724                                 }
725                         } else { 
726                                 name = (rv3d->persp == RV3D_ORTHO) ? "User Ortho" : "User Persp";
727                         }
728                         break;
729         }
730         
731         return name;
732 }
733
734 static void draw_viewport_name(ARegion *ar, View3D *v3d)
735 {
736         RegionView3D *rv3d= ar->regiondata;
737         char *name = view3d_get_name(v3d, rv3d);
738         char *printable = NULL;
739         
740         if (v3d->localvd) {
741                 printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
742                                                                                                  strcpy(printable, name);
743                                                                                                  strcat(printable, " (Local)");
744         } else {
745                 printable = name;
746         }
747
748         if (printable) {
749                 UI_ThemeColor(TH_TEXT_HI);
750                 BLF_draw_default(22,  ar->winy-17, 0.0f, printable);
751         }
752
753         if (v3d->localvd) {
754                 free(printable);
755         }
756 }
757
758 /* draw info beside axes in bottom left-corner: 
759 *       framenum, object name, bone name (if available), marker name (if available)
760 */
761 static void draw_selected_name(Scene *scene, Object *ob, View3D *v3d)
762 {
763         char info[256], *markern;
764         short offset=30;
765         
766         /* get name of marker on current frame (if available) */
767         markern= scene_find_marker_name(scene, CFRA);
768         
769         /* check if there is an object */
770         if(ob) {
771                 /* name(s) to display depends on type of object */
772                 if(ob->type==OB_ARMATURE) {
773                         bArmature *arm= ob->data;
774                         char *name= NULL;
775                         
776                         /* show name of active bone too (if possible) */
777                         if(arm->edbo) {
778
779                                 if(arm->act_edbone)
780                                         name= ((EditBone *)arm->act_edbone)->name;
781
782                         }
783                         else if(ob->mode & OB_MODE_POSE) {
784                                 if(arm->act_bone) {
785
786                                         if(arm->act_bone->layer & arm->layer)
787                                                 name= arm->act_bone->name;
788
789                                 }
790                         }
791                         if(name && markern)
792                                 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern);
793                         else if(name)
794                                 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name);
795                         else
796                                 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
797                 }
798                 else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
799                         Key *key= NULL;
800                         KeyBlock *kb = NULL;
801                         char shapes[75];
802                         
803                         /* try to display active shapekey too */
804                         shapes[0] = 0;
805                         key = ob_get_key(ob);
806                         if(key){
807                                 kb = BLI_findlink(&key->block, ob->shapenr-1);
808                                 if(kb){
809                                         sprintf(shapes, ": %s ", kb->name);             
810                                         if(ob->shapeflag == OB_SHAPE_LOCK){
811                                                 strcat(shapes, " (Pinned)");
812                                         }
813                                 }
814                         }
815                         
816                         if(markern)
817                                 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern);
818                         else
819                                 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes);
820                 }
821                 else {
822                         /* standard object */
823                         if (markern)
824                                 sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern);
825                         else
826                                 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
827                 }
828                 
829                 /* colour depends on whether there is a keyframe */
830                 if (id_frame_has_keyframe((ID *)ob, /*frame_to_float(scene, CFRA)*/(float)(CFRA), v3d->keyflags))
831                         UI_ThemeColor(TH_VERTEX_SELECT);
832                 else
833                         UI_ThemeColor(TH_TEXT_HI);
834         }
835         else {
836                 /* no object */
837                 if (markern)
838                         sprintf(info, "(%d) <%s>", CFRA, markern);
839                 else
840                         sprintf(info, "(%d)", CFRA);
841                 
842                 /* colour is always white */
843                 UI_ThemeColor(TH_TEXT_HI);
844         }
845         
846         if (U.uiflag & USER_SHOW_ROTVIEWICON)
847                 offset = 14 + (U.rvisize * 2);
848
849         BLF_draw_default(offset,  10, 0.0f, info);
850 }
851
852 static void view3d_get_viewborder_size(Scene *scene, ARegion *ar, float size_r[2])
853 {
854         float winmax= MAX2(ar->winx, ar->winy);
855         float aspect= (float) (scene->r.xsch*scene->r.xasp)/(scene->r.ysch*scene->r.yasp);
856         
857         if(aspect>1.0) {
858                 size_r[0]= winmax;
859                 size_r[1]= winmax/aspect;
860         } else {
861                 size_r[0]= winmax*aspect;
862                 size_r[1]= winmax;
863         }
864 }
865
866 void calc_viewborder(Scene *scene, ARegion *ar, View3D *v3d, rctf *viewborder_r)
867 {
868         RegionView3D *rv3d= ar->regiondata;
869         float zoomfac, size[2];
870         float dx= 0.0f, dy= 0.0f;
871         
872         view3d_get_viewborder_size(scene, ar, size);
873         
874         /* magic zoom calculation, no idea what
875                 * it signifies, if you find out, tell me! -zr
876                 */
877         /* simple, its magic dude!
878                 * well, to be honest, this gives a natural feeling zooming
879                 * with multiple keypad presses (ton)
880                 */
881         
882         zoomfac= (M_SQRT2 + rv3d->camzoom/50.0);
883         zoomfac= (zoomfac*zoomfac)*0.25;
884         
885         size[0]= size[0]*zoomfac;
886         size[1]= size[1]*zoomfac;
887         
888         /* center in window */
889         viewborder_r->xmin= 0.5*ar->winx - 0.5*size[0];
890         viewborder_r->ymin= 0.5*ar->winy - 0.5*size[1];
891         viewborder_r->xmax= viewborder_r->xmin + size[0];
892         viewborder_r->ymax= viewborder_r->ymin + size[1];
893         
894         dx= ar->winx*rv3d->camdx*zoomfac*2.0f;
895         dy= ar->winy*rv3d->camdy*zoomfac*2.0f;
896         
897         /* apply offset */
898         viewborder_r->xmin-= dx;
899         viewborder_r->ymin-= dy;
900         viewborder_r->xmax-= dx;
901         viewborder_r->ymax-= dy;
902         
903         if(v3d->camera && v3d->camera->type==OB_CAMERA) {
904                 Camera *cam= v3d->camera->data;
905                 float w = viewborder_r->xmax - viewborder_r->xmin;
906                 float h = viewborder_r->ymax - viewborder_r->ymin;
907                 float side = MAX2(w, h);
908                 
909                 viewborder_r->xmin+= cam->shiftx*side;
910                 viewborder_r->xmax+= cam->shiftx*side;
911                 viewborder_r->ymin+= cam->shifty*side;
912                 viewborder_r->ymax+= cam->shifty*side;
913         }
914 }
915
916 void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar)
917 {
918         RegionView3D *rv3d= ar->regiondata;
919         float size[2];
920         int im_width= (scene->r.size*scene->r.xsch)/100;
921         
922         view3d_get_viewborder_size(scene, ar, size);
923         
924         rv3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
925         rv3d->camzoom= CLAMPIS(rv3d->camzoom, -30, 300);
926 }
927
928
929 static void drawviewborder_flymode(ARegion *ar) 
930 {
931         /* draws 4 edge brackets that frame the safe area where the
932         mouse can move during fly mode without spinning the view */
933         float x1, x2, y1, y2;
934         
935         x1= 0.45*(float)ar->winx;
936         y1= 0.45*(float)ar->winy;
937         x2= 0.55*(float)ar->winx;
938         y2= 0.55*(float)ar->winy;
939         cpack(0);
940         
941         
942         glBegin(GL_LINES);
943         /* bottom left */
944         glVertex2f(x1,y1); 
945         glVertex2f(x1,y1+5);
946         
947         glVertex2f(x1,y1); 
948         glVertex2f(x1+5,y1);
949         
950         /* top right */
951         glVertex2f(x2,y2); 
952         glVertex2f(x2,y2-5);
953         
954         glVertex2f(x2,y2); 
955         glVertex2f(x2-5,y2);
956         
957         /* top left */
958         glVertex2f(x1,y2); 
959         glVertex2f(x1,y2-5);
960         
961         glVertex2f(x1,y2); 
962         glVertex2f(x1+5,y2);
963         
964         /* bottom right */
965         glVertex2f(x2,y1); 
966         glVertex2f(x2,y1+5);
967         
968         glVertex2f(x2,y1); 
969         glVertex2f(x2-5,y1);
970         glEnd();        
971 }
972
973
974 static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
975 {
976         extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);          // interface_panel.c
977         float fac, a;
978         float x1, x2, y1, y2;
979         float x3, y3, x4, y4;
980         rctf viewborder;
981         Camera *ca= NULL;
982         
983         if(v3d->camera==NULL)
984                 return;
985         if(v3d->camera->type==OB_CAMERA)
986                 ca = v3d->camera->data;
987         
988         calc_viewborder(scene, ar, v3d, &viewborder);
989         x1= viewborder.xmin;
990         y1= viewborder.ymin;
991         x2= viewborder.xmax;
992         y2= viewborder.ymax;
993         
994         /* passepartout, specified in camera edit buttons */
995         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001) {
996                 if (ca->passepartalpha == 1.0) {
997                         glColor3f(0, 0, 0);
998                 } else {
999                         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1000                         glEnable(GL_BLEND);
1001                         glColor4f(0, 0, 0, ca->passepartalpha);
1002                 }
1003                 if (x1 > 0.0)
1004                         glRectf(0.0, (float)ar->winy, x1, 0.0);
1005                 if (x2 < (float)ar->winx)
1006                         glRectf(x2, (float)ar->winy, (float)ar->winx, 0.0);
1007                 if (y2 < (float)ar->winy)
1008                         glRectf(x1, (float)ar->winy, x2, y2);
1009                 if (y2 > 0.0) 
1010                         glRectf(x1, y1, x2, 0.0);
1011                 
1012                 glDisable(GL_BLEND);
1013         }
1014         
1015         /* edge */
1016         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
1017         
1018         setlinestyle(0);
1019         UI_ThemeColor(TH_BACK);
1020         glRectf(x1, y1, x2, y2);
1021         
1022         setlinestyle(3);
1023         UI_ThemeColor(TH_WIRE);
1024         glRectf(x1, y1, x2, y2);
1025         
1026         /* border */
1027         if(scene->r.mode & R_BORDER) {
1028                 
1029                 cpack(0);
1030                 x3= x1+ scene->r.border.xmin*(x2-x1);
1031                 y3= y1+ scene->r.border.ymin*(y2-y1);
1032                 x4= x1+ scene->r.border.xmax*(x2-x1);
1033                 y4= y1+ scene->r.border.ymax*(y2-y1);
1034                 
1035                 cpack(0x4040FF);
1036                 glRectf(x3,  y3,  x4,  y4); 
1037         }
1038         
1039         /* safety border */
1040         if (ca && (ca->flag & CAM_SHOWTITLESAFE)) {
1041                 fac= 0.1;
1042                 
1043                 a= fac*(x2-x1);
1044                 x1+= a; 
1045                 x2-= a;
1046                 
1047                 a= fac*(y2-y1);
1048                 y1+= a;
1049                 y2-= a;
1050                 
1051                 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1052                 
1053                 uiSetRoundBox(15);
1054                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
1055         }
1056         
1057         setlinestyle(0);
1058         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1059         
1060         /* camera name - draw in highlighted text color */
1061         if (ca && (ca->flag & CAM_SHOWNAME)) {
1062                 UI_ThemeColor(TH_TEXT_HI);
1063                 BLF_draw_default(x1, y1-15, 0.0f, v3d->camera->id.name+2);
1064                 UI_ThemeColor(TH_WIRE);
1065         }
1066 }
1067
1068 /* *********************** backdraw for selection *************** */
1069
1070 void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
1071 {
1072         RegionView3D *rv3d= ar->regiondata;
1073         struct Base *base = scene->basact;
1074         rcti winrct;
1075
1076         if(base && (base->object->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT) ||
1077                      paint_facesel_test(base->object)));
1078         else if((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) &&
1079                 scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE));
1080         else if((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT));
1081         else if(scene->obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT));
1082         else {
1083                 v3d->flag &= ~V3D_INVALID_BACKBUF;
1084                 return;
1085         }
1086
1087         if( !(v3d->flag & V3D_INVALID_BACKBUF) ) return;
1088
1089 //      if(test) {
1090 //              if(qtest()) {
1091 //                      addafterqueue(ar->win, BACKBUFDRAW, 1);
1092 //                      return;
1093 //              }
1094 //      }
1095
1096         if(v3d->drawtype > OB_WIRE) v3d->zbuf= TRUE;
1097         
1098         glDisable(GL_DITHER);
1099
1100         region_scissor_winrct(ar, &winrct);
1101         glScissor(winrct.xmin, winrct.ymin, winrct.xmax - winrct.xmin, winrct.ymax - winrct.ymin);
1102
1103         glClearColor(0.0, 0.0, 0.0, 0.0); 
1104         if(v3d->zbuf) {
1105                 glEnable(GL_DEPTH_TEST);
1106                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1107         }
1108         else {
1109                 glClear(GL_COLOR_BUFFER_BIT);
1110                 glDisable(GL_DEPTH_TEST);
1111         }
1112         
1113         if(rv3d->rflag & RV3D_CLIPPING)
1114                 view3d_set_clipping(rv3d);
1115         
1116         G.f |= G_BACKBUFSEL;
1117         
1118         if(base && (base->lay & v3d->lay)) {
1119                 draw_object_backbufsel(scene, v3d, rv3d, base->object);
1120         }
1121
1122         v3d->flag &= ~V3D_INVALID_BACKBUF;
1123
1124         G.f &= ~G_BACKBUFSEL;
1125         v3d->zbuf= FALSE; 
1126         glDisable(GL_DEPTH_TEST);
1127         glEnable(GL_DITHER);
1128
1129         if(rv3d->rflag & RV3D_CLIPPING)
1130                 view3d_clr_clipping();
1131
1132         /* it is important to end a view in a transform compatible with buttons */
1133 //      persp(PERSP_WIN);  // set ortho
1134
1135 }
1136
1137 void view3d_validate_backbuf(ViewContext *vc)
1138 {
1139         if(vc->v3d->flag & V3D_INVALID_BACKBUF)
1140                 backdrawview3d(vc->scene, vc->ar, vc->v3d);
1141 }
1142
1143 /* samples a single pixel (copied from vpaint) */
1144 unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
1145 {
1146         unsigned int col;
1147         
1148         if(x >= vc->ar->winx || y >= vc->ar->winy) return 0;
1149         x+= vc->ar->winrct.xmin;
1150         y+= vc->ar->winrct.ymin;
1151         
1152         view3d_validate_backbuf(vc);
1153
1154         glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
1155         glReadBuffer(GL_BACK);  
1156         
1157         if(ENDIAN_ORDER==B_ENDIAN) SWITCH_INT(col);
1158         
1159         return WM_framebuffer_to_index(col);
1160 }
1161
1162 /* reads full rect, converts indices */
1163 ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
1164 {
1165         unsigned int *dr, *rd;
1166         struct ImBuf *ibuf, *ibuf1;
1167         int a;
1168         short xminc, yminc, xmaxc, ymaxc, xs, ys;
1169         
1170         /* clip */
1171         if(xmin<0) xminc= 0; else xminc= xmin;
1172         if(xmax >= vc->ar->winx) xmaxc= vc->ar->winx-1; else xmaxc= xmax;
1173         if(xminc > xmaxc) return NULL;
1174
1175         if(ymin<0) yminc= 0; else yminc= ymin;
1176         if(ymax >= vc->ar->winy) ymaxc= vc->ar->winy-1; else ymaxc= ymax;
1177         if(yminc > ymaxc) return NULL;
1178         
1179         ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect,0);
1180
1181         view3d_validate_backbuf(vc); 
1182         
1183         glReadPixels(vc->ar->winrct.xmin+xminc, vc->ar->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
1184         glReadBuffer(GL_BACK);  
1185
1186         if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1187
1188         a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
1189         dr= ibuf->rect;
1190         while(a--) {
1191                 if(*dr) *dr= WM_framebuffer_to_index(*dr);
1192                 dr++;
1193         }
1194         
1195         /* put clipped result back, if needed */
1196         if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) 
1197                 return ibuf;
1198         
1199         ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0);
1200         rd= ibuf->rect;
1201         dr= ibuf1->rect;
1202                 
1203         for(ys= ymin; ys<=ymax; ys++) {
1204                 for(xs= xmin; xs<=xmax; xs++, dr++) {
1205                         if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
1206                                 *dr= *rd;
1207                                 rd++;
1208                         }
1209                 }
1210         }
1211         IMB_freeImBuf(ibuf);
1212         return ibuf1;
1213 }
1214
1215 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
1216 unsigned int view3d_sample_backbuf_rect(ViewContext *vc, short mval[2], int size, 
1217                                                                                 unsigned int min, unsigned int max, int *dist, short strict, 
1218                                                                                 void *handle, unsigned int (*indextest)(void *handle, unsigned int index))
1219 {
1220         struct ImBuf *buf;
1221         unsigned int *bufmin, *bufmax, *tbuf;
1222         int minx, miny;
1223         int a, b, rc, nr, amount, dirvec[4][2];
1224         int distance=0;
1225         unsigned int index = 0;
1226         short indexok = 0;      
1227
1228         amount= (size-1)/2;
1229
1230         minx = mval[0]-(amount+1);
1231         miny = mval[1]-(amount+1);
1232         buf = view3d_read_backbuf(vc, minx, miny, minx+size-1, miny+size-1);
1233         if (!buf) return 0;
1234
1235         rc= 0;
1236         
1237         dirvec[0][0]= 1; dirvec[0][1]= 0;
1238         dirvec[1][0]= 0; dirvec[1][1]= -size;
1239         dirvec[2][0]= -1; dirvec[2][1]= 0;
1240         dirvec[3][0]= 0; dirvec[3][1]= size;
1241         
1242         bufmin = buf->rect;
1243         tbuf = buf->rect;
1244         bufmax = buf->rect + size*size;
1245         tbuf+= amount*size+ amount;
1246         
1247         for(nr=1; nr<=size; nr++) {
1248                 
1249                 for(a=0; a<2; a++) {
1250                         for(b=0; b<nr; b++, distance++) {
1251                                 if (*tbuf && *tbuf>=min && *tbuf<max) { //we got a hit
1252                                         if(strict){
1253                                                 indexok =  indextest(handle, *tbuf - min+1);
1254                                                 if(indexok){
1255                                                         *dist= (short) sqrt( (float)distance   );
1256                                                         index = *tbuf - min+1;
1257                                                         goto exit; 
1258                                                 }                                               
1259                                         }
1260                                         else{
1261                                                 *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong - 
1262                                                 index = *tbuf - min+1; // messy yah, but indices start at 1
1263                                                 goto exit;
1264                                         }                       
1265                                 }
1266                                 
1267                                 tbuf+= (dirvec[rc][0]+dirvec[rc][1]);
1268                                 
1269                                 if(tbuf<bufmin || tbuf>=bufmax) {
1270                                         goto exit;
1271                                 }
1272                         }
1273                         rc++;
1274                         rc &= 3;
1275                 }
1276         }
1277
1278 exit:
1279         IMB_freeImBuf(buf);
1280         return index;
1281 }
1282
1283
1284 /* ************************************************************* */
1285
1286 static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d)
1287 {
1288         RegionView3D *rv3d= ar->regiondata;
1289         BGpic *bgpic;
1290         Image *ima;
1291         ImBuf *ibuf= NULL;
1292         float vec[4], fac, asp, zoomx, zoomy;
1293         float x1, y1, x2, y2, cx, cy;
1294
1295
1296         for ( bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next ) {
1297
1298                 if(     (bgpic->view == 0) || /* zero for any */
1299                         (bgpic->view & (1<<rv3d->view)) || /* check agaist flags */
1300                         (rv3d->persp==RV3D_CAMOB && bgpic->view == (1<<RV3D_VIEW_CAMERA))
1301                 ) {
1302                         ima= bgpic->ima;
1303                         if(ima==NULL)
1304                                 continue;
1305                         BKE_image_user_calc_frame(&bgpic->iuser, CFRA, 0);
1306                         ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser);
1307                         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) )
1308                                 continue;
1309                         if(ibuf->channels!=4)
1310                                 continue;
1311                         if(ibuf->rect==NULL)
1312                                 IMB_rect_from_float(ibuf);
1313
1314                         if(rv3d->persp==RV3D_CAMOB) {
1315                                 rctf vb;
1316
1317                                 calc_viewborder(scene, ar, v3d, &vb);
1318
1319                                 x1= vb.xmin;
1320                                 y1= vb.ymin;
1321                                 x2= vb.xmax;
1322                                 y2= vb.ymax;
1323                         }
1324                         else {
1325                                 float sco[2];
1326
1327                                 /* calc window coord */
1328                                 initgrabz(rv3d, 0.0, 0.0, 0.0);
1329                                 window_to_3d_delta(ar, vec, 1, 0);
1330                                 fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
1331                                 fac= 1.0/fac;
1332
1333                                 asp= ( (float)ibuf->y)/(float)ibuf->x;
1334
1335                                 vec[0] = vec[1] = vec[2] = 0.0;
1336                                 view3d_project_float(ar, vec, sco, rv3d->persmat);
1337                                 cx = sco[0];
1338                                 cy = sco[1];
1339
1340                                 x1=  cx+ fac*(bgpic->xof-bgpic->size);
1341                                 y1=  cy+ asp*fac*(bgpic->yof-bgpic->size);
1342                                 x2=  cx+ fac*(bgpic->xof+bgpic->size);
1343                                 y2=  cy+ asp*fac*(bgpic->yof+bgpic->size);
1344                         }
1345
1346                         /* complete clip? */
1347
1348                         if(x2 < 0 ) continue;
1349                         if(y2 < 0 ) continue;
1350                         if(x1 > ar->winx ) continue;
1351                         if(y1 > ar->winy ) continue;
1352
1353                         zoomx= (x2-x1)/ibuf->x;
1354                         zoomy= (y2-y1)/ibuf->y;
1355
1356                         /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
1357                         if(zoomx < 1.0f || zoomy < 1.0f) {
1358                                 float tzoom= MIN2(zoomx, zoomy);
1359                                 int mip= 0;
1360
1361                                 if(ibuf->mipmap[0]==NULL)
1362                                         IMB_makemipmap(ibuf, 0, 0);
1363
1364                                 while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) {
1365                                         tzoom*= 2.0f;
1366                                         zoomx*= 2.0f;
1367                                         zoomy*= 2.0f;
1368                                         mip++;
1369                                 }
1370                                 if(mip>0)
1371                                         ibuf= ibuf->mipmap[mip-1];
1372                         }
1373
1374                         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1375                         glDepthMask(0);
1376
1377                         glEnable(GL_BLEND);
1378                         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
1379
1380                         glMatrixMode(GL_PROJECTION);
1381                         glPushMatrix();
1382                         glMatrixMode(GL_MODELVIEW);
1383                         glPushMatrix();
1384                         ED_region_pixelspace(ar);
1385
1386                         glPixelZoom(zoomx, zoomy);
1387                         glColor4f(1.0, 1.0, 1.0, 1.0-bgpic->blend);
1388                         glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
1389
1390                         glPixelZoom(1.0, 1.0);
1391                         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
1392
1393                         glMatrixMode(GL_PROJECTION);
1394                         glPopMatrix();
1395                         glMatrixMode(GL_MODELVIEW);
1396                         glPopMatrix();
1397
1398                         glDisable(GL_BLEND);
1399
1400                         glDepthMask(1);
1401                         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1402                 }
1403         }
1404 }
1405
1406 /* ****************** View3d afterdraw *************** */
1407
1408 typedef struct View3DAfter {
1409         struct View3DAfter *next, *prev;
1410         struct Base *base;
1411         int type, flag;
1412 } View3DAfter;
1413
1414 /* temp storage of Objects that need to be drawn as last */
1415 void add_view3d_after(View3D *v3d, Base *base, int type, int flag)
1416 {
1417         View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
1418         
1419         BLI_addtail(&v3d->afterdraw, v3da);
1420         v3da->base= base;
1421         v3da->type= type;
1422         v3da->flag= flag;
1423 }
1424
1425 /* clears zbuffer and draws it over */
1426 static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear)
1427 {
1428         View3DAfter *v3da, *next;
1429         int doit= 0;
1430         
1431         for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
1432                 if(v3da->type==V3D_XRAY) doit= 1;
1433         
1434         if(doit) {
1435                 if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
1436                 v3d->xray= TRUE;
1437                 
1438                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1439                         next= v3da->next;
1440                         if(v3da->type==V3D_XRAY) {
1441                                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1442                                 BLI_remlink(&v3d->afterdraw, v3da);
1443                                 MEM_freeN(v3da);
1444                         }
1445                 }
1446                 v3d->xray= FALSE;
1447         }
1448 }
1449
1450 /* disables write in zbuffer and draws it over */
1451 static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
1452 {
1453         View3DAfter *v3da, *next;
1454         
1455         glDepthMask(0);
1456         v3d->transp= TRUE;
1457         
1458         for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1459                 next= v3da->next;
1460                 if(v3da->type==V3D_TRANSP) {
1461                         draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1462                         BLI_remlink(&v3d->afterdraw, v3da);
1463                         MEM_freeN(v3da);
1464                 }
1465         }
1466         v3d->transp= FALSE;
1467         
1468         glDepthMask(1);
1469         
1470 }
1471
1472 /* *********************** */
1473
1474 /*
1475         In most cases call draw_dupli_objects,
1476         draw_dupli_objects_color was added because when drawing set dupli's
1477         we need to force the color
1478  */
1479 static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
1480 {       
1481         RegionView3D *rv3d= ar->regiondata;
1482         ListBase *lb;
1483         DupliObject *dob;
1484         Base tbase;
1485         BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
1486         GLuint displist=0;
1487         short transflag, use_displist= -1;      /* -1 is initialize */
1488         char dt, dtx;
1489         
1490         if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
1491         
1492         tbase.flag= OB_FROMDUPLI|base->flag;
1493         lb= object_duplilist(scene, base->object);
1494         
1495         for(dob= lb->first; dob; dob= dob->next) {
1496                 if(dob->no_draw);
1497                 else {
1498                         tbase.object= dob->ob;
1499                         
1500                         /* extra service: draw the duplicator in drawtype of parent */
1501                         /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
1502                         dt= tbase.object->dt;   tbase.object->dt= MIN2(tbase.object->dt, base->object->dt);
1503                         dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
1504                         
1505                         /* negative scale flag has to propagate */
1506                         transflag= tbase.object->transflag;
1507                         if(base->object->transflag & OB_NEG_SCALE)
1508                                 tbase.object->transflag ^= OB_NEG_SCALE;
1509                         
1510                         UI_ThemeColorBlend(color, TH_BACK, 0.5);
1511                         
1512                         /* generate displist, test for new object */
1513                         if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
1514                                 use_displist= -1;
1515                                 glDeleteLists(displist, 1);
1516                         }
1517                         /* generate displist */
1518                         if(use_displist == -1) {
1519                                 
1520                                 /* lamp drawing messes with matrices, could be handled smarter... but this works */
1521                                 if(dob->ob->type==OB_LAMP || dob->type==OB_DUPLIGROUP || !(bb_tmp= object_get_boundbox(dob->ob)))
1522                                         use_displist= 0;
1523                                 else {
1524                                         bb= *bb_tmp; /* must make a copy  */
1525
1526                                         /* disable boundbox check for list creation */
1527                                         object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
1528                                         /* need this for next part of code */
1529                                         unit_m4(dob->ob->obmat);        /* obmat gets restored */
1530                                         
1531                                         displist= glGenLists(1);
1532                                         glNewList(displist, GL_COMPILE);
1533                                         draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1534                                         glEndList();
1535                                         
1536                                         use_displist= 1;
1537                                         object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
1538                                 }
1539                         }
1540                         if(use_displist) {
1541                                 glMultMatrixf(dob->mat);
1542                                 if(boundbox_clip(rv3d, dob->mat, &bb))
1543                                         glCallList(displist);
1544                                 glLoadMatrixf(rv3d->viewmat);
1545                         }
1546                         else {
1547                                 copy_m4_m4(dob->ob->obmat, dob->mat);
1548                                 draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1549                         }
1550                         
1551                         tbase.object->dt= dt;
1552                         tbase.object->dtx= dtx;
1553                         tbase.object->transflag= transflag;
1554                 }
1555         }
1556         
1557         /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
1558         
1559         free_object_duplilist(lb);      /* does restore */
1560         
1561         if(use_displist)
1562                 glDeleteLists(displist, 1);
1563 }
1564
1565 static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
1566 {
1567         /* define the color here so draw_dupli_objects_color can be called
1568         * from the set loop */
1569         
1570         int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
1571         /* debug */
1572         if(base->object->dup_group && base->object->dup_group->id.us<1)
1573                 color= TH_REDALERT;
1574         
1575         draw_dupli_objects_color(scene, ar, v3d, base, color);
1576 }
1577
1578
1579 void view3d_update_depths(ARegion *ar, View3D *v3d)
1580 {
1581         RegionView3D *rv3d= ar->regiondata;
1582         
1583         /* Create storage for, and, if necessary, copy depth buffer */
1584         if(!rv3d->depths) rv3d->depths= MEM_callocN(sizeof(ViewDepths),"ViewDepths");
1585         if(rv3d->depths) {
1586                 ViewDepths *d= rv3d->depths;
1587                 if(d->w != ar->winx ||
1588                    d->h != ar->winy ||
1589                    !d->depths) {
1590                         d->w= ar->winx;
1591                         d->h= ar->winy;
1592                         if(d->depths)
1593                                 MEM_freeN(d->depths);
1594                         d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths");
1595                         d->damaged= 1;
1596                 }
1597                 
1598                 if(d->damaged) {
1599                         glReadPixels(ar->winrct.xmin,ar->winrct.ymin,d->w,d->h,
1600                                                  GL_DEPTH_COMPONENT,GL_FLOAT, d->depths);
1601                         
1602                         glGetDoublev(GL_DEPTH_RANGE,d->depth_range);
1603                         
1604                         d->damaged= 0;
1605                 }
1606         }
1607 }
1608
1609 void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
1610 {
1611         short zbuf= v3d->zbuf;
1612         RegionView3D *rv3d= ar->regiondata;
1613
1614         setwinmatrixview3d(ar, v3d, NULL);      /* 0= no pick rect */
1615         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
1616
1617         mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
1618         invert_m4_m4(rv3d->persinv, rv3d->persmat);
1619         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
1620
1621         glClear(GL_DEPTH_BUFFER_BIT);
1622
1623         glLoadMatrixf(rv3d->viewmat);
1624
1625         v3d->zbuf= TRUE;
1626         glEnable(GL_DEPTH_TEST);
1627
1628         draw_gpencil_3dview_ext(scene, ar, 1);
1629         
1630         v3d->zbuf= zbuf;
1631
1632 }
1633
1634 void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *))
1635 {
1636         RegionView3D *rv3d= ar->regiondata;
1637         Base *base;
1638         Scene *sce;
1639         short zbuf= v3d->zbuf;
1640         short flag= v3d->flag;
1641         float glalphaclip= U.glalphaclip;
1642         int obcenter_dia= U.obcenter_dia;
1643         /* temp set drawtype to solid */
1644         
1645         /* Setting these temporarily is not nice */
1646         v3d->flag &= ~V3D_SELECT_OUTLINE;
1647         U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
1648         U.obcenter_dia= 0;
1649         
1650         setwinmatrixview3d(ar, v3d, NULL);      /* 0= no pick rect */
1651         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
1652         
1653         mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
1654         invert_m4_m4(rv3d->persinv, rv3d->persmat);
1655         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
1656         
1657         glClear(GL_DEPTH_BUFFER_BIT);
1658         
1659         glLoadMatrixf(rv3d->viewmat);
1660 //      persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
1661         
1662         if(rv3d->rflag & RV3D_CLIPPING) {
1663                 view3d_set_clipping(rv3d);
1664         }
1665         
1666         v3d->zbuf= TRUE;
1667         glEnable(GL_DEPTH_TEST);
1668         
1669         /* draw set first */
1670         if(scene->set) {
1671                 for(SETLOOPER(scene->set, base)) {
1672                         if(v3d->lay & base->lay) {
1673                                 if (func == NULL || func(base)) {
1674                                         draw_object(scene, ar, v3d, base, 0);
1675                                         if(base->object->transflag & OB_DUPLI) {
1676                                                 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
1677                                         }
1678                                 }
1679                         }
1680                 }
1681         }
1682         
1683         for(base= scene->base.first; base; base= base->next) {
1684                 if(v3d->lay & base->lay) {
1685                         if (func == NULL || func(base)) {
1686                                 /* dupli drawing */
1687                                 if(base->object->transflag & OB_DUPLI) {
1688                                         draw_dupli_objects(scene, ar, v3d, base);
1689                                 }
1690                                 draw_object(scene, ar, v3d, base, 0);
1691                         }
1692                 }
1693         }
1694         
1695         /* this isnt that nice, draw xray objects as if they are normal */
1696         if (v3d->afterdraw.first) {
1697                 View3DAfter *v3da, *next;
1698                 int num = 0;
1699                 v3d->xray= TRUE;
1700                 
1701                 glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
1702                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1703                         next= v3da->next;
1704                         if(v3da->type==V3D_XRAY) {
1705                                 draw_object(scene, ar, v3d, v3da->base, 0);
1706                                 num++;
1707                         }
1708                         /* dont remove this time */
1709                 }
1710                 v3d->xray= FALSE;
1711                 
1712                 glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
1713                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1714                         next= v3da->next;
1715                         if(v3da->type==V3D_XRAY) {
1716                                 v3d->xray= TRUE; v3d->transp= FALSE;  
1717                         } else if (v3da->type==V3D_TRANSP) {
1718                                 v3d->xray= FALSE; v3d->transp= TRUE;
1719                         }
1720                         
1721                         draw_object(scene, ar, v3d, v3da->base, 0); /* Draw Xray or Transp objects normally */
1722                         BLI_remlink(&v3d->afterdraw, v3da);
1723                         MEM_freeN(v3da);
1724                 }
1725                 v3d->xray= FALSE;
1726                 v3d->transp= FALSE;
1727         }
1728         
1729         v3d->zbuf = zbuf;
1730         U.glalphaclip = glalphaclip;
1731         v3d->flag = flag;
1732         U.obcenter_dia= obcenter_dia;
1733 }
1734
1735 typedef struct View3DShadow {
1736         struct View3DShadow *next, *prev;
1737         GPULamp *lamp;
1738 } View3DShadow;
1739
1740 static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows)
1741 {
1742         GPULamp *lamp;
1743         Lamp *la = (Lamp*)ob->data;
1744         View3DShadow *shadow;
1745         
1746         lamp = GPU_lamp_from_blender(scene, ob, par);
1747         
1748         if(lamp) {
1749                 GPU_lamp_update(lamp, ob->lay, obmat);
1750                 GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
1751                 
1752                 if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
1753                         shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow");
1754                         shadow->lamp = lamp;
1755                         BLI_addtail(shadows, shadow);
1756                 }
1757         }
1758 }
1759
1760 static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
1761 {
1762         ListBase shadows;
1763         View3DShadow *shadow;
1764         Scene *sce;
1765         Base *base;
1766         Object *ob;
1767         
1768         shadows.first= shadows.last= NULL;
1769         
1770         /* update lamp transform and gather shadow lamps */
1771         for(SETLOOPER(scene, base)) {
1772                 ob= base->object;
1773                 
1774                 if(ob->type == OB_LAMP)
1775                         gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
1776                 
1777                 if (ob->transflag & OB_DUPLI) {
1778                         DupliObject *dob;
1779                         ListBase *lb = object_duplilist(scene, ob);
1780                         
1781                         for(dob=lb->first; dob; dob=dob->next)
1782                                 if(dob->ob->type==OB_LAMP)
1783                                         gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
1784                         
1785                         free_object_duplilist(lb);
1786                 }
1787         }
1788         
1789         /* render shadows after updating all lamps, nested object_duplilist
1790                 * don't work correct since it's replacing object matrices */
1791         for(shadow=shadows.first; shadow; shadow=shadow->next) {
1792                 /* this needs to be done better .. */
1793                 float viewmat[4][4], winmat[4][4];
1794                 int drawtype, lay, winsize, flag2;
1795                 
1796                 drawtype= v3d->drawtype;
1797                 lay= v3d->lay;
1798                 flag2= v3d->flag2 & V3D_SOLID_TEX;
1799                 
1800                 v3d->drawtype = OB_SOLID;
1801                 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
1802                 v3d->flag2 &= ~V3D_SOLID_TEX;
1803                 
1804                 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
1805 // XXX          drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1);
1806                 GPU_lamp_shadow_buffer_unbind(shadow->lamp);
1807                 
1808                 v3d->drawtype= drawtype;
1809                 v3d->lay= lay;
1810                 v3d->flag2 |= flag2;
1811         }
1812         
1813         BLI_freelistN(&shadows);
1814 }
1815
1816 /* *********************** customdata **************** */
1817
1818 /* goes over all modes and view3d settings */
1819 static CustomDataMask get_viewedit_datamask(bScreen *screen, Scene *scene, Object *ob)
1820 {
1821         CustomDataMask mask = CD_MASK_BAREMESH;
1822         ScrArea *sa;
1823         
1824         /* check if we need tfaces & mcols due to face select or texture paint */
1825         if(paint_facesel_test(ob) || (ob && ob->mode & OB_MODE_TEXTURE_PAINT))
1826                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
1827         
1828         /* check if we need tfaces & mcols due to view mode */
1829         for(sa = screen->areabase.first; sa; sa = sa->next) {
1830                 if(sa->spacetype == SPACE_VIEW3D) {
1831                         View3D *view = sa->spacedata.first;
1832                         if(view->drawtype == OB_SHADED) {
1833                                 /* this includes normals for mesh_create_shadedColors */
1834                                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
1835                         }
1836                         if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
1837                                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
1838                                 
1839                                 if(scene->gm.matmode == GAME_MAT_GLSL)
1840                                         mask |= CD_MASK_ORCO;
1841                         }
1842                 }
1843         }
1844         
1845         /* check if we need mcols due to vertex paint or weightpaint */
1846         if(ob) {
1847                 if(ob->mode & OB_MODE_VERTEX_PAINT)
1848                         mask |= CD_MASK_MCOL;
1849                 if(ob->mode & OB_MODE_WEIGHT_PAINT)
1850                         mask |= CD_MASK_WEIGHT_MCOL;
1851         }
1852
1853         return mask;
1854 }
1855
1856 static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4])
1857 {
1858         RegionView3D *rv3d= ar->regiondata;
1859
1860         /* setup window matrices */
1861         if(winmat)
1862                 copy_m4_m4(rv3d->winmat, winmat);
1863         else
1864                 setwinmatrixview3d(ar, v3d, NULL); /* NULL= no pickrect */
1865         
1866         /* setup view matrix */
1867         if(viewmat)
1868                 copy_m4_m4(rv3d->viewmat, viewmat);
1869         else
1870                 setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
1871         
1872         /* update utilitity matrices */
1873         mul_m4_m4m4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
1874         invert_m4_m4(rv3d->persinv, rv3d->persmat);
1875         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
1876         
1877         /* calculate pixelsize factor once, is used for lamps and obcenters */
1878         {
1879                 float len1, len2, vec[3];
1880                 
1881                 VECCOPY(vec, rv3d->persinv[0]);
1882                 len1= normalize_v3(vec);
1883                 VECCOPY(vec, rv3d->persinv[1]);
1884                 len2= normalize_v3(vec);
1885                 
1886                 rv3d->pixsize= 2.0f*(len1>len2?len1:len2);
1887                 
1888                 /* correct for window size */
1889                 if(ar->winx > ar->winy) rv3d->pixsize/= (float)ar->winx;
1890                 else rv3d->pixsize/= (float)ar->winy;
1891         }
1892         
1893         /* set for opengl */
1894         glMatrixMode(GL_PROJECTION);
1895         glLoadMatrixf(rv3d->winmat);
1896         glMatrixMode(GL_MODELVIEW);
1897         glLoadMatrixf(rv3d->viewmat);
1898 }
1899
1900 void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4])
1901 {
1902         Scene *sce;
1903         Base *base;
1904         int bwinx, bwiny;
1905
1906         glPushMatrix();
1907
1908         /* set temporary new size */
1909         bwinx= ar->winx;
1910         bwiny= ar->winy;
1911         ar->winx= winx;
1912         ar->winy= winy;
1913
1914         /* set flags */
1915         G.f |= G_RENDER_OGL;
1916         GPU_free_images();
1917
1918         /* set background color, fallback on the view background color */
1919         if(scene->world) {
1920                 glClearColor(scene->world->horr, scene->world->horg, scene->world->horb, 0.0);
1921         }
1922         else {
1923                 float col[3];
1924                 UI_GetThemeColor3fv(TH_BACK, col);
1925                 glClearColor(col[0], col[1], col[2], 0.0);      
1926         }
1927
1928         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1929
1930         /* setup view matrices */
1931         view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
1932
1933         /* set zbuffer */
1934         if(v3d->drawtype > OB_WIRE) {
1935                 v3d->zbuf= TRUE;
1936                 glEnable(GL_DEPTH_TEST);
1937         }
1938         else
1939                 v3d->zbuf= FALSE;
1940
1941         /* draw set first */
1942         if(scene->set) {
1943                 for(SETLOOPER(scene->set, base)) {
1944                         if(v3d->lay & base->lay) {
1945                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
1946                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
1947                                 
1948                                 if(base->object->transflag & OB_DUPLI)
1949                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
1950                         }
1951                 }
1952         }
1953         
1954         /* then draw not selected and the duplis, but skip editmode object */
1955         for(base= scene->base.first; base; base= base->next) {
1956                 if(v3d->lay & base->lay) {
1957                         /* dupli drawing */
1958                         if(base->object->transflag & OB_DUPLI)
1959                                 draw_dupli_objects(scene, ar, v3d, base);
1960
1961                         draw_object(scene, ar, v3d, base, 0);
1962                 }
1963         }
1964
1965         /* transp and X-ray afterdraw stuff */
1966         view3d_draw_transp(scene, ar, v3d);
1967         view3d_draw_xray(scene, ar, v3d, 1);    // clears zbuffer if it is used!
1968
1969         /* cleanup */
1970         if(v3d->zbuf) {
1971                 v3d->zbuf= FALSE;
1972                 glDisable(GL_DEPTH_TEST);
1973         }
1974
1975         /* draw grease-pencil stuff */
1976         draw_gpencil_3dview_ext(scene, ar, 1);
1977
1978         ED_region_pixelspace(ar);
1979
1980         /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
1981         draw_gpencil_3dview_ext(scene, ar, 0);
1982
1983         GPU_free_images();
1984
1985         /* restore size */
1986         ar->winx= bwinx;
1987         ar->winy= bwiny;
1988
1989         glPopMatrix();
1990 }
1991
1992 void view3d_main_area_draw(const bContext *C, ARegion *ar)
1993 {
1994         Scene *scene= CTX_data_scene(C);
1995         View3D *v3d = CTX_wm_view3d(C);
1996         RegionView3D *rv3d= CTX_wm_region_view3d(C);
1997         Scene *sce;
1998         Base *base;
1999         Object *ob;
2000         float col[3];
2001         int retopo= 0, sculptparticle= 0;
2002         Object *obact = OBACT;
2003         char *grid_unit= NULL;
2004
2005         /* from now on all object derived meshes check this */
2006         v3d->customdata_mask= get_viewedit_datamask(CTX_wm_screen(C), scene, obact);
2007         
2008         /* shadow buffers, before we setup matrices */
2009         if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
2010                 gpu_update_lamps_shadows(scene, v3d);
2011
2012         /* clear background */
2013         UI_GetThemeColor3fv(TH_BACK, col);
2014         glClearColor(col[0], col[1], col[2], 0.0); 
2015         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
2016         
2017         /* setup view matrices */
2018         view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
2019
2020         ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
2021
2022         if(rv3d->rflag & RV3D_CLIPPING)
2023                 view3d_draw_clipping(rv3d);
2024         
2025         /* set zbuffer after we draw clipping region */
2026         if(v3d->drawtype > OB_WIRE) {
2027                 v3d->zbuf= TRUE;
2028                 glEnable(GL_DEPTH_TEST);
2029         }
2030         else
2031                 v3d->zbuf= FALSE;
2032
2033         /* enables anti-aliasing for 3D view drawing */
2034         /*if (!(U.gameflags & USER_DISABLE_AA))
2035                 glEnable(GL_MULTISAMPLE_ARB);*/
2036         
2037         // needs to be done always, gridview is adjusted in drawgrid() now
2038         rv3d->gridview= v3d->grid;
2039         
2040         if(rv3d->view==0 || rv3d->persp!=0) {
2041                 drawfloor(scene, v3d);
2042                 if(rv3d->persp==2) {
2043                         if(scene->world) {
2044                                 if(scene->world->mode & WO_STARS) {
2045                                         RE_make_stars(NULL, scene, star_stuff_init_func, star_stuff_vertex_func,
2046                                                                   star_stuff_term_func);
2047                                 }
2048                         }
2049                         if(v3d->flag & V3D_DISPBGPICS) draw_bgpic(scene, ar, v3d);
2050                 }
2051         }
2052         else {
2053                 ED_region_pixelspace(ar);
2054                 drawgrid(&scene->unit, ar, v3d, &grid_unit);
2055                 /* XXX make function? replaces persp(1) */
2056                 glMatrixMode(GL_PROJECTION);
2057                 glLoadMatrixf(rv3d->winmat);
2058                 glMatrixMode(GL_MODELVIEW);
2059                 glLoadMatrixf(rv3d->viewmat);
2060                 
2061                 if(v3d->flag & V3D_DISPBGPICS) {
2062                         draw_bgpic(scene, ar, v3d);
2063                 }
2064         }
2065         
2066         if(rv3d->rflag & RV3D_CLIPPING)
2067                 view3d_set_clipping(rv3d);
2068         
2069         /* draw set first */
2070         if(scene->set) {
2071                 for(SETLOOPER(scene->set, base)) {
2072                         
2073                         if(v3d->lay & base->lay) {
2074                                 
2075                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2076                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
2077                                 
2078                                 if(base->object->transflag & OB_DUPLI) {
2079                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2080                                 }
2081                         }
2082                 }
2083                 
2084                 /* Transp and X-ray afterdraw stuff for sets is done later */
2085         }
2086         
2087         /* extra service in layerbuttons, showing used layers */
2088         v3d->lay_used = 0;
2089         
2090         /* then draw not selected and the duplis, but skip editmode object */
2091         for(base= scene->base.first; base; base= base->next) {
2092                 v3d->lay_used |= base->lay;
2093                 
2094                 if(v3d->lay & base->lay) {
2095                         
2096                         /* dupli drawing */
2097                         if(base->object->transflag & OB_DUPLI) {
2098                                 draw_dupli_objects(scene, ar, v3d, base);
2099                         }
2100                         if((base->flag & SELECT)==0) {
2101                                 if(base->object!=scene->obedit) 
2102                                         draw_object(scene, ar, v3d, base, 0);
2103                         }
2104                 }
2105         }
2106
2107 //      retopo= retopo_mesh_check() || retopo_curve_check();
2108         sculptparticle= (obact && obact->mode & (OB_MODE_PARTICLE_EDIT)) && !scene->obedit;
2109         if(retopo)
2110                 view3d_update_depths(ar, v3d);
2111         
2112         /* draw selected and editmode */
2113         for(base= scene->base.first; base; base= base->next) {
2114                 if(v3d->lay & base->lay) {
2115                         if (base->object==scene->obedit || ( base->flag & SELECT) ) 
2116                                 draw_object(scene, ar, v3d, base, 0);
2117                 }
2118         }
2119         
2120         if(!retopo && sculptparticle && !(obact && (obact->dtx & OB_DRAWXRAY))) {
2121                 view3d_update_depths(ar, v3d);
2122         }
2123         
2124         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
2125         
2126 //      REEB_draw();
2127         
2128 //      if(scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
2129         
2130         /* Transp and X-ray afterdraw stuff */
2131         view3d_draw_transp(scene, ar, v3d);
2132         view3d_draw_xray(scene, ar, v3d, 1);    // clears zbuffer if it is used!
2133         
2134         if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) {
2135                 view3d_update_depths(ar, v3d);
2136         }
2137         
2138         if(rv3d->rflag & RV3D_CLIPPING)
2139                 view3d_clr_clipping();
2140         
2141         BIF_draw_manipulator(C);
2142         
2143         /* Disable back anti-aliasing */
2144         /*if (!(U.gameflags & USER_DISABLE_AA))
2145                 glDisable(GL_MULTISAMPLE_ARB);*/
2146
2147         if(v3d->zbuf) {
2148                 v3d->zbuf= FALSE;
2149                 glDisable(GL_DEPTH_TEST);
2150         }
2151         
2152         /* draw grease-pencil stuff (3d-space strokes) */
2153         //if (v3d->flag2 & V3D_DISPGP)
2154                 draw_gpencil_3dview((bContext *)C, 1);
2155         
2156         BDR_drawSketch(C);
2157         
2158         ED_region_pixelspace(ar);
2159         
2160 //      retopo_paint_view_update(v3d);
2161 //      retopo_draw_paint_lines();
2162         
2163         /* Draw particle edit brush XXX (removed) */
2164         
2165         if(rv3d->persp>1) drawviewborder(scene, ar, v3d);
2166         if(rv3d->rflag & RV3D_FLYMODE) drawviewborder_flymode(ar);
2167         
2168         /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2169 //      if (v3d->flag2 & V3D_DISPGP)
2170                 draw_gpencil_3dview((bContext *)C, 0);
2171
2172         drawcursor(scene, ar, v3d);
2173         
2174         if(U.uiflag & USER_SHOW_ROTVIEWICON)
2175                 draw_view_axis(rv3d);
2176         else    
2177                 draw_view_icon(rv3d);
2178         
2179         /* XXX removed viewport fps */
2180         if(U.uiflag & USER_SHOW_VIEWPORTNAME) {
2181                 draw_viewport_name(ar, v3d);
2182         }
2183         if (grid_unit) { /* draw below the viewport name */
2184                 UI_ThemeColor(TH_TEXT_HI);
2185                 BLF_draw_default(10,  ar->winy-(USER_SHOW_VIEWPORTNAME?40:20), 0.0f, grid_unit);
2186         }
2187
2188         ob= OBACT;
2189         if(U.uiflag & USER_DRAWVIEWINFO) 
2190                 draw_selected_name(scene, ob, v3d);
2191
2192         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_PIXEL);
2193         
2194         /* XXX here was the blockhandlers for floating panels */
2195
2196         v3d->flag |= V3D_INVALID_BACKBUF;
2197 }
2198
2199