Camera tracking: support of tripod motion solving
[blender.git] / source / blender / editors / space_view3d / view3d_draw.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) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_view3d/view3d_draw.c
28  *  \ingroup spview3d
29  */
30
31
32 #include <string.h>
33 #include <stdio.h>
34 #include <math.h>
35
36 #include "DNA_armature_types.h"
37 #include "DNA_camera_types.h"
38 #include "DNA_customdata_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_group_types.h"
41 #include "DNA_key_types.h"
42 #include "DNA_lamp_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_world_types.h"
45
46 #include "MEM_guardedalloc.h"
47
48 #include "BLI_blenlib.h"
49 #include "BLI_math.h"
50 #include "BLI_rand.h"
51 #include "BLI_utildefines.h"
52
53 #include "BKE_anim.h"
54 #include "BKE_camera.h"
55 #include "BKE_context.h"
56 #include "BKE_customdata.h"
57 #include "BKE_image.h"
58 #include "BKE_key.h"
59 #include "BKE_object.h"
60 #include "BKE_global.h"
61 #include "BKE_paint.h"
62 #include "BKE_scene.h"
63 #include "BKE_screen.h"
64 #include "BKE_unit.h"
65 #include "BKE_movieclip.h"
66
67 #include "RE_engine.h"
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_screen.h"
83 #include "ED_space_api.h"
84 #include "ED_screen_types.h"
85 #include "ED_transform.h"
86
87 #include "UI_interface.h"
88 #include "UI_interface_icons.h"
89 #include "UI_resources.h"
90
91 #include "GPU_draw.h"
92 #include "GPU_material.h"
93 #include "GPU_extensions.h"
94
95 #include "view3d_intern.h"  // own include
96
97
98
99 static void star_stuff_init_func(void)
100 {
101         cpack(0xFFFFFF);
102         glPointSize(1.0);
103         glBegin(GL_POINTS);
104 }
105 static void star_stuff_vertex_func(float*i)
106 {
107         glVertex3fv(i);
108 }
109 static void star_stuff_term_func(void)
110 {
111         glEnd();
112 }
113
114 void circf(float x, float y, float rad)
115 {
116         GLUquadricObj *qobj = gluNewQuadric(); 
117         
118         gluQuadricDrawStyle(qobj, GLU_FILL); 
119         
120         glPushMatrix(); 
121         
122         glTranslatef(x, y, 0.0);
123         
124         gluDisk(qobj, 0.0,  rad, 32, 1);
125         
126         glPopMatrix(); 
127         
128         gluDeleteQuadric(qobj);
129 }
130
131 void circ(float x, float y, float rad)
132 {
133         GLUquadricObj *qobj = gluNewQuadric(); 
134         
135         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
136         
137         glPushMatrix(); 
138         
139         glTranslatef(x, y, 0.0);
140         
141         gluDisk(qobj, 0.0,  rad, 32, 1);
142         
143         glPopMatrix(); 
144         
145         gluDeleteQuadric(qobj);
146 }
147
148
149 /* ********* custom clipping *********** */
150
151 static void view3d_draw_clipping(RegionView3D *rv3d)
152 {
153         BoundBox *bb = rv3d->clipbb;
154
155         if (bb) {
156                 static unsigned int clipping_index[6][4] = {{0, 1, 2, 3},
157                                                             {0, 4, 5, 1},
158                                                             {4, 7, 6, 5},
159                                                             {7, 3, 2, 6},
160                                                             {1, 5, 6, 2},
161                                                             {7, 4, 0, 3}};
162
163                 UI_ThemeColorShade(TH_BACK, -8);
164
165                 glEnableClientState(GL_VERTEX_ARRAY);
166                 glVertexPointer(3, GL_FLOAT, 0, bb->vec);
167                 glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
168                 glDisableClientState(GL_VERTEX_ARRAY);
169
170         }
171 }
172
173 void ED_view3d_clipping_set(RegionView3D *rv3d)
174 {
175         double plane[4];
176         const unsigned int tot = (rv3d->viewlock) ? 4 : 6;
177         unsigned int a;
178
179         for (a = 0; a < tot; a++) {
180                 copy_v4db_v4fl(plane, rv3d->clip[a]);
181                 glClipPlane(GL_CLIP_PLANE0 + a, plane);
182                 glEnable(GL_CLIP_PLANE0 + a);
183         }
184 }
185
186 /* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
187 void ED_view3d_clipping_disable(void)
188 {
189         unsigned int a;
190
191         for (a = 0; a < 6; a++) {
192                 glDisable(GL_CLIP_PLANE0 + a);
193         }
194 }
195 void ED_view3d_clipping_enable(void)
196 {
197         unsigned int a;
198
199         for (a = 0; a < 6; a++) {
200                 glEnable(GL_CLIP_PLANE0 + a);
201         }
202 }
203
204 static int view3d_clipping_test(const float vec[3], float clip[][4])
205 {
206         float view[3];
207         copy_v3_v3(view, vec);
208
209         if (0.0f < clip[0][3] + dot_v3v3(view, clip[0]))
210                 if (0.0f < clip[1][3] + dot_v3v3(view, clip[1]))
211                         if (0.0f < clip[2][3] + dot_v3v3(view, clip[2]))
212                                 if (0.0f < clip[3][3] + dot_v3v3(view, clip[3]))
213                                         return 0;
214
215         return 1;
216 }
217
218 /* for 'local' ED_view3d_clipping_local must run first
219  * then all comparisons can be done in localspace */
220 int ED_view3d_clipping_test(RegionView3D *rv3d, const float vec[3], const int is_local)
221 {
222         return view3d_clipping_test(vec, is_local ? rv3d->clip_local : rv3d->clip);
223 }
224
225 /* ********* end custom clipping *********** */
226
227
228 static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, double dx)
229 {       
230         double verts[2][2];
231
232         x += (wx);
233         y += (wy);
234
235         /* set fixed 'Y' */
236         verts[0][1] = 0.0f;
237         verts[1][1] = (double)ar->winy;
238
239         /* iter over 'X' */
240         verts[0][0] = verts[1][0] = x - dx *floor(x / dx);
241         glEnableClientState(GL_VERTEX_ARRAY);
242         glVertexPointer(2, GL_DOUBLE, 0, verts);
243
244         while (verts[0][0] < ar->winx) {
245                 glDrawArrays(GL_LINES, 0, 2);
246                 verts[0][0] = verts[1][0] = verts[0][0] + dx;
247         }
248
249         /* set fixed 'X' */
250         verts[0][0] = 0.0f;
251         verts[1][0] = (double)ar->winx;
252
253         /* iter over 'Y' */
254         verts[0][1] = verts[1][1] = y - dx *floor(y / dx);
255         while (verts[0][1] < ar->winy) {
256                 glDrawArrays(GL_LINES, 0, 2);
257                 verts[0][1] = verts[1][1] = verts[0][1] + dx;
258         }
259
260         glDisableClientState(GL_VERTEX_ARRAY);
261 }
262
263 #define GRID_MIN_PX 6.0f
264
265 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
266 {
267         /* extern short bgpicmode; */
268         RegionView3D *rv3d = ar->regiondata;
269         double wx, wy, x, y, fw, fx, fy, dx;
270         double vec4[4];
271         unsigned char col[3], col2[3];
272
273         fx = rv3d->persmat[3][0];
274         fy = rv3d->persmat[3][1];
275         fw = rv3d->persmat[3][3];
276
277         wx = (ar->winx / 2.0); /* because of rounding errors, grid at wrong location */
278         wy = (ar->winy / 2.0);
279
280         x = (wx) * fx / fw;
281         y = (wy) * fy / fw;
282
283         vec4[0] = vec4[1] = v3d->grid;
284
285         vec4[2] = 0.0;
286         vec4[3] = 1.0;
287         mul_m4_v4d(rv3d->persmat, vec4);
288         fx = vec4[0];
289         fy = vec4[1];
290         fw = vec4[3];
291
292         dx = fabs(x - (wx) * fx / fw);
293         if (dx == 0) dx = fabs(y - (wy) * fy / fw);
294         
295         glDepthMask(0);     // disable write in zbuffer
296
297         /* check zoom out */
298         UI_ThemeColor(TH_GRID);
299         
300         if (unit->system) {
301                 /* Use GRID_MIN_PX*2 for units because very very small grid
302                  * items are less useful when dealing with units */
303                 void *usys;
304                 int len, i;
305                 double dx_scalar;
306                 float blend_fac;
307
308                 bUnit_GetSystem(&usys, &len, unit->system, B_UNIT_LENGTH);
309
310                 if (usys) {
311                         i = len;
312                         while (i--) {
313                                 double scalar = bUnit_GetScaler(usys, i);
314
315                                 dx_scalar = dx * scalar / unit->scale_length;
316                                 if (dx_scalar < (GRID_MIN_PX * 2))
317                                         continue;
318
319                                 /* Store the smallest drawn grid size units name so users know how big each grid cell is */
320                                 if (*grid_unit == NULL) {
321                                         *grid_unit = bUnit_GetNameDisplay(usys, i);
322                                         rv3d->gridview = (scalar * v3d->grid) / unit->scale_length;
323                                 }
324                                 blend_fac = 1 - ((GRID_MIN_PX * 2) / dx_scalar);
325
326                                 /* tweak to have the fade a bit nicer */
327                                 blend_fac = (blend_fac * blend_fac) * 2.0f;
328                                 CLAMP(blend_fac, 0.3f, 1.0f);
329
330
331                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, blend_fac);
332
333                                 drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
334                         }
335                 }
336         }
337         else {
338                 short sublines = v3d->gridsubdiv;
339
340                 if (dx < GRID_MIN_PX) {
341                         rv3d->gridview *= sublines;
342                         dx *= sublines;
343
344                         if (dx < GRID_MIN_PX) {
345                                 rv3d->gridview *= sublines;
346                                 dx *= sublines;
347
348                                 if (dx < GRID_MIN_PX) {
349                                         rv3d->gridview *= sublines;
350                                         dx *= sublines;
351                                         if (dx < GRID_MIN_PX) ;
352                                         else {
353                                                 UI_ThemeColor(TH_GRID);
354                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
355                                         }
356                                 }
357                                 else {  // start blending out
358                                         UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX * 6));
359                                         drawgrid_draw(ar, wx, wy, x, y, dx);
360
361                                         UI_ThemeColor(TH_GRID);
362                                         drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
363                                 }
364                         }
365                         else {  // start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX*10))
366                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX * 6));
367                                 drawgrid_draw(ar, wx, wy, x, y, dx);
368
369                                 UI_ThemeColor(TH_GRID);
370                                 drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
371                         }
372                 }
373                 else {
374                         if (dx > (GRID_MIN_PX * 10)) {      // start blending in
375                                 rv3d->gridview /= sublines;
376                                 dx /= sublines;
377                                 if (dx > (GRID_MIN_PX * 10)) {      // start blending in
378                                         rv3d->gridview /= sublines;
379                                         dx /= sublines;
380                                         if (dx > (GRID_MIN_PX * 10)) {
381                                                 UI_ThemeColor(TH_GRID);
382                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
383                                         }
384                                         else {
385                                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX * 6));
386                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
387                                                 UI_ThemeColor(TH_GRID);
388                                                 drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
389                                         }
390                                 }
391                                 else {
392                                         UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX * 6));
393                                         drawgrid_draw(ar, wx, wy, x, y, dx);
394                                         UI_ThemeColor(TH_GRID);
395                                         drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
396                                 }
397                         }
398                         else {
399                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX * 6));
400                                 drawgrid_draw(ar, wx, wy, x, y, dx);
401                                 UI_ThemeColor(TH_GRID);
402                                 drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
403                         }
404                 }
405         }
406
407
408         x += (wx);
409         y += (wy);
410         UI_GetThemeColor3ubv(TH_GRID, col);
411
412         setlinestyle(0);
413         
414         /* center cross */
415         /* horizontal line */
416         if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
417                 UI_make_axis_color(col, col2, 'Y');
418         else UI_make_axis_color(col, col2, 'X');
419         glColor3ubv(col2);
420         
421         fdrawline(0.0,  y,  (float)ar->winx,  y); 
422         
423         /* vertical line */
424         if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
425                 UI_make_axis_color(col, col2, 'Y');
426         else UI_make_axis_color(col, col2, 'Z');
427         glColor3ubv(col2);
428
429         fdrawline(x, 0.0, x, (float)ar->winy); 
430
431         glDepthMask(1);     // enable write in zbuffer
432 }
433 #undef GRID_MIN_PX
434
435 static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
436 {
437         float grid, grid_scale;
438         unsigned char col_grid[3];
439         const int gridlines = v3d->gridlines / 2;
440
441         if (v3d->gridlines < 3) return;
442         
443         grid_scale = v3d->grid;
444         /* use 'grid_scale' instead of 'v3d->grid' from now on */
445
446         /* apply units */
447         if (scene->unit.system) {
448                 void *usys;
449                 int len;
450
451                 bUnit_GetSystem(&usys, &len, scene->unit.system, B_UNIT_LENGTH);
452
453                 if (usys) {
454                         int i = bUnit_GetBaseUnit(usys);
455                         *grid_unit = bUnit_GetNameDisplay(usys, i);
456                         grid_scale = (grid_scale * (float)bUnit_GetScaler(usys, i)) / scene->unit.scale_length;
457                 }
458         }
459
460         grid = gridlines * grid_scale;
461
462         if (v3d->zbuf && scene->obedit) glDepthMask(0);  // for zbuffer-select
463
464         UI_GetThemeColor3ubv(TH_GRID, col_grid);
465
466         /* draw the Y axis and/or grid lines */
467         if (v3d->gridflag & V3D_SHOW_FLOOR) {
468                 float vert[4][3] = {{0.0f}};
469                 unsigned char col_bg[3];
470                 unsigned char col_grid_emphasise[3], col_grid_light[3];
471                 int a;
472                 int prev_emphasise = -1;
473
474                 UI_GetThemeColor3ubv(TH_BACK, col_bg);
475
476                 /* emphasise division lines lighter instead of darker, if background is darker than grid */
477                 UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
478                 UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
479                                         (((col_grid[0] + col_grid[1] + col_grid[2]) + 30) >
480                                          (col_bg[0] + col_bg[1] + col_bg[2])) ? 20 : -10);
481
482                 /* set fixed axis */
483                 vert[0][0] = vert[2][1] = grid;
484                 vert[1][0] = vert[3][1] = -grid;
485
486                 glEnableClientState(GL_VERTEX_ARRAY);
487                 glVertexPointer(3, GL_FLOAT, 0, vert);
488
489                 for (a = -gridlines; a <= gridlines; a++) {
490                         const float line = a * grid_scale;
491                         const int is_emphasise = (a % 10) == 0;
492
493                         if (is_emphasise != prev_emphasise) {
494                                 glColor3ubv(is_emphasise ? col_grid_emphasise : col_grid_light);
495                                 prev_emphasise = is_emphasise;
496                         }
497
498                         /* set variable axis */
499                         vert[0][1] = vert[1][1] =
500                         vert[2][0] = vert[3][0] = line;
501
502                         glDrawArrays(GL_LINES, 0, 4);
503                 }
504
505                 glDisableClientState(GL_VERTEX_ARRAY);
506
507                 GPU_print_error("sdsd");
508         }
509         
510         /* draw the Z axis line */      
511         /* check for the 'show Z axis' preference */
512         if (v3d->gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
513                 int axis;
514                 for (axis = 0; axis < 3; axis++) {
515                         if (v3d->gridflag & (V3D_SHOW_X << axis)) {
516                                 float vert[3];
517                                 unsigned char tcol[3];
518
519                                 UI_make_axis_color(col_grid, tcol, 'X' + axis);
520                                 glColor3ubv(tcol);
521
522                                 glBegin(GL_LINE_STRIP);
523                                 zero_v3(vert);
524                                 vert[axis] = grid;
525                                 glVertex3fv(vert);
526                                 vert[axis] = -grid;
527                                 glVertex3fv(vert);
528                                 glEnd();
529                         }
530                 }
531         }
532
533
534
535
536         if (v3d->zbuf && scene->obedit) glDepthMask(1);
537         
538 }
539
540 static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
541 {
542         int mx, my, co[2];
543         int flag;
544         
545         /* we don't want the clipping for cursor */
546         flag = v3d->flag;
547         v3d->flag = 0;
548         project_int(ar, give_cursor(scene, v3d), co);
549         v3d->flag = flag;
550         
551         mx = co[0];
552         my = co[1];
553         
554         if (mx != IS_CLIPPED) {
555                 setlinestyle(0); 
556                 cpack(0xFF);
557                 circ((float)mx, (float)my, 10.0);
558                 setlinestyle(4); 
559                 cpack(0xFFFFFF);
560                 circ((float)mx, (float)my, 10.0);
561                 setlinestyle(0);
562                 cpack(0x0);
563                 
564                 sdrawline(mx - 20, my, mx - 5, my);
565                 sdrawline(mx + 5, my, mx + 20, my);
566                 sdrawline(mx, my - 20, mx, my - 5);
567                 sdrawline(mx, my + 5, mx, my + 20);
568         }
569 }
570
571 /* Draw a live substitute of the view icon, which is always shown
572  * colors copied from transform_manipulator.c, we should keep these matching. */
573 static void draw_view_axis(RegionView3D *rv3d)
574 {
575         const float k = U.rvisize;   /* axis size */
576         const float toll = 0.5;      /* used to see when view is quasi-orthogonal */
577         const float start = k + 1.0f; /* axis center in screen coordinates, x=y */
578         float ydisp = 0.0;          /* vertical displacement to allow obj info text */
579         int bright = 25 * (float)U.rvibright + 5; /* axis alpha (rvibright has range 0-10) */
580
581         float vec[3];
582         float dx, dy;
583         
584         /* thickness of lines is proportional to k */
585         glLineWidth(2);
586
587         glEnable(GL_BLEND);
588         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
589
590         /* X */
591         vec[0] = 1;
592         vec[1] = vec[2] = 0;
593         mul_qt_v3(rv3d->viewquat, vec);
594         dx = vec[0] * k;
595         dy = vec[1] * k;
596
597         glColor4ub(220, 0, 0, bright);
598         glBegin(GL_LINES);
599         glVertex2f(start, start + ydisp);
600         glVertex2f(start + dx, start + dy + ydisp);
601         glEnd();
602
603         if (fabsf(dx) > toll || fabsf(dy) > toll) {
604                 BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "x", 1);
605         }
606         
607         /* BLF_draw_default disables blending */
608         glEnable(GL_BLEND);
609
610         /* Y */
611         vec[1] = 1;
612         vec[0] = vec[2] = 0;
613         mul_qt_v3(rv3d->viewquat, vec);
614         dx = vec[0] * k;
615         dy = vec[1] * k;
616
617         glColor4ub(0, 220, 0, bright);
618         glBegin(GL_LINES);
619         glVertex2f(start, start + ydisp);
620         glVertex2f(start + dx, start + dy + ydisp);
621         glEnd();
622
623         if (fabsf(dx) > toll || fabsf(dy) > toll) {
624                 BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "y", 1);
625         }
626
627         glEnable(GL_BLEND);
628         
629         /* Z */
630         vec[2] = 1;
631         vec[1] = vec[0] = 0;
632         mul_qt_v3(rv3d->viewquat, vec);
633         dx = vec[0] * k;
634         dy = vec[1] * k;
635
636         glColor4ub(30, 30, 220, bright);
637         glBegin(GL_LINES);
638         glVertex2f(start, start + ydisp);
639         glVertex2f(start + dx, start + dy + ydisp);
640         glEnd();
641
642         if (fabsf(dx) > toll || fabsf(dy) > toll) {
643                 BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "z", 1);
644         }
645
646         /* restore line-width */
647         
648         glLineWidth(1.0);
649         glDisable(GL_BLEND);
650 }
651
652 /* draw center and axis of rotation for ongoing 3D mouse navigation */
653 static void draw_rotation_guide(RegionView3D *rv3d)
654 {
655         float o[3]; // center of rotation
656         float end[3]; // endpoints for drawing
657
658         float color[4] = {0.0f, 0.4235f, 1.0f, 1.0f}; // bright blue so it matches device LEDs
659
660         negate_v3_v3(o, rv3d->ofs);
661
662         glEnable(GL_BLEND);
663         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
664         glShadeModel(GL_SMOOTH);
665         glPointSize(5);
666         glEnable(GL_POINT_SMOOTH);
667         glDepthMask(0); // don't overwrite zbuf
668
669         if (rv3d->rot_angle != 0.f) {
670                 // -- draw rotation axis --
671                 float scaled_axis[3];
672                 const float scale = rv3d->dist;
673                 mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
674
675
676                 glBegin(GL_LINE_STRIP);
677                 color[3] = 0.f; // more transparent toward the ends
678                 glColor4fv(color);
679                 add_v3_v3v3(end, o, scaled_axis);
680                 glVertex3fv(end);
681
682                 // color[3] = 0.2f + fabsf(rv3d->rot_angle); // modulate opacity with angle
683                 // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2
684
685                 color[3] = 0.5f; // more opaque toward the center
686                 glColor4fv(color);
687                 glVertex3fv(o);
688
689                 color[3] = 0.f;
690                 glColor4fv(color);
691                 sub_v3_v3v3(end, o, scaled_axis);
692                 glVertex3fv(end);
693                 glEnd();
694                 
695                 // -- draw ring around rotation center --
696                 {
697 #define     ROT_AXIS_DETAIL 13
698
699                         const float s = 0.05f * scale;
700                         const float step = 2.f * (float)(M_PI / ROT_AXIS_DETAIL);
701                         float angle;
702                         int i;
703
704                         float q[4]; // rotate ring so it's perpendicular to axis
705                         const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
706                         if (!upright) {
707                                 const float up[3] = {0.f, 0.f, 1.f};
708                                 float vis_angle, vis_axis[3];
709
710                                 cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
711                                 vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
712                                 axis_angle_to_quat(q, vis_axis, vis_angle);
713                         }
714
715                         color[3] = 0.25f; // somewhat faint
716                         glColor4fv(color);
717                         glBegin(GL_LINE_LOOP);
718                         for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) {
719                                 float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
720
721                                 if (!upright) {
722                                         mul_qt_v3(q, p);
723                                 }
724
725                                 add_v3_v3(p, o);
726                                 glVertex3fv(p);
727                         }
728                         glEnd();
729
730 #undef      ROT_AXIS_DETAIL
731                 }
732
733                 color[3] = 1.f; // solid dot
734         }
735         else
736                 color[3] = 0.5f;  // see-through dot
737
738         // -- draw rotation center --
739         glColor4fv(color);
740         glBegin(GL_POINTS);
741         glVertex3fv(o);
742         glEnd();
743
744         // find screen coordinates for rotation center, then draw pretty icon
745         // mul_m4_v3(rv3d->persinv, rot_center);
746         // UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
747         // ^^ just playing around, does not work
748
749         glDisable(GL_BLEND);
750         glDisable(GL_POINT_SMOOTH);
751         glDepthMask(1);
752 }
753
754 static void draw_view_icon(RegionView3D *rv3d)
755 {
756         BIFIconID icon;
757         
758         if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
759                 icon = ICON_AXIS_TOP;
760         else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
761                 icon = ICON_AXIS_FRONT;
762         else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
763                 icon = ICON_AXIS_SIDE;
764         else return;
765         
766         glEnable(GL_BLEND);
767         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
768         
769         UI_icon_draw(5.0, 5.0, icon);
770         
771         glDisable(GL_BLEND);
772 }
773
774 static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
775 {
776         const char *name = NULL;
777         
778         switch (rv3d->view) {
779                 case RV3D_VIEW_FRONT:
780                         if (rv3d->persp == RV3D_ORTHO) name = "Front Ortho";
781                         else name = "Front Persp";
782                         break;
783                 case RV3D_VIEW_BACK:
784                         if (rv3d->persp == RV3D_ORTHO) name = "Back Ortho";
785                         else name = "Back Persp";
786                         break;
787                 case RV3D_VIEW_TOP:
788                         if (rv3d->persp == RV3D_ORTHO) name = "Top Ortho";
789                         else name = "Top Persp";
790                         break;
791                 case RV3D_VIEW_BOTTOM:
792                         if (rv3d->persp == RV3D_ORTHO) name = "Bottom Ortho";
793                         else name = "Bottom Persp";
794                         break;
795                 case RV3D_VIEW_RIGHT:
796                         if (rv3d->persp == RV3D_ORTHO) name = "Right Ortho";
797                         else name = "Right Persp";
798                         break;
799                 case RV3D_VIEW_LEFT:
800                         if (rv3d->persp == RV3D_ORTHO) name = "Left Ortho";
801                         else name = "Left Persp";
802                         break;
803                         
804                 default:
805                         if (rv3d->persp == RV3D_CAMOB) {
806                                 if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
807                                         Camera *cam;
808                                         cam = v3d->camera->data;
809                                         name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
810                                 }
811                                 else {
812                                         name = "Object as Camera";
813                                 }
814                         }
815                         else {
816                                 name = (rv3d->persp == RV3D_ORTHO) ? "User Ortho" : "User Persp";
817                         }
818                         break;
819         }
820         
821         return name;
822 }
823
824 static void draw_viewport_name(ARegion *ar, View3D *v3d)
825 {
826         RegionView3D *rv3d = ar->regiondata;
827         const char *name = view3d_get_name(v3d, rv3d);
828         char tmpstr[24];
829         
830         if (v3d->localvd) {
831                 BLI_snprintf(tmpstr, sizeof(tmpstr), "%s (Local)", name);
832                 name = tmpstr;
833         }
834
835         if (name) {
836                 UI_ThemeColor(TH_TEXT_HI);
837                 BLF_draw_default_ascii(22,  ar->winy - 17, 0.0f, name, sizeof(tmpstr));
838         }
839 }
840
841 /* draw info beside axes in bottom left-corner: 
842  * framenum, object name, bone name (if available), marker name (if available)
843  */
844 static void draw_selected_name(Scene *scene, Object *ob)
845 {
846         char info[256], *markern;
847         short offset = 30;
848         
849         /* get name of marker on current frame (if available) */
850         markern = scene_find_marker_name(scene, CFRA);
851         
852         /* check if there is an object */
853         if (ob) {
854                 /* name(s) to display depends on type of object */
855                 if (ob->type == OB_ARMATURE) {
856                         bArmature *arm = ob->data;
857                         char *name = NULL;
858                         
859                         /* show name of active bone too (if possible) */
860                         if (arm->edbo) {
861
862                                 if (arm->act_edbone)
863                                         name = ((EditBone *)arm->act_edbone)->name;
864
865                         }
866                         else if (ob->mode & OB_MODE_POSE) {
867                                 if (arm->act_bone) {
868
869                                         if (arm->act_bone->layer & arm->layer)
870                                                 name = arm->act_bone->name;
871
872                                 }
873                         }
874                         if (name && markern)
875                                 BLI_snprintf(info, sizeof(info), "(%d) %s %s <%s>", CFRA, ob->id.name + 2, name, markern);
876                         else if (name)
877                                 BLI_snprintf(info, sizeof(info), "(%d) %s %s", CFRA, ob->id.name + 2, name);
878                         else
879                                 BLI_snprintf(info, sizeof(info), "(%d) %s", CFRA, ob->id.name + 2);
880                 }
881                 else if (ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
882                         Key *key = NULL;
883                         KeyBlock *kb = NULL;
884                         char shapes[MAX_NAME + 10];
885                         
886                         /* try to display active shapekey too */
887                         shapes[0] = '\0';
888                         key = ob_get_key(ob);
889                         if (key) {
890                                 kb = BLI_findlink(&key->block, ob->shapenr - 1);
891                                 if (kb) {
892                                         BLI_snprintf(shapes, sizeof(shapes), ": %s ", kb->name);
893                                         if (ob->shapeflag == OB_SHAPE_LOCK) {
894                                                 strcat(shapes, " (Pinned)");
895                                         }
896                                 }
897                         }
898                         
899                         if (markern)
900                                 BLI_snprintf(info, sizeof(info), "(%d) %s %s <%s>", CFRA, ob->id.name + 2, shapes, markern);
901                         else
902                                 BLI_snprintf(info, sizeof(info), "(%d) %s %s", CFRA, ob->id.name + 2, shapes);
903                 }
904                 else {
905                         /* standard object */
906                         if (markern)
907                                 BLI_snprintf(info, sizeof(info), "(%d) %s <%s>", CFRA, ob->id.name + 2, markern);
908                         else
909                                 BLI_snprintf(info, sizeof(info), "(%d) %s", CFRA, ob->id.name + 2);
910                 }
911                 
912                 /* color depends on whether there is a keyframe */
913                 if (id_frame_has_keyframe((ID *)ob, /*BKE_curframe(scene)*/ (float)(CFRA), ANIMFILTER_KEYS_LOCAL))
914                         UI_ThemeColor(TH_VERTEX_SELECT);
915                 else
916                         UI_ThemeColor(TH_TEXT_HI);
917         }
918         else {
919                 /* no object */
920                 if (markern)
921                         BLI_snprintf(info, sizeof(info), "(%d) <%s>", CFRA, markern);
922                 else
923                         BLI_snprintf(info, sizeof(info), "(%d)", CFRA);
924                 
925                 /* color is always white */
926                 UI_ThemeColor(TH_TEXT_HI);
927         }
928         
929         if (U.uiflag & USER_SHOW_ROTVIEWICON)
930                 offset = 14 + (U.rvisize * 2);
931
932         BLF_draw_default(offset,  10, 0.0f, info, sizeof(info));
933 }
934
935 static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
936                                  rctf *viewborder_r, short no_shift, short no_zoom)
937 {
938         CameraParams params;
939         rctf rect_view, rect_camera;
940
941         /* get viewport viewplane */
942         camera_params_init(&params);
943         camera_params_from_view3d(&params, v3d, rv3d);
944         if (no_zoom)
945                 params.zoom = 1.0f;
946         camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
947         rect_view = params.viewplane;
948
949         /* get camera viewplane */
950         camera_params_init(&params);
951         camera_params_from_object(&params, v3d->camera);
952         if (no_shift) {
953                 params.shiftx = 0.0f;
954                 params.shifty = 0.0f;
955         }
956         camera_params_compute_viewplane(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
957         rect_camera = params.viewplane;
958
959         /* get camera border within viewport */
960         viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / (rect_view.xmax - rect_view.xmin)) * ar->winx;
961         viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / (rect_view.xmax - rect_view.xmin)) * ar->winx;
962         viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / (rect_view.ymax - rect_view.ymin)) * ar->winy;
963         viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / (rect_view.ymax - rect_view.ymin)) * ar->winy;
964 }
965
966 void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float size_r[2])
967 {
968         rctf viewborder;
969
970         view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, TRUE, TRUE);
971         size_r[0] = viewborder.xmax - viewborder.xmin;
972         size_r[1] = viewborder.ymax - viewborder.ymin;
973 }
974
975 void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
976                                   rctf *viewborder_r, short no_shift)
977 {
978         view3d_camera_border(scene, ar, v3d, rv3d, viewborder_r, no_shift, FALSE);
979 }
980
981 static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac)
982 {
983         float x3, y3, x4, y4;
984
985         x3 = x1 + fac * (x2 - x1);
986         y3 = y1 + fac * (y2 - y1);
987         x4 = x1 + (1.0f - fac) * (x2 - x1);
988         y4 = y1 + (1.0f - fac) * (y2 - y1);
989
990         glBegin(GL_LINES);
991         glVertex2f(x1, y3);
992         glVertex2f(x2, y3);
993
994         glVertex2f(x1, y4);
995         glVertex2f(x2, y4);
996
997         glVertex2f(x3, y1);
998         glVertex2f(x3, y2);
999
1000         glVertex2f(x4, y1);
1001         glVertex2f(x4, y2);
1002         glEnd();
1003 }
1004
1005 /* harmonious triangle */
1006 static void drawviewborder_triangle(float x1, float x2, float y1, float y2, const char golden, const char dir)
1007 {
1008         float ofs;
1009         float w = x2 - x1;
1010         float h = y2 - y1;
1011
1012         glBegin(GL_LINES);
1013         if (w > h) {
1014                 if (golden) {
1015                         ofs = w * (1.0f - (1.0f / 1.61803399f));
1016                 }
1017                 else {
1018                         ofs = h * (h / w);
1019                 }
1020                 if (dir == 'B') SWAP(float, y1, y2);
1021
1022                 glVertex2f(x1, y1);
1023                 glVertex2f(x2, y2);
1024
1025                 glVertex2f(x2, y1);
1026                 glVertex2f(x1 + (w - ofs), y2);
1027
1028                 glVertex2f(x1, y2);
1029                 glVertex2f(x1 + ofs, y1);
1030         }
1031         else {
1032                 if (golden) {
1033                         ofs = h * (1.0f - (1.0f / 1.61803399f));
1034                 }
1035                 else {
1036                         ofs = w * (w / h);
1037                 }
1038                 if (dir == 'B') SWAP(float, x1, x2);
1039
1040                 glVertex2f(x1, y1);
1041                 glVertex2f(x2, y2);
1042
1043                 glVertex2f(x2, y1);
1044                 glVertex2f(x1, y1 + ofs);
1045
1046                 glVertex2f(x1, y2);
1047                 glVertex2f(x2, y1 + (h - ofs));
1048         }
1049         glEnd();
1050 }
1051
1052 static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
1053 {
1054         float fac, a;
1055         float x1, x2, y1, y2;
1056         float x1i, x2i, y1i, y2i;
1057         float x3, y3, x4, y4;
1058         rctf viewborder;
1059         Camera *ca = NULL;
1060         RegionView3D *rv3d = (RegionView3D *)ar->regiondata;
1061         
1062         if (v3d->camera == NULL)
1063                 return;
1064         if (v3d->camera->type == OB_CAMERA)
1065                 ca = v3d->camera->data;
1066         
1067         ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE);
1068         /* the offsets */
1069         x1 = viewborder.xmin;
1070         y1 = viewborder.ymin;
1071         x2 = viewborder.xmax;
1072         y2 = viewborder.ymax;
1073         
1074         /* apply offsets so the real 3D camera shows through */
1075
1076         /* note: quite un-scientific but without this bit extra
1077          * 0.0001 on the lower left the 2D border sometimes
1078          * obscures the 3D camera border */
1079         /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
1080          * but keep it here in case we need to remove the workaround */
1081         x1i = (int)(x1 - 1.0001f);
1082         y1i = (int)(y1 - 1.0001f);
1083         x2i = (int)(x2 + (1.0f - 0.0001f));
1084         y2i = (int)(y2 + (1.0f - 0.0001f));
1085         
1086         /* passepartout, specified in camera edit buttons */
1087         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
1088                 if (ca->passepartalpha == 1.0f) {
1089                         glColor3f(0, 0, 0);
1090                 }
1091                 else {
1092                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1093                         glEnable(GL_BLEND);
1094                         glColor4f(0, 0, 0, ca->passepartalpha);
1095                 }
1096                 if (x1i > 0.0f)
1097                         glRectf(0.0, (float)ar->winy, x1i, 0.0);
1098                 if (x2i < (float)ar->winx)
1099                         glRectf(x2i, (float)ar->winy, (float)ar->winx, 0.0);
1100                 if (y2i < (float)ar->winy)
1101                         glRectf(x1i, (float)ar->winy, x2i, y2i);
1102                 if (y2i > 0.0f)
1103                         glRectf(x1i, y1i, x2i, 0.0);
1104                 
1105                 glDisable(GL_BLEND);
1106         }
1107
1108         /* edge */
1109         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);      
1110
1111         setlinestyle(0);
1112
1113         UI_ThemeColor(TH_BACK);
1114                 
1115         glRectf(x1i, y1i, x2i, y2i);
1116
1117 #ifdef VIEW3D_CAMERA_BORDER_HACK
1118         if (view3d_camera_border_hack_test == TRUE) {
1119                 glColor4fv(view3d_camera_border_hack_col);
1120                 glRectf(x1i + 1, y1i + 1, x2i - 1, y2i - 1);
1121                 view3d_camera_border_hack_test = FALSE;
1122         }
1123 #endif
1124
1125         setlinestyle(3);
1126
1127         /* outer line not to confuse with object selecton */
1128         if (v3d->flag2 & V3D_LOCK_CAMERA) {
1129                 UI_ThemeColor(TH_REDALERT);
1130                 glRectf(x1i - 1, y1i - 1, x2i + 1, y2i + 1);
1131         }
1132
1133         UI_ThemeColor(TH_WIRE);
1134         glRectf(x1i, y1i, x2i, y2i);
1135
1136         /* border */
1137         if (scene->r.mode & R_BORDER) {
1138                 
1139                 cpack(0);
1140                 x3 = x1 + scene->r.border.xmin * (x2 - x1);
1141                 y3 = y1 + scene->r.border.ymin * (y2 - y1);
1142                 x4 = x1 + scene->r.border.xmax * (x2 - x1);
1143                 y4 = y1 + scene->r.border.ymax * (y2 - y1);
1144                 
1145                 cpack(0x4040FF);
1146                 glRectf(x3,  y3,  x4,  y4); 
1147         }
1148
1149         /* safety border */
1150         if (ca) {
1151                 if (ca->dtx & CAM_DTX_CENTER) {
1152                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1153
1154                         x3 = x1 + 0.5f * (x2 - x1);
1155                         y3 = y1 + 0.5f * (y2 - y1);
1156
1157                         glBegin(GL_LINES);
1158                         glVertex2f(x1, y3);
1159                         glVertex2f(x2, y3);
1160
1161                         glVertex2f(x3, y1);
1162                         glVertex2f(x3, y2);
1163                         glEnd();
1164                 }
1165
1166                 if (ca->dtx & CAM_DTX_CENTER_DIAG) {
1167                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1168
1169                         glBegin(GL_LINES);
1170                         glVertex2f(x1, y1);
1171                         glVertex2f(x2, y2);
1172
1173                         glVertex2f(x1, y2);
1174                         glVertex2f(x2, y1);
1175                         glEnd();
1176                 }
1177
1178                 if (ca->dtx & CAM_DTX_THIRDS) {
1179                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1180                         drawviewborder_grid3(x1, x2, y1, y2, 1.0f / 3.0f);
1181                 }
1182
1183                 if (ca->dtx & CAM_DTX_GOLDEN) {
1184                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1185                         drawviewborder_grid3(x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
1186                 }
1187
1188                 if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
1189                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1190                         drawviewborder_triangle(x1, x2, y1, y2, 0, 'A');
1191                 }
1192
1193                 if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
1194                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1195                         drawviewborder_triangle(x1, x2, y1, y2, 0, 'B');
1196                 }
1197
1198                 if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
1199                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1200                         drawviewborder_triangle(x1, x2, y1, y2, 1, 'A');
1201                 }
1202
1203                 if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
1204                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1205                         drawviewborder_triangle(x1, x2, y1, y2, 1, 'B');
1206                 }
1207
1208                 if (ca->flag & CAM_SHOWTITLESAFE) {
1209                         fac = 0.1;
1210
1211                         a = fac * (x2 - x1);
1212                         x1 += a;
1213                         x2 -= a;
1214
1215                         a = fac * (y2 - y1);
1216                         y1 += a;
1217                         y2 -= a;
1218
1219                         UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1220
1221                         uiSetRoundBox(UI_CNR_ALL);
1222                         uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
1223                 }
1224                 if (ca && (ca->flag & CAM_SHOWSENSOR)) {
1225                         /* determine sensor fit, and get sensor x/y, for auto fit we
1226                          * assume and square sensor and only use sensor_x */
1227                         float sizex = scene->r.xsch * scene->r.xasp;
1228                         float sizey = scene->r.ysch * scene->r.yasp;
1229                         int sensor_fit = camera_sensor_fit(ca->sensor_fit, sizex, sizey);
1230                         float sensor_x = ca->sensor_x;
1231                         float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y;
1232
1233                         /* determine sensor plane */
1234                         rctf rect;
1235
1236                         if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
1237                                 float sensor_scale = (x2i - x1i) / sensor_x;
1238                                 float sensor_height = sensor_scale * sensor_y;
1239
1240                                 rect.xmin = x1i;
1241                                 rect.xmax = x2i;
1242                                 rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f;
1243                                 rect.ymax = rect.ymin + sensor_height;
1244                         }
1245                         else {
1246                                 float sensor_scale = (y2i - y1i) / sensor_y;
1247                                 float sensor_width = sensor_scale * sensor_x;
1248
1249                                 rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f;
1250                                 rect.xmax = rect.xmin + sensor_width;
1251                                 rect.ymin = y1i;
1252                                 rect.ymax = y2i;
1253                         }
1254
1255                         /* draw */
1256                         UI_ThemeColorShade(TH_WIRE, 100);
1257                         uiDrawBox(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f);
1258                 }
1259         }
1260
1261         setlinestyle(0);
1262         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1263
1264         /* camera name - draw in highlighted text color */
1265         if (ca && (ca->flag & CAM_SHOWNAME)) {
1266                 UI_ThemeColor(TH_TEXT_HI);
1267                 BLF_draw_default(x1i, y1i - 15, 0.0f, v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
1268                 UI_ThemeColor(TH_WIRE);
1269         }
1270 }
1271
1272 /* *********************** backdraw for selection *************** */
1273
1274 static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
1275 {
1276         RegionView3D *rv3d = ar->regiondata;
1277         struct Base *base = scene->basact;
1278         int multisample_enabled;
1279         rcti winrct;
1280
1281         BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
1282
1283         if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
1284                      paint_facesel_test(base->object)))
1285         {
1286                 /* do nothing */
1287         }
1288         else if ((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) &&
1289                  scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE))
1290         {
1291                 /* do nothing */
1292         }
1293         else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
1294                  v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
1295         {
1296                 /* do nothing */
1297         }
1298         else if (scene->obedit && v3d->drawtype > OB_WIRE &&
1299                  (v3d->flag & V3D_ZBUF_SELECT)) {
1300                 /* do nothing */
1301         }
1302         else {
1303                 v3d->flag &= ~V3D_INVALID_BACKBUF;
1304                 return;
1305         }
1306
1307         if (!(v3d->flag & V3D_INVALID_BACKBUF) ) return;
1308
1309 //      if (test) {
1310 //              if (qtest()) {
1311 //                      addafterqueue(ar->win, BACKBUFDRAW, 1);
1312 //                      return;
1313 //              }
1314 //      }
1315
1316         if (v3d->drawtype > OB_WIRE) v3d->zbuf = TRUE;
1317         
1318         /* dithering and AA break color coding, so disable */
1319         glDisable(GL_DITHER);
1320
1321         multisample_enabled = glIsEnabled(GL_MULTISAMPLE_ARB);
1322         if (multisample_enabled)
1323                 glDisable(GL_MULTISAMPLE_ARB);
1324
1325         region_scissor_winrct(ar, &winrct);
1326         glScissor(winrct.xmin, winrct.ymin, winrct.xmax - winrct.xmin, winrct.ymax - winrct.ymin);
1327
1328         glClearColor(0.0, 0.0, 0.0, 0.0); 
1329         if (v3d->zbuf) {
1330                 glEnable(GL_DEPTH_TEST);
1331                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1332         }
1333         else {
1334                 glClear(GL_COLOR_BUFFER_BIT);
1335                 glDisable(GL_DEPTH_TEST);
1336         }
1337         
1338         if (rv3d->rflag & RV3D_CLIPPING)
1339                 ED_view3d_clipping_set(rv3d);
1340         
1341         G.f |= G_BACKBUFSEL;
1342         
1343         if (base && (base->lay & v3d->lay))
1344                 draw_object_backbufsel(scene, v3d, rv3d, base->object);
1345
1346         v3d->flag &= ~V3D_INVALID_BACKBUF;
1347         ar->swap = 0; /* mark invalid backbuf for wm draw */
1348
1349         G.f &= ~G_BACKBUFSEL;
1350         v3d->zbuf = FALSE;
1351         glDisable(GL_DEPTH_TEST);
1352         glEnable(GL_DITHER);
1353         if (multisample_enabled)
1354                 glEnable(GL_MULTISAMPLE_ARB);
1355
1356         if (rv3d->rflag & RV3D_CLIPPING)
1357                 ED_view3d_clipping_disable();
1358
1359         /* it is important to end a view in a transform compatible with buttons */
1360 //      persp(PERSP_WIN);  // set ortho
1361
1362 }
1363
1364 void view3d_validate_backbuf(ViewContext *vc)
1365 {
1366         if (vc->v3d->flag & V3D_INVALID_BACKBUF)
1367                 backdrawview3d(vc->scene, vc->ar, vc->v3d);
1368 }
1369
1370 /* samples a single pixel (copied from vpaint) */
1371 unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
1372 {
1373         unsigned int col;
1374         
1375         if (x >= vc->ar->winx || y >= vc->ar->winy) return 0;
1376         x += vc->ar->winrct.xmin;
1377         y += vc->ar->winrct.ymin;
1378         
1379         view3d_validate_backbuf(vc);
1380
1381         glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
1382         glReadBuffer(GL_BACK);  
1383         
1384         if (ENDIAN_ORDER == B_ENDIAN) SWITCH_INT(col);
1385         
1386         return WM_framebuffer_to_index(col);
1387 }
1388
1389 /* reads full rect, converts indices */
1390 ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
1391 {
1392         unsigned int *dr, *rd;
1393         struct ImBuf *ibuf, *ibuf1;
1394         int a;
1395         short xminc, yminc, xmaxc, ymaxc, xs, ys;
1396         
1397         /* clip */
1398         if (xmin < 0) xminc = 0; else xminc = xmin;
1399         if (xmax >= vc->ar->winx) xmaxc = vc->ar->winx - 1; else xmaxc = xmax;
1400         if (xminc > xmaxc) return NULL;
1401
1402         if (ymin < 0) yminc = 0; else yminc = ymin;
1403         if (ymax >= vc->ar->winy) ymaxc = vc->ar->winy - 1; else ymaxc = ymax;
1404         if (yminc > ymaxc) return NULL;
1405         
1406         ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect);
1407
1408         view3d_validate_backbuf(vc); 
1409         
1410         glReadPixels(vc->ar->winrct.xmin + xminc,
1411                      vc->ar->winrct.ymin + yminc,
1412                      (xmaxc - xminc + 1),
1413                      (ymaxc - yminc + 1),
1414                      GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
1415
1416         glReadBuffer(GL_BACK);  
1417
1418         if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1419
1420         a = (xmaxc - xminc + 1) * (ymaxc - yminc + 1);
1421         dr = ibuf->rect;
1422         while (a--) {
1423                 if (*dr) *dr = WM_framebuffer_to_index(*dr);
1424                 dr++;
1425         }
1426         
1427         /* put clipped result back, if needed */
1428         if (xminc == xmin && xmaxc == xmax && yminc == ymin && ymaxc == ymax)
1429                 return ibuf;
1430         
1431         ibuf1 = IMB_allocImBuf( (xmax - xmin + 1), (ymax - ymin + 1), 32, IB_rect);
1432         rd = ibuf->rect;
1433         dr = ibuf1->rect;
1434
1435         for (ys = ymin; ys <= ymax; ys++) {
1436                 for (xs = xmin; xs <= xmax; xs++, dr++) {
1437                         if (xs >= xminc && xs <= xmaxc && ys >= yminc && ys <= ymaxc) {
1438                                 *dr = *rd;
1439                                 rd++;
1440                         }
1441                 }
1442         }
1443         IMB_freeImBuf(ibuf);
1444         return ibuf1;
1445 }
1446
1447 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
1448 unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size,
1449                                         unsigned int min, unsigned int max, int *dist, short strict,
1450                                         void *handle, unsigned int (*indextest)(void *handle, unsigned int index))
1451 {
1452         struct ImBuf *buf;
1453         unsigned int *bufmin, *bufmax, *tbuf;
1454         int minx, miny;
1455         int a, b, rc, nr, amount, dirvec[4][2];
1456         int distance = 0;
1457         unsigned int index = 0;
1458         short indexok = 0;      
1459
1460         amount = (size - 1) / 2;
1461
1462         minx = mval[0] - (amount + 1);
1463         miny = mval[1] - (amount + 1);
1464         buf = view3d_read_backbuf(vc, minx, miny, minx + size - 1, miny + size - 1);
1465         if (!buf) return 0;
1466
1467         rc = 0;
1468         
1469         dirvec[0][0] = 1; dirvec[0][1] = 0;
1470         dirvec[1][0] = 0; dirvec[1][1] = -size;
1471         dirvec[2][0] = -1; dirvec[2][1] = 0;
1472         dirvec[3][0] = 0; dirvec[3][1] = size;
1473         
1474         bufmin = buf->rect;
1475         tbuf = buf->rect;
1476         bufmax = buf->rect + size * size;
1477         tbuf += amount * size + amount;
1478         
1479         for (nr = 1; nr <= size; nr++) {
1480                 
1481                 for (a = 0; a < 2; a++) {
1482                         for (b = 0; b < nr; b++, distance++) {
1483                                 if (*tbuf && *tbuf >= min && *tbuf < max) { //we got a hit
1484                                         if (strict) {
1485                                                 indexok =  indextest(handle, *tbuf - min + 1);
1486                                                 if (indexok) {
1487                                                         *dist = (short) sqrt( (float)distance);
1488                                                         index = *tbuf - min + 1;
1489                                                         goto exit; 
1490                                                 }                                               
1491                                         }
1492                                         else {
1493                                                 *dist = (short) sqrt( (float)distance); // XXX, this distance is wrong -
1494                                                 index = *tbuf - min + 1; // messy yah, but indices start at 1
1495                                                 goto exit;
1496                                         }                       
1497                                 }
1498                                 
1499                                 tbuf += (dirvec[rc][0] + dirvec[rc][1]);
1500                                 
1501                                 if (tbuf < bufmin || tbuf >= bufmax) {
1502                                         goto exit;
1503                                 }
1504                         }
1505                         rc++;
1506                         rc &= 3;
1507                 }
1508         }
1509
1510 exit:
1511         IMB_freeImBuf(buf);
1512         return index;
1513 }
1514
1515
1516 /* ************************************************************* */
1517
1518 static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int foreground)
1519 {
1520         RegionView3D *rv3d = ar->regiondata;
1521         BGpic *bgpic;
1522         Image *ima;
1523         MovieClip *clip;
1524         ImBuf *ibuf = NULL, *freeibuf;
1525         float vec[4], fac, asp, zoomx, zoomy;
1526         float x1, y1, x2, y2, cx, cy;
1527         int fg_flag = foreground ? V3D_BGPIC_FOREGROUND : 0;
1528
1529         for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1530
1531                 if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
1532                         continue;
1533
1534                 if ((bgpic->view == 0) || /* zero for any */
1535                     (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */
1536                     (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
1537                 {
1538                         /* disable individual images */
1539                         if ((bgpic->flag & V3D_BGPIC_DISABLED))
1540                                 continue;
1541
1542                         freeibuf = NULL;
1543                         if (bgpic->source == V3D_BGPIC_IMAGE) {
1544                                 ima = bgpic->ima;
1545                                 if (ima == NULL)
1546                                         continue;
1547                                 BKE_image_user_calc_frame(&bgpic->iuser, CFRA, 0);
1548                                 ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser);
1549                         }
1550                         else {
1551                                 clip = NULL;
1552
1553                                 if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
1554                                         if (scene->camera)
1555                                                 clip = object_get_movieclip(scene, scene->camera, 1);
1556                                 }
1557                                 else clip = bgpic->clip;
1558
1559                                 if (clip == NULL)
1560                                         continue;
1561
1562                                 BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
1563                                 ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
1564
1565                                 /* working with ibuf from image and clip has got different workflow now.
1566                                  * ibuf acquired from clip is referenced by cache system and should
1567                                  * be dereferenced after usage. */
1568                                 freeibuf = ibuf;
1569                         }
1570
1571                         if (ibuf == NULL)
1572                                 continue;
1573
1574                         if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
1575                                 if (freeibuf)
1576                                         IMB_freeImBuf(freeibuf);
1577
1578                                 continue;
1579                         }
1580
1581                         if (ibuf->rect == NULL)
1582                                 IMB_rect_from_float(ibuf);
1583
1584                         if (rv3d->persp == RV3D_CAMOB) {
1585                                 rctf vb;
1586
1587                                 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE);
1588
1589                                 x1 = vb.xmin;
1590                                 y1 = vb.ymin;
1591                                 x2 = vb.xmax;
1592                                 y2 = vb.ymax;
1593                         }
1594                         else {
1595                                 float sco[2];
1596                                 const float mval_f[2] = {1.0f, 0.0f};
1597
1598                                 /* calc window coord */
1599                                 initgrabz(rv3d, 0.0, 0.0, 0.0);
1600                                 ED_view3d_win_to_delta(ar, mval_f, vec);
1601                                 fac = maxf(fabsf(vec[0]), maxf(fabsf(vec[1]), fabsf(vec[2]))); /* largest abs axis */
1602                                 fac = 1.0f / fac;
1603
1604                                 asp = ( (float)ibuf->y) / (float)ibuf->x;
1605
1606                                 zero_v3(vec);
1607                                 ED_view3d_project_float_v2(ar, vec, sco, rv3d->persmat);
1608                                 cx = sco[0];
1609                                 cy = sco[1];
1610
1611                                 x1 =  cx + fac * (bgpic->xof - bgpic->size);
1612                                 y1 =  cy + asp * fac * (bgpic->yof - bgpic->size);
1613                                 x2 =  cx + fac * (bgpic->xof + bgpic->size);
1614                                 y2 =  cy + asp * fac * (bgpic->yof + bgpic->size);
1615                         }
1616
1617                         /* complete clip? */
1618
1619                         if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) {
1620                                 if (freeibuf)
1621                                         IMB_freeImBuf(freeibuf);
1622
1623                                 continue;
1624                         }
1625
1626                         zoomx = (x2 - x1) / ibuf->x;
1627                         zoomy = (y2 - y1) / ibuf->y;
1628
1629                         /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
1630                         if (zoomx < 1.0f || zoomy < 1.0f) {
1631                                 float tzoom = MIN2(zoomx, zoomy);
1632                                 int mip = 0;
1633
1634                                 if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
1635                                         IMB_remakemipmap(ibuf, 0);
1636                                         ibuf->userflags &= ~IB_MIPMAP_INVALID;
1637                                 }
1638                                 else if (ibuf->mipmap[0] == NULL)
1639                                         IMB_makemipmap(ibuf, 0);
1640
1641                                 while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
1642                                         tzoom *= 2.0f;
1643                                         zoomx *= 2.0f;
1644                                         zoomy *= 2.0f;
1645                                         mip++;
1646                                 }
1647                                 if (mip > 0)
1648                                         ibuf = ibuf->mipmap[mip - 1];
1649                         }
1650
1651                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1652                         glDepthMask(0);
1653
1654                         glEnable(GL_BLEND);
1655                         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
1656
1657                         glMatrixMode(GL_PROJECTION);
1658                         glPushMatrix();
1659                         glMatrixMode(GL_MODELVIEW);
1660                         glPushMatrix();
1661                         ED_region_pixelspace(ar);
1662
1663                         glPixelZoom(zoomx, zoomy);
1664                         glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
1665                         glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
1666
1667                         glPixelZoom(1.0, 1.0);
1668                         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
1669
1670                         glMatrixMode(GL_PROJECTION);
1671                         glPopMatrix();
1672                         glMatrixMode(GL_MODELVIEW);
1673                         glPopMatrix();
1674
1675                         glDisable(GL_BLEND);
1676
1677                         glDepthMask(1);
1678                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1679
1680                         if (freeibuf)
1681                                 IMB_freeImBuf(freeibuf);
1682                 }
1683         }
1684 }
1685
1686 static void draw_bgpics(Scene *scene, ARegion *ar, View3D *v3d, int foreground)
1687 {
1688         RegionView3D *rv3d = ar->regiondata;
1689
1690         if ((v3d->flag & V3D_DISPBGPICS) == 0)
1691                 return;
1692
1693         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
1694                 return;
1695
1696         if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
1697                 if (rv3d->persp == RV3D_CAMOB) {
1698                         draw_bgpic(scene, ar, v3d, foreground);
1699                 }
1700         }
1701         else {
1702                         draw_bgpic(scene, ar, v3d, foreground);
1703         }
1704 }
1705
1706 /* ****************** View3d afterdraw *************** */
1707
1708 typedef struct View3DAfter {
1709         struct View3DAfter *next, *prev;
1710         struct Base *base;
1711         int flag;
1712 } View3DAfter;
1713
1714 /* temp storage of Objects that need to be drawn as last */
1715 void add_view3d_after(ListBase *lb, Base *base, int flag)
1716 {
1717         View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
1718         BLI_addtail(lb, v3da);
1719         v3da->base = base;
1720         v3da->flag = flag;
1721 }
1722
1723 /* disables write in zbuffer and draws it over */
1724 static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
1725 {
1726         View3DAfter *v3da, *next;
1727         
1728         glDepthMask(0);
1729         v3d->transp = TRUE;
1730         
1731         for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
1732                 next = v3da->next;
1733                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1734                 BLI_remlink(&v3d->afterdraw_transp, v3da);
1735                 MEM_freeN(v3da);
1736         }
1737         v3d->transp = FALSE;
1738         
1739         glDepthMask(1);
1740         
1741 }
1742
1743 /* clears zbuffer and draws it over */
1744 static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear)
1745 {
1746         View3DAfter *v3da, *next;
1747
1748         if (clear && v3d->zbuf)
1749                 glClear(GL_DEPTH_BUFFER_BIT);
1750
1751         v3d->xray = TRUE;
1752         for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
1753                 next = v3da->next;
1754                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1755                 BLI_remlink(&v3d->afterdraw_xray, v3da);
1756                 MEM_freeN(v3da);
1757         }
1758         v3d->xray = FALSE;
1759 }
1760
1761
1762 /* clears zbuffer and draws it over */
1763 static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, int clear)
1764 {
1765         View3DAfter *v3da, *next;
1766
1767         if (clear && v3d->zbuf)
1768                 glClear(GL_DEPTH_BUFFER_BIT);
1769
1770         v3d->xray = TRUE;
1771         v3d->transp = TRUE;
1772         
1773         for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
1774                 next = v3da->next;
1775                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1776                 BLI_remlink(&v3d->afterdraw_xraytransp, v3da);
1777                 MEM_freeN(v3da);
1778         }
1779
1780         v3d->transp = FALSE;
1781         v3d->xray = FALSE;
1782
1783 }
1784
1785 /* *********************** */
1786
1787 /*
1788  * In most cases call draw_dupli_objects,
1789  * draw_dupli_objects_color was added because when drawing set dupli's
1790  * we need to force the color
1791  */
1792
1793 #if 0
1794 int dupli_ob_sort(void *arg1, void *arg2)
1795 {
1796         void *p1 = ((DupliObject *)arg1)->ob;
1797         void *p2 = ((DupliObject *)arg2)->ob;
1798         int val = 0;
1799         if (p1 < p2) val = -1;
1800         else if (p1 > p2) val = 1;
1801         return val;
1802 }
1803 #endif
1804
1805
1806 static DupliObject *dupli_step(DupliObject *dob)
1807 {
1808         while (dob && dob->no_draw)
1809                 dob = dob->next;
1810         return dob;
1811 }
1812
1813 static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
1814 {
1815         RegionView3D *rv3d = ar->regiondata;
1816         ListBase *lb;
1817         DupliObject *dob_prev = NULL, *dob, *dob_next = NULL;
1818         Base tbase;
1819         BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
1820         GLuint displist = 0;
1821         short transflag, use_displist = -1;  /* -1 is initialize */
1822         char dt, dtx;
1823         
1824         if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
1825         
1826         tbase.flag = OB_FROMDUPLI | base->flag;
1827         lb = object_duplilist(scene, base->object);
1828         // BLI_sortlist(lb, dupli_ob_sort); // might be nice to have if we have a dupli list with mixed objects.
1829
1830         dob = dupli_step(lb->first);
1831         if (dob) dob_next = dupli_step(dob->next);
1832
1833         for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
1834                 tbase.object = dob->ob;
1835
1836                 /* extra service: draw the duplicator in drawtype of parent */
1837                 /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
1838                 dt = tbase.object->dt;   tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
1839                 dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
1840
1841                 /* negative scale flag has to propagate */
1842                 transflag = tbase.object->transflag;
1843                 if (base->object->transflag & OB_NEG_SCALE)
1844                         tbase.object->transflag ^= OB_NEG_SCALE;
1845
1846                 UI_ThemeColorBlend(color, TH_BACK, 0.5);
1847
1848                 /* generate displist, test for new object */
1849                 if (dob_prev && dob_prev->ob != dob->ob) {
1850                         if (use_displist == 1)
1851                                 glDeleteLists(displist, 1);
1852
1853                         use_displist = -1;
1854                 }
1855
1856                 /* generate displist */
1857                 if (use_displist == -1) {
1858
1859                         /* note, since this was added, its checked dob->type==OB_DUPLIGROUP
1860                          * however this is very slow, it was probably needed for the NLA
1861                          * offset feature (used in group-duplicate.blend but no longer works in 2.5)
1862                          * so for now it should be ok to - campbell */
1863
1864                         if (/* if this is the last no need  to make a displist */
1865                             (dob_next == NULL || dob_next->ob != dob->ob) ||
1866                             /* lamp drawing messes with matrices, could be handled smarter... but this works */
1867                             (dob->ob->type == OB_LAMP) ||
1868                             (dob->type == OB_DUPLIGROUP && dob->animated) ||
1869                             !(bb_tmp = object_get_boundbox(dob->ob)))
1870                         {
1871                                 // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2);
1872                                 use_displist = 0;
1873                         }
1874                         else {
1875                                 // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2);
1876                                 bb = *bb_tmp; /* must make a copy  */
1877
1878                                 /* disable boundbox check for list creation */
1879                                 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
1880                                 /* need this for next part of code */
1881                                 unit_m4(dob->ob->obmat);    /* obmat gets restored */
1882
1883                                 displist = glGenLists(1);
1884                                 glNewList(displist, GL_COMPILE);
1885                                 draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1886                                 glEndList();
1887
1888                                 use_displist = 1;
1889                                 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
1890                         }
1891                 }
1892                 if (use_displist) {
1893                         glMultMatrixf(dob->mat);
1894                         if (ED_view3d_boundbox_clip(rv3d, dob->mat, &bb))
1895                                 glCallList(displist);
1896                         glLoadMatrixf(rv3d->viewmat);
1897                 }
1898                 else {
1899                         copy_m4_m4(dob->ob->obmat, dob->mat);
1900                         draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1901                 }
1902
1903                 tbase.object->dt = dt;
1904                 tbase.object->dtx = dtx;
1905                 tbase.object->transflag = transflag;
1906         }
1907         
1908         /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
1909         
1910         free_object_duplilist(lb);  /* does restore */
1911         
1912         if (use_displist)
1913                 glDeleteLists(displist, 1);
1914 }
1915
1916 static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
1917 {
1918         /* define the color here so draw_dupli_objects_color can be called
1919          * from the set loop */
1920         
1921         int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE;
1922         /* debug */
1923         if (base->object->dup_group && base->object->dup_group->id.us < 1)
1924                 color = TH_REDALERT;
1925         
1926         draw_dupli_objects_color(scene, ar, v3d, base, color);
1927 }
1928
1929 void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
1930 {
1931         int x, y, w, h; 
1932         rcti r;
1933         /* clamp rect by area */
1934
1935         r.xmin = 0;
1936         r.xmax = ar->winx - 1;
1937         r.ymin = 0;
1938         r.ymax = ar->winy - 1;
1939
1940         /* Constrain rect to depth bounds */
1941         BLI_isect_rcti(&r, rect, rect);
1942
1943         /* assign values to compare with the ViewDepths */
1944         x = rect->xmin;
1945         y = rect->ymin;
1946
1947         w = rect->xmax - rect->xmin;
1948         h = rect->ymax - rect->ymin;
1949
1950         if (w <= 0 || h <= 0) {
1951                 if (d->depths)
1952                         MEM_freeN(d->depths);
1953                 d->depths = NULL;
1954
1955                 d->damaged = FALSE;
1956         }
1957         else if (d->w != w ||
1958                  d->h != h ||
1959                  d->x != x ||
1960                  d->y != y ||
1961                  d->depths == NULL
1962                  )
1963         {
1964                 d->x = x;
1965                 d->y = y;
1966                 d->w = w;
1967                 d->h = h;
1968
1969                 if (d->depths)
1970                         MEM_freeN(d->depths);
1971
1972                 d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
1973                 
1974                 d->damaged = TRUE;
1975         }
1976
1977         if (d->damaged) {
1978                 glReadPixels(ar->winrct.xmin + d->x, ar->winrct.ymin + d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
1979                 glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
1980                 d->damaged = FALSE;
1981         }
1982 }
1983
1984 /* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
1985 void ED_view3d_depth_update(ARegion *ar)
1986 {
1987         RegionView3D *rv3d = ar->regiondata;
1988         
1989         /* Create storage for, and, if necessary, copy depth buffer */
1990         if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
1991         if (rv3d->depths) {
1992                 ViewDepths *d = rv3d->depths;
1993                 if (d->w != ar->winx ||
1994                     d->h != ar->winy ||
1995                     !d->depths)
1996                 {
1997                         d->w = ar->winx;
1998                         d->h = ar->winy;
1999                         if (d->depths)
2000                                 MEM_freeN(d->depths);
2001                         d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
2002                         d->damaged = 1;
2003                 }
2004                 
2005                 if (d->damaged) {
2006                         glReadPixels(ar->winrct.xmin, ar->winrct.ymin, d->w, d->h,
2007                                      GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
2008                         
2009                         glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
2010                         
2011                         d->damaged = 0;
2012                 }
2013         }
2014 }
2015
2016 /* utility function to find the closest Z value, use for autodepth */
2017 float view3d_depth_near(ViewDepths *d)
2018 {
2019         /* convert to float for comparisons */
2020         const float near = (float)d->depth_range[0];
2021         const float far_real = (float)d->depth_range[1];
2022         float far = far_real;
2023
2024         const float *depths = d->depths;
2025         float depth = FLT_MAX;
2026         int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
2027
2028         /* far is both the starting 'far' value
2029          * and the closest value found. */      
2030         while (i--) {
2031                 depth = *depths++;
2032                 if ((depth < far) && (depth > near)) {
2033                         far = depth;
2034                 }
2035         }
2036
2037         return far == far_real ? FLT_MAX : far;
2038 }
2039
2040 void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
2041 {
2042         short zbuf = v3d->zbuf;
2043         RegionView3D *rv3d = ar->regiondata;
2044
2045         setwinmatrixview3d(ar, v3d, NULL);  /* 0= no pick rect */
2046         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
2047
2048         mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
2049         invert_m4_m4(rv3d->persinv, rv3d->persmat);
2050         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
2051
2052         glClear(GL_DEPTH_BUFFER_BIT);
2053
2054         glLoadMatrixf(rv3d->viewmat);
2055
2056         v3d->zbuf = TRUE;
2057         glEnable(GL_DEPTH_TEST);
2058
2059         draw_gpencil_view3d(scene, v3d, ar, 1);
2060         
2061         v3d->zbuf = zbuf;
2062
2063 }
2064
2065 void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *))
2066 {
2067         RegionView3D *rv3d = ar->regiondata;
2068         Base *base;
2069         short zbuf = v3d->zbuf;
2070         short flag = v3d->flag;
2071         float glalphaclip = U.glalphaclip;
2072         int obcenter_dia = U.obcenter_dia;
2073         /* temp set drawtype to solid */
2074         
2075         /* Setting these temporarily is not nice */
2076         v3d->flag &= ~V3D_SELECT_OUTLINE;
2077         U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
2078         U.obcenter_dia = 0;
2079         
2080         setwinmatrixview3d(ar, v3d, NULL);  /* 0= no pick rect */
2081         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
2082         
2083         mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
2084         invert_m4_m4(rv3d->persinv, rv3d->persmat);
2085         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
2086         
2087         glClear(GL_DEPTH_BUFFER_BIT);
2088         
2089         glLoadMatrixf(rv3d->viewmat);
2090 //      persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
2091         
2092         if (rv3d->rflag & RV3D_CLIPPING) {
2093                 ED_view3d_clipping_set(rv3d);
2094         }
2095         
2096         v3d->zbuf = TRUE;
2097         glEnable(GL_DEPTH_TEST);
2098         
2099         /* draw set first */
2100         if (scene->set) {
2101                 Scene *sce_iter;
2102                 for (SETLOOPER(scene->set, sce_iter, base)) {
2103                         if (v3d->lay & base->lay) {
2104                                 if (func == NULL || func(base)) {
2105                                         draw_object(scene, ar, v3d, base, 0);
2106                                         if (base->object->transflag & OB_DUPLI) {
2107                                                 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2108                                         }
2109                                 }
2110                         }
2111                 }
2112         }
2113         
2114         for (base = scene->base.first; base; base = base->next) {
2115                 if (v3d->lay & base->lay) {
2116                         if (func == NULL || func(base)) {
2117                                 /* dupli drawing */
2118                                 if (base->object->transflag & OB_DUPLI) {
2119                                         draw_dupli_objects(scene, ar, v3d, base);
2120                                 }
2121                                 draw_object(scene, ar, v3d, base, 0);
2122                         }
2123                 }
2124         }
2125         
2126         /* this isn't that nice, draw xray objects as if they are normal */
2127         if (v3d->afterdraw_transp.first ||
2128             v3d->afterdraw_xray.first ||
2129             v3d->afterdraw_xraytransp.first)
2130         {
2131                 View3DAfter *v3da, *next;
2132                 int mask_orig;
2133
2134                 v3d->xray = TRUE;
2135                 
2136                 /* transp materials can change the depth mask, see #21388 */
2137                 glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
2138
2139
2140                 if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
2141                         glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
2142                         for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
2143                                 next = v3da->next;
2144                                 draw_object(scene, ar, v3d, v3da->base, 0);
2145                         }
2146                         glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
2147                 }
2148
2149                 /* draw 3 passes, transp/xray/xraytransp */
2150                 v3d->xray = FALSE;
2151                 v3d->transp = TRUE;
2152                 for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
2153                         next = v3da->next;
2154                         draw_object(scene, ar, v3d, v3da->base, 0);
2155                         BLI_remlink(&v3d->afterdraw_transp, v3da);
2156                         MEM_freeN(v3da);
2157                 }
2158
2159                 v3d->xray = TRUE;
2160                 v3d->transp = FALSE;
2161                 for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
2162                         next = v3da->next;
2163                         draw_object(scene, ar, v3d, v3da->base, 0);
2164                         BLI_remlink(&v3d->afterdraw_xray, v3da);
2165                         MEM_freeN(v3da);
2166                 }
2167
2168                 v3d->xray = TRUE;
2169                 v3d->transp = TRUE;
2170                 for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
2171                         next = v3da->next;
2172                         draw_object(scene, ar, v3d, v3da->base, 0);
2173                         BLI_remlink(&v3d->afterdraw_xraytransp, v3da);
2174                         MEM_freeN(v3da);
2175                 }
2176
2177                 
2178                 v3d->xray = FALSE;
2179                 v3d->transp = FALSE;
2180
2181                 glDepthMask(mask_orig);
2182         }
2183         
2184         if (rv3d->rflag & RV3D_CLIPPING)
2185                 ED_view3d_clipping_disable();
2186         
2187         v3d->zbuf = zbuf;
2188         if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
2189
2190         U.glalphaclip = glalphaclip;
2191         v3d->flag = flag;
2192         U.obcenter_dia = obcenter_dia;
2193 }
2194
2195 typedef struct View3DShadow {
2196         struct View3DShadow *next, *prev;
2197         GPULamp *lamp;
2198 } View3DShadow;
2199
2200 static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par,
2201                                    float obmat[][4], ListBase *shadows)
2202 {
2203         GPULamp *lamp;
2204         Lamp *la = (Lamp *)ob->data;
2205         View3DShadow *shadow;
2206         
2207         lamp = GPU_lamp_from_blender(scene, ob, par);
2208         
2209         if (lamp) {
2210                 GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
2211                 GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
2212                 
2213                 if ((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
2214                         shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
2215                         shadow->lamp = lamp;
2216                         BLI_addtail(shadows, shadow);
2217                 }
2218         }
2219 }
2220
2221 static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
2222 {
2223         ListBase shadows;
2224         View3DShadow *shadow;
2225         Scene *sce_iter;
2226         Base *base;
2227         Object *ob;
2228         
2229         shadows.first = shadows.last = NULL;
2230         
2231         /* update lamp transform and gather shadow lamps */
2232         for (SETLOOPER(scene, sce_iter, base)) {
2233                 ob = base->object;
2234                 
2235                 if (ob->type == OB_LAMP)
2236                         gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
2237                 
2238                 if (ob->transflag & OB_DUPLI) {
2239                         DupliObject *dob;
2240                         ListBase *lb = object_duplilist(scene, ob);
2241                         
2242                         for (dob = lb->first; dob; dob = dob->next)
2243                                 if (dob->ob->type == OB_LAMP)
2244                                         gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
2245                         
2246                         free_object_duplilist(lb);
2247                 }
2248         }
2249         
2250         /* render shadows after updating all lamps, nested object_duplilist
2251          * don't work correct since it's replacing object matrices */
2252         for (shadow = shadows.first; shadow; shadow = shadow->next) {
2253                 /* this needs to be done better .. */
2254                 float viewmat[4][4], winmat[4][4];
2255                 int drawtype, lay, winsize, flag2 = v3d->flag2;
2256                 ARegion ar = {NULL};
2257                 RegionView3D rv3d = {{{0}}};
2258                 
2259                 drawtype = v3d->drawtype;
2260                 lay = v3d->lay;
2261                 
2262                 v3d->drawtype = OB_SOLID;
2263                 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
2264                 v3d->flag2 &= ~V3D_SOLID_TEX;
2265                 v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
2266                 
2267                 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
2268
2269                 ar.regiondata = &rv3d;
2270                 ar.regiontype = RGN_TYPE_WINDOW;
2271                 rv3d.persp = RV3D_CAMOB;
2272                 copy_m4_m4(rv3d.winmat, winmat);
2273                 copy_m4_m4(rv3d.viewmat, viewmat);
2274                 invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
2275                 mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
2276                 invert_m4_m4(rv3d.persinv, rv3d.viewinv);
2277
2278                 ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE);
2279                 GPU_lamp_shadow_buffer_unbind(shadow->lamp);
2280                 
2281                 v3d->drawtype = drawtype;
2282                 v3d->lay = lay;
2283                 v3d->flag2 = flag2;
2284         }
2285         
2286         BLI_freelistN(&shadows);
2287 }
2288
2289 /* *********************** customdata **************** */
2290
2291 CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
2292 {
2293         CustomDataMask mask = 0;
2294
2295         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) ||
2296             ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
2297         {
2298                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
2299
2300                 if (scene_use_new_shading_nodes(scene)) {
2301                         if (v3d->drawtype == OB_MATERIAL)
2302                                 mask |= CD_MASK_ORCO;
2303                 }
2304                 else {
2305                         if (scene->gm.matmode == GAME_MAT_GLSL)
2306                                 mask |= CD_MASK_ORCO;
2307                 }
2308         }
2309
2310         return mask;
2311 }
2312
2313 CustomDataMask ED_view3d_object_datamask(Scene *scene)
2314 {
2315         Object *ob = scene->basact ? scene->basact->object : NULL;
2316         CustomDataMask mask = 0;
2317
2318         if (ob) {
2319                 /* check if we need tfaces & mcols due to face select or texture paint */
2320                 if (paint_facesel_test(ob) || (ob->mode & OB_MODE_TEXTURE_PAINT)) {
2321                         mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
2322                 }
2323
2324                 /* check if we need mcols due to vertex paint or weightpaint */
2325                 if (ob->mode & OB_MODE_VERTEX_PAINT) {
2326                         mask |= CD_MASK_MCOL;
2327                 }
2328
2329                 if (ob->mode & OB_MODE_WEIGHT_PAINT) {
2330                         mask |= CD_MASK_PREVIEW_MCOL;
2331                 }
2332         }
2333
2334         return mask;
2335 }
2336
2337 /* goes over all modes and view3d settings */
2338 CustomDataMask ED_view3d_screen_datamask(bScreen *screen)
2339 {
2340         Scene *scene = screen->scene;
2341         CustomDataMask mask = CD_MASK_BAREMESH;
2342         ScrArea *sa;
2343         
2344         /* check if we need tfaces & mcols due to view mode */
2345         for (sa = screen->areabase.first; sa; sa = sa->next) {
2346                 if (sa->spacetype == SPACE_VIEW3D) {
2347                         mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first);
2348                 }
2349         }
2350
2351         mask |= ED_view3d_object_datamask(scene);
2352
2353         return mask;
2354 }
2355
2356 void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4])
2357 {
2358         RegionView3D *rv3d = ar->regiondata;
2359
2360         /* setup window matrices */
2361         if (winmat)
2362                 copy_m4_m4(rv3d->winmat, winmat);
2363         else
2364                 setwinmatrixview3d(ar, v3d, NULL);  /* NULL= no pickrect */
2365
2366         /* setup view matrix */
2367         if (viewmat)
2368                 copy_m4_m4(rv3d->viewmat, viewmat);
2369         else
2370                 setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
2371
2372         /* update utilitity matrices */
2373         mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
2374         invert_m4_m4(rv3d->persinv, rv3d->persmat);
2375         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
2376
2377         /* calculate pixelsize factor once, is used for lamps and obcenters */
2378         {
2379                 /* note:  '1.0f / len_v3(v1)'  replaced  'len_v3(rv3d->viewmat[0])'
2380                  * because of float point precision problems at large values [#23908] */
2381                 float v1[3], v2[3];
2382                 float len1, len2;
2383
2384                 v1[0] = rv3d->persmat[0][0];
2385                 v1[1] = rv3d->persmat[1][0];
2386                 v1[2] = rv3d->persmat[2][0];
2387
2388                 v2[0] = rv3d->persmat[0][1];
2389                 v2[1] = rv3d->persmat[1][1];
2390                 v2[2] = rv3d->persmat[2][1];
2391
2392                 len1 = 1.0f / len_v3(v1);
2393                 len2 = 1.0f / len_v3(v2);
2394
2395                 rv3d->pixsize = (2.0f * MAX2(len1, len2)) / (float)MAX2(ar->winx, ar->winy);
2396         }
2397 }
2398
2399 static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4])
2400 {
2401         RegionView3D *rv3d = ar->regiondata;
2402
2403         ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
2404
2405         /* set for opengl */
2406         glMatrixMode(GL_PROJECTION);
2407         glLoadMatrixf(rv3d->winmat);
2408         glMatrixMode(GL_MODELVIEW);
2409         glLoadMatrixf(rv3d->viewmat);
2410 }
2411
2412 void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
2413                               int winx, int winy, float viewmat[][4], float winmat[][4],
2414                               int draw_background)
2415 {
2416         RegionView3D *rv3d = ar->regiondata;
2417         Base *base;
2418         float backcol[3];
2419         int bwinx, bwiny;
2420         rcti brect;
2421         ImBuf *bg_ibuf = NULL;
2422
2423         glPushMatrix();
2424
2425         /* set temporary new size */
2426         bwinx = ar->winx;
2427         bwiny = ar->winy;
2428         brect = ar->winrct;
2429         
2430         ar->winx = winx;
2431         ar->winy = winy;
2432         ar->winrct.xmin = 0;
2433         ar->winrct.ymin = 0;
2434         ar->winrct.xmax = winx;
2435         ar->winrct.ymax = winy;
2436         
2437         
2438         /* set flags */
2439         G.f |= G_RENDER_OGL;
2440
2441         /* free images which can have changed on frame-change
2442          * warning! can be slow so only free animated images - campbell */
2443         GPU_free_images_anim();
2444         
2445         /* shadow buffers, before we setup matrices */
2446         if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
2447                 gpu_update_lamps_shadows(scene, v3d);
2448
2449         /* if scene has got active clip, use it for render backdrop */
2450         if (draw_background && scene->clip && rv3d->persp == RV3D_CAMOB && v3d->camera) {
2451                 MovieClipUser user = {0};
2452
2453                 BKE_movieclip_user_set_frame(&user, CFRA);
2454                 bg_ibuf = BKE_movieclip_get_ibuf(scene->clip, &user);
2455         }
2456
2457         if (!bg_ibuf) {
2458                 /* set background color, fallback on the view background color
2459                  * (if active clip is set but frame is failed to load fallback to horizon color as background) */
2460                 if (scene->world) {
2461                         if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
2462                                 linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
2463                         else
2464                                 copy_v3_v3(backcol, &scene->world->horr);
2465                         glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
2466                 }
2467                 else {
2468                         UI_ThemeClearColor(TH_BACK);
2469                 }
2470         }
2471
2472         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2473
2474         if (bg_ibuf) {
2475                 unsigned char *pixels, *cp, *dst_cp;
2476                 int i;
2477
2478                 if (bg_ibuf->rect_float && !bg_ibuf->rect)
2479                         IMB_rect_from_float(bg_ibuf);
2480
2481                 dst_cp = pixels = MEM_callocN(4 * sizeof(unsigned char) * bg_ibuf->x * bg_ibuf->y, "draw offscreen clip pixels");
2482                 cp = (unsigned char *)bg_ibuf->rect;
2483                 for (i = 0; i < bg_ibuf->x * bg_ibuf->y; i++, cp += 4, dst_cp += 4) {
2484                         dst_cp[0] = cp[0];
2485                         dst_cp[1] = cp[1];
2486                         dst_cp[2] = cp[2];
2487                         dst_cp[3] = 255;
2488                 }
2489
2490                 glMatrixMode(GL_PROJECTION);
2491                 glPushMatrix();
2492                 glMatrixMode(GL_MODELVIEW);
2493                 glPushMatrix();
2494                 ED_region_pixelspace(ar);
2495
2496                 glPixelZoom((float)winx / bg_ibuf->x, (float)winy / bg_ibuf->y);
2497                 glaDrawPixelsTex(0, 0, bg_ibuf->x, bg_ibuf->y, GL_UNSIGNED_BYTE, pixels);
2498
2499                 glPixelZoom(1.0, 1.0);
2500
2501                 glMatrixMode(GL_PROJECTION);
2502                 glPopMatrix();
2503                 glMatrixMode(GL_MODELVIEW);
2504                 glPopMatrix();
2505
2506                 IMB_freeImBuf(bg_ibuf);
2507                 MEM_freeN(pixels);
2508         }
2509
2510         /* setup view matrices */
2511         view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
2512
2513         if (rv3d->rflag & RV3D_CLIPPING)
2514                 view3d_draw_clipping(rv3d);
2515
2516         /* set zbuffer */
2517         if (v3d->drawtype > OB_WIRE) {
2518                 v3d->zbuf = TRUE;
2519                 glEnable(GL_DEPTH_TEST);
2520         }
2521         else
2522                 v3d->zbuf = FALSE;
2523
2524         if (rv3d->rflag & RV3D_CLIPPING)
2525                 ED_view3d_clipping_set(rv3d);
2526
2527         /* draw set first */
2528         if (scene->set) {
2529                 Scene *sce_iter;
2530                 for (SETLOOPER(scene->set, sce_iter, base)) {
2531                         if (v3d->lay & base->lay) {
2532                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2533                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR | DRAW_SCENESET);
2534                                 
2535                                 if (base->object->transflag & OB_DUPLI)
2536                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2537                         }
2538                 }
2539         }
2540         
2541         /* then draw not selected and the duplis, but skip editmode object */
2542         for (base = scene->base.first; base; base = base->next) {
2543                 if (v3d->lay & base->lay) {
2544                         /* dupli drawing */
2545                         if (base->object->transflag & OB_DUPLI)
2546                                 draw_dupli_objects(scene, ar, v3d, base);
2547
2548                         draw_object(scene, ar, v3d, base, 0);
2549                 }
2550         }
2551
2552         /* must be before xray draw which clears the depth buffer */
2553         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2554         draw_gpencil_view3d(scene, v3d, ar, 1);
2555         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2556
2557         /* transp and X-ray afterdraw stuff */
2558         if (v3d->afterdraw_transp.first)     view3d_draw_transp(scene, ar, v3d);
2559         if (v3d->afterdraw_xray.first)       view3d_draw_xray(scene, ar, v3d, 1);         // clears zbuffer if it is used!
2560         if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, 1);
2561
2562         if (rv3d->rflag & RV3D_CLIPPING)
2563                 ED_view3d_clipping_disable();
2564
2565         /* cleanup */
2566         if (v3d->zbuf) {
2567                 v3d->zbuf = FALSE;
2568                 glDisable(GL_DEPTH_TEST);
2569         }
2570
2571         /* draw grease-pencil stuff */
2572         ED_region_pixelspace(ar);
2573
2574         /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2575         draw_gpencil_view3d(scene, v3d, ar, 0);
2576
2577         /* freeing the images again here could be done after the operator runs, leaving for now */
2578         GPU_free_images_anim();
2579
2580         /* restore size */
2581         ar->winx = bwinx;
2582         ar->winy = bwiny;
2583         ar->winrct = brect;
2584
2585         glPopMatrix();
2586
2587         // XXX, without this the sequencer flickers with opengl draw enabled, need to find out why - campbell
2588         glColor4ub(255, 255, 255, 255);
2589
2590         G.f &= ~G_RENDER_OGL;
2591 }
2592
2593 /* utility func for ED_view3d_draw_offscreen */
2594 ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
2595                                       int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256])
2596 {
2597         RegionView3D *rv3d = ar->regiondata;
2598         ImBuf *ibuf;
2599         GPUOffScreen *ofs;
2600         
2601         /* state changes make normal drawing go weird otherwise */
2602         glPushAttrib(GL_LIGHTING_BIT);
2603
2604         /* bind */
2605         ofs = GPU_offscreen_create(sizex, sizey, err_out);
2606         if (ofs == NULL)
2607                 return NULL;
2608
2609         GPU_offscreen_bind(ofs);
2610
2611         /* render 3d view */
2612         if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
2613                 CameraParams params;
2614
2615                 camera_params_init(&params);
2616                 camera_params_from_object(&params, v3d->camera);
2617                 camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
2618                 camera_params_compute_matrix(&params);
2619
2620                 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background);
2621         }
2622         else {
2623                 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background);
2624         }
2625
2626         /* read in pixels & stamp */
2627         ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
2628
2629         if (ibuf->rect_float)
2630                 GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
2631         else if (ibuf->rect)
2632                 GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
2633         
2634         //if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
2635         //      BKE_stamp_buf(scene, NULL, rr->rectf, rr->rectx, rr->recty, 4);
2636
2637         /* unbind */
2638         GPU_offscreen_unbind(ofs);
2639         GPU_offscreen_free(ofs);
2640
2641         glPopAttrib();
2642         
2643         if (ibuf->rect_float && ibuf->rect)
2644                 IMB_rect_from_float(ibuf);
2645         
2646         return ibuf;
2647 }
2648
2649 /* creates own 3d views, used by the sequencer */
2650 ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height,
2651                                              unsigned int flag, int drawtype, int draw_background, char err_out[256])
2652 {
2653         View3D v3d = {NULL};
2654         ARegion ar = {NULL};
2655         RegionView3D rv3d = {{{0}}};
2656
2657         /* connect data */
2658         v3d.regionbase.first = v3d.regionbase.last = &ar;
2659         ar.regiondata = &rv3d;
2660         ar.regiontype = RGN_TYPE_WINDOW;
2661
2662         v3d.camera = camera;
2663         v3d.lay = scene->lay;
2664         v3d.drawtype = drawtype;
2665         v3d.flag2 = V3D_RENDER_OVERRIDE;
2666
2667         rv3d.persp = RV3D_CAMOB;
2668
2669         copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
2670         normalize_m4(rv3d.viewinv);
2671         invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
2672
2673         {
2674                 CameraParams params;
2675
2676                 camera_params_init(&params);
2677                 camera_params_from_object(&params, v3d.camera);
2678                 camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
2679                 camera_params_compute_matrix(&params);
2680
2681                 copy_m4_m4(rv3d.winmat, params.winmat);
2682                 v3d.near = params.clipsta;
2683                 v3d.far = params.clipend;
2684                 v3d.lens = params.lens;
2685         }
2686
2687         mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
2688         invert_m4_m4(rv3d.persinv, rv3d.viewinv);
2689
2690         return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, draw_background, err_out);
2691
2692         // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty);
2693 }
2694
2695
2696 /* NOTE: the info that this uses is updated in ED_refresh_viewport_fps(), 
2697  * which currently gets called during SCREEN_OT_animation_step.
2698  */
2699 static void draw_viewport_fps(Scene *scene, ARegion *ar)
2700 {
2701         ScreenFrameRateInfo *fpsi = scene->fps_info;
2702         float fps;
2703         char printable[16];
2704         int i, tot;
2705         
2706         if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
2707                 return;
2708         
2709         printable[0] = '\0';
2710         
2711 #if 0
2712         /* this is too simple, better do an average */
2713         fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
2714 #else
2715         fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
2716         
2717         for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) {
2718                 if (fpsi->redrawtimes_fps[i]) {
2719                         fps += fpsi->redrawtimes_fps[i];
2720                         tot++;
2721                 }
2722         }
2723         if (tot) {
2724                 fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
2725                 
2726                 //fpsi->redrawtime_index++;
2727                 //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
2728                 //      fpsi->redrawtime = 0;
2729                 
2730                 fps = fps / tot;
2731         }
2732 #endif
2733
2734               /* is this more then half a frame behind? */
2735               if (fps + 0.5f < (float)(FPS)) {
2736                 UI_ThemeColor(TH_REDALERT);
2737                 BLI_snprintf(printable, sizeof(printable), "fps: %.2f", fps);
2738         } 
2739         else {
2740                 UI_ThemeColor(TH_TEXT_HI);
2741                 BLI_snprintf(printable, sizeof(printable), "fps: %i", (int)(fps + 0.5f));
2742         }
2743         
2744         BLF_draw_default_ascii(22,  ar->winy - 17, 0.0f, printable, sizeof(printable));
2745 }
2746
2747 static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar)
2748 {
2749         Scene *scene = CTX_data_scene(C);
2750         View3D *v3d = CTX_wm_view3d(C);
2751         RegionView3D *rv3d = CTX_wm_region_view3d(C);
2752         RenderEngineType *type;
2753
2754         /* create render engine */
2755         if (!rv3d->render_engine) {
2756                 type = RE_engines_find(scene->r.engine);
2757
2758                 if (!(type->view_update && type->view_draw))
2759                         return 0;
2760
2761                 rv3d->render_engine = RE_engine_create(type);
2762                 type->view_update(rv3d->render_engine, C);
2763         }
2764
2765         /* setup view matrices */
2766         view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
2767
2768         /* background draw */
2769         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2770         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2771
2772         ED_region_pixelspace(ar);
2773
2774         /* render result draw */
2775         if (v3d->flag & V3D_DISPBGPICS)
2776                 draw_bgpic(scene, ar, v3d, FALSE);
2777         else
2778                 fdrawcheckerboard(0, 0, ar->winx, ar->winy);
2779
2780         type = rv3d->render_engine->type;
2781         type->view_draw(rv3d->render_engine, C);
2782
2783         if (v3d->flag & V3D_DISPBGPICS)
2784                 draw_bgpic(scene, ar, v3d, TRUE);
2785
2786         return 1;
2787 }
2788
2789 static void view3d_main_area_draw_engine_info(RegionView3D *rv3d, ARegion *ar)
2790 {
2791         if (!rv3d->render_engine || !rv3d->render_engine->text)
2792                 return;
2793
2794         ED_region_info_draw(ar, rv3d->render_engine->text, 1, 0.25);
2795 }
2796
2797 /* warning: this function has duplicate drawing in ED_view3d_draw_offscreen() */
2798 static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit)
2799 {
2800         Scene *scene = CTX_data_scene(C);
2801         View3D *v3d = CTX_wm_view3d(C);
2802         RegionView3D *rv3d = CTX_wm_region_view3d(C);
2803         Base *base;
2804         float backcol[3];
2805         unsigned int lay_used;
2806
2807         /* shadow buffers, before we setup matrices */
2808         if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
2809                 gpu_update_lamps_shadows(scene, v3d);
2810         
2811         /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
2812         if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
2813                 rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
2814                 GPU_default_lights();
2815         }
2816
2817         /* clear background */
2818         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) {
2819                 if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
2820                         linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
2821                 else
2822                         copy_v3_v3(backcol, &scene->world->horr);
2823                 glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
2824         }
2825         else
2826                 UI_ThemeClearColor(TH_BACK);
2827
2828         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2829         
2830         /* setup view matrices */
2831         view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
2832
2833         ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
2834
2835         if (rv3d->rflag & RV3D_CLIPPING)
2836                 view3d_draw_clipping(rv3d);
2837         
2838         /* set zbuffer after we draw clipping region */
2839         if (v3d->drawtype > OB_WIRE) {
2840                 v3d->zbuf = TRUE;
2841                 glEnable(GL_DEPTH_TEST);
2842         }
2843         else
2844                 v3d->zbuf = FALSE;
2845
2846         /* enables anti-aliasing for 3D view drawing */
2847 #if 0
2848         if (!(U.gameflags & USER_DISABLE_AA))
2849                 glEnable(GL_MULTISAMPLE_ARB);
2850 #endif
2851
2852         // needs to be done always, gridview is adjusted in drawgrid() now
2853         rv3d->gridview = v3d->grid;
2854
2855         if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
2856                 if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2857                         drawfloor(scene, v3d, grid_unit);
2858                 }
2859                 if (rv3d->persp == RV3D_CAMOB) {
2860                         if (scene->world) {
2861                                 if (scene->world->mode & WO_STARS) {
2862                                         RE_make_stars(NULL, scene, star_stuff_init_func, star_stuff_vertex_func,
2863                                                       star_stuff_term_func);
2864                                 }
2865                         }
2866                 }
2867         }
2868         else {
2869                 if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2870                         ED_region_pixelspace(ar);
2871                         drawgrid(&scene->unit, ar, v3d, grid_unit);
2872                         /* XXX make function? replaces persp(1) */
2873                         glMatrixMode(GL_PROJECTION);
2874                         glLoadMatrixf(rv3d->winmat);
2875                         glMatrixMode(GL_MODELVIEW);
2876                         glLoadMatrixf(rv3d->viewmat);
2877                 }
2878         }
2879
2880         draw_bgpics(scene, ar, v3d, FALSE);
2881
2882         if (rv3d->rflag & RV3D_CLIPPING)
2883                 ED_view3d_clipping_set(rv3d);
2884
2885         /* draw set first */
2886         if (scene->set) {
2887                 Scene *sce_iter;
2888                 for (SETLOOPER(scene->set, sce_iter, base)) {
2889                         
2890                         if (v3d->lay & base->lay) {
2891                                 
2892                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2893                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR | DRAW_SCENESET);
2894                                 
2895                                 if (base->object->transflag & OB_DUPLI) {
2896                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2897                                 }
2898                         }
2899                 }
2900                 
2901                 /* Transp and X-ray afterdraw stuff for sets is done later */
2902         }
2903
2904         lay_used = 0;
2905
2906         /* then draw not selected and the duplis, but skip editmode object */
2907         for (base = scene->base.first; base; base = base->next) {
2908                 lay_used |= base->lay & ((1 << 20) - 1);
2909
2910                 if (v3d->lay & base->lay) {
2911                         
2912                         /* dupli drawing */
2913                         if (base->object->transflag & OB_DUPLI) {
2914                                 draw_dupli_objects(scene, ar, v3d, base);
2915                         }
2916                         if ((base->flag & SELECT) == 0) {
2917                                 if (base->object != scene->obedit)
2918                                         draw_object(scene, ar, v3d, base, 0);
2919                         }
2920                 }
2921         }
2922
2923         if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
2924                 /* find header and force tag redraw */
2925                 ScrArea *sa = CTX_wm_area(C);
2926                 ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
2927                 ED_region_tag_redraw(ar_header); /* can be NULL */
2928                 v3d->lay_used = lay_used;
2929         }
2930
2931         /* draw selected and editmode */
2932         for (base = scene->base.first; base; base = base->next) {
2933                 if (v3d->lay & base->lay) {
2934                         if (base->object == scene->obedit || (base->flag & SELECT) )
2935                                 draw_object(scene, ar, v3d, base, 0);
2936                 }
2937         }
2938
2939         draw_bgpics(scene, ar, v3d, TRUE);
2940
2941 //      REEB_draw();
2942
2943         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2944                 /* must be before xray draw which clears the depth buffer */
2945                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2946                 draw_gpencil_view3d(scene, v3d, ar, 1);
2947                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2948         }
2949
2950         /* Transp and X-ray afterdraw stuff */
2951         if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
2952         if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, 1);         // clears zbuffer if it is used!
2953         if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, 1);
2954         
2955         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
2956
2957         if (rv3d->rflag & RV3D_CLIPPING)
2958                 ED_view3d_clipping_disable();
2959         
2960         BIF_draw_manipulator(C);
2961
2962 #if 0
2963         /* Disable back anti-aliasing */
2964         if (!(U.gameflags & USER_DISABLE_AA))
2965                 glDisable(GL_MULTISAMPLE_ARB);
2966 #endif
2967
2968         if (v3d->zbuf) {
2969                 v3d->zbuf = FALSE;
2970                 glDisable(GL_DEPTH_TEST);
2971         }
2972
2973         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2974                 BDR_drawSketch(C);
2975         }
2976
2977         if ((U.ndof_flag & NDOF_SHOW_GUIDE) && (rv3d->viewlock != RV3D_LOCKED) && (rv3d->persp != RV3D_CAMOB))
2978                 // TODO: draw something else (but not this) during fly mode
2979                 draw_rotation_guide(rv3d);
2980
2981 }
2982
2983 static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const char *grid_unit)
2984 {
2985         Scene *scene = CTX_data_scene(C);
2986         View3D *v3d = CTX_wm_view3d(C);
2987         RegionView3D *rv3d = CTX_wm_region_view3d(C);
2988         bScreen *screen = CTX_wm_screen(C);
2989
2990         Object *ob;
2991
2992         if (rv3d->persp == RV3D_CAMOB)
2993                 drawviewborder(scene, ar, v3d);
2994
2995         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2996                 /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2997                 //      if (v3d->flag2 & V3D_DISPGP)
2998                 draw_gpencil_view3d(scene, v3d, ar, 0);
2999
3000                 drawcursor(scene, ar, v3d);
3001         }
3002         
3003         if (U.uiflag & USER_SHOW_ROTVIEWICON)
3004                 draw_view_axis(rv3d);
3005         else    
3006                 draw_view_icon(rv3d);
3007         
3008         ob = OBACT;
3009         if (U.uiflag & USER_DRAWVIEWINFO)
3010                 draw_selected_name(scene, ob);
3011
3012         if (rv3d->render_engine) {
3013                 view3d_main_area_draw_engine_info(rv3d, ar);
3014                 return;
3015         }
3016
3017         if ((U.uiflag & USER_SHOW_FPS) && screen->animtimer) {
3018                 draw_viewport_fps(scene, ar);
3019         }
3020         else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
3021                 draw_viewport_name(ar, v3d);
3022         }
3023
3024         if (grid_unit) { /* draw below the viewport name */
3025                 char numstr[32] = "";
3026
3027                 UI_ThemeColor(TH_TEXT_HI);
3028                 if (v3d->grid != 1.0f) {
3029                         BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
3030                 }
3031
3032                 BLF_draw_default_ascii(22,  ar->winy - (USER_SHOW_VIEWPORTNAME ? 40 : 20), 0.0f,
3033                                        numstr[0] ? numstr : grid_unit, sizeof(numstr));
3034         }
3035 }
3036
3037 void view3d_main_area_draw(const bContext *C, ARegion *ar)
3038 {
3039         View3D *v3d = CTX_wm_view3d(C);
3040         const char *grid_unit = NULL;
3041
3042         /* draw viewport using external renderer? */
3043         if (!(v3d->drawtype == OB_RENDER && view3d_main_area_draw_engine(C, ar))) {
3044                 /* draw viewport using opengl */
3045                 view3d_main_area_draw_objects(C, ar, &grid_unit);
3046                 ED_region_pixelspace(ar);
3047         }
3048         
3049         view3d_main_area_draw_info(C, ar, grid_unit);
3050
3051         v3d->flag |= V3D_INVALID_BACKBUF;
3052 }
3053