style cleanup: mostly whitespace around operators
[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(-1);
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.); 
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.); 
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)
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
1528
1529         for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
1530
1531                 if ((bgpic->view == 0) || /* zero for any */
1532                     (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */
1533                     (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
1534                 {
1535                         /* disable individual images */
1536                         if ((bgpic->flag & V3D_BGPIC_DISABLED))
1537                                 continue;
1538
1539                         freeibuf = NULL;
1540                         if (bgpic->source == V3D_BGPIC_IMAGE) {
1541                                 ima = bgpic->ima;
1542                                 if (ima == NULL)
1543                                         continue;
1544                                 BKE_image_user_calc_frame(&bgpic->iuser, CFRA, 0);
1545                                 ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser);
1546                         }
1547                         else {
1548                                 clip = NULL;
1549
1550                                 if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
1551                                         if (scene->camera)
1552                                                 clip = object_get_movieclip(scene, scene->camera, 1);
1553                                 }
1554                                 else clip = bgpic->clip;
1555
1556                                 if (clip == NULL)
1557                                         continue;
1558
1559                                 BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
1560                                 ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
1561
1562                                 /* working with ibuf from image and clip has got different workflow now.
1563                                  * ibuf acquired from clip is referenced by cache system and should
1564                                  * be dereferenced after usage. */
1565                                 freeibuf = ibuf;
1566                         }
1567
1568                         if (ibuf == NULL)
1569                                 continue;
1570
1571                         if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
1572                                 if (freeibuf)
1573                                         IMB_freeImBuf(freeibuf);
1574
1575                                 continue;
1576                         }
1577
1578                         if (ibuf->rect == NULL)
1579                                 IMB_rect_from_float(ibuf);
1580
1581                         if (rv3d->persp == RV3D_CAMOB) {
1582                                 rctf vb;
1583
1584                                 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE);
1585
1586                                 x1 = vb.xmin;
1587                                 y1 = vb.ymin;
1588                                 x2 = vb.xmax;
1589                                 y2 = vb.ymax;
1590                         }
1591                         else {
1592                                 float sco[2];
1593                                 const float mval_f[2] = {1.0f, 0.0f};
1594
1595                                 /* calc window coord */
1596                                 initgrabz(rv3d, 0.0, 0.0, 0.0);
1597                                 ED_view3d_win_to_delta(ar, mval_f, vec);
1598                                 fac = maxf(fabsf(vec[0]), maxf(fabsf(vec[1]), fabsf(vec[2]))); /* largest abs axis */
1599                                 fac = 1.0f / fac;
1600
1601                                 asp = ( (float)ibuf->y) / (float)ibuf->x;
1602
1603                                 zero_v3(vec);
1604                                 ED_view3d_project_float_v2(ar, vec, sco, rv3d->persmat);
1605                                 cx = sco[0];
1606                                 cy = sco[1];
1607
1608                                 x1 =  cx + fac * (bgpic->xof - bgpic->size);
1609                                 y1 =  cy + asp * fac * (bgpic->yof - bgpic->size);
1610                                 x2 =  cx + fac * (bgpic->xof + bgpic->size);
1611                                 y2 =  cy + asp * fac * (bgpic->yof + bgpic->size);
1612                         }
1613
1614                         /* complete clip? */
1615
1616                         if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) {
1617                                 if (freeibuf)
1618                                         IMB_freeImBuf(freeibuf);
1619
1620                                 continue;
1621                         }
1622
1623                         zoomx = (x2 - x1) / ibuf->x;
1624                         zoomy = (y2 - y1) / ibuf->y;
1625
1626                         /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
1627                         if (zoomx < 1.0f || zoomy < 1.0f) {
1628                                 float tzoom = MIN2(zoomx, zoomy);
1629                                 int mip = 0;
1630
1631                                 if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
1632                                         IMB_remakemipmap(ibuf, 0);
1633                                         ibuf->userflags &= ~IB_MIPMAP_INVALID;
1634                                 }
1635                                 else if (ibuf->mipmap[0] == NULL)
1636                                         IMB_makemipmap(ibuf, 0);
1637
1638                                 while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
1639                                         tzoom *= 2.0f;
1640                                         zoomx *= 2.0f;
1641                                         zoomy *= 2.0f;
1642                                         mip++;
1643                                 }
1644                                 if (mip > 0)
1645                                         ibuf = ibuf->mipmap[mip - 1];
1646                         }
1647
1648                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1649                         glDepthMask(0);
1650
1651                         glEnable(GL_BLEND);
1652                         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
1653
1654                         glMatrixMode(GL_PROJECTION);
1655                         glPushMatrix();
1656                         glMatrixMode(GL_MODELVIEW);
1657                         glPushMatrix();
1658                         ED_region_pixelspace(ar);
1659
1660                         glPixelZoom(zoomx, zoomy);
1661                         glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
1662                         glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
1663
1664                         glPixelZoom(1.0, 1.0);
1665                         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
1666
1667                         glMatrixMode(GL_PROJECTION);
1668                         glPopMatrix();
1669                         glMatrixMode(GL_MODELVIEW);
1670                         glPopMatrix();
1671
1672                         glDisable(GL_BLEND);
1673
1674                         glDepthMask(1);
1675                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1676
1677                         if (freeibuf)
1678                                 IMB_freeImBuf(freeibuf);
1679                 }
1680         }
1681 }
1682
1683 /* ****************** View3d afterdraw *************** */
1684
1685 typedef struct View3DAfter {
1686         struct View3DAfter *next, *prev;
1687         struct Base *base;
1688         int flag;
1689 } View3DAfter;
1690
1691 /* temp storage of Objects that need to be drawn as last */
1692 void add_view3d_after(ListBase *lb, Base *base, int flag)
1693 {
1694         View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
1695         BLI_addtail(lb, v3da);
1696         v3da->base = base;
1697         v3da->flag = flag;
1698 }
1699
1700 /* disables write in zbuffer and draws it over */
1701 static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
1702 {
1703         View3DAfter *v3da, *next;
1704         
1705         glDepthMask(0);
1706         v3d->transp = TRUE;
1707         
1708         for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
1709                 next = v3da->next;
1710                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1711                 BLI_remlink(&v3d->afterdraw_transp, v3da);
1712                 MEM_freeN(v3da);
1713         }
1714         v3d->transp = FALSE;
1715         
1716         glDepthMask(1);
1717         
1718 }
1719
1720 /* clears zbuffer and draws it over */
1721 static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear)
1722 {
1723         View3DAfter *v3da, *next;
1724
1725         if (clear && v3d->zbuf)
1726                 glClear(GL_DEPTH_BUFFER_BIT);
1727
1728         v3d->xray = TRUE;
1729         for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
1730                 next = v3da->next;
1731                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1732                 BLI_remlink(&v3d->afterdraw_xray, v3da);
1733                 MEM_freeN(v3da);
1734         }
1735         v3d->xray = FALSE;
1736 }
1737
1738
1739 /* clears zbuffer and draws it over */
1740 static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, int clear)
1741 {
1742         View3DAfter *v3da, *next;
1743
1744         if (clear && v3d->zbuf)
1745                 glClear(GL_DEPTH_BUFFER_BIT);
1746
1747         v3d->xray = TRUE;
1748         v3d->transp = TRUE;
1749         
1750         for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
1751                 next = v3da->next;
1752                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1753                 BLI_remlink(&v3d->afterdraw_xraytransp, v3da);
1754                 MEM_freeN(v3da);
1755         }
1756
1757         v3d->transp = FALSE;
1758         v3d->xray = FALSE;
1759
1760 }
1761
1762 /* *********************** */
1763
1764 /*
1765  * In most cases call draw_dupli_objects,
1766  * draw_dupli_objects_color was added because when drawing set dupli's
1767  * we need to force the color
1768  */
1769
1770 #if 0
1771 int dupli_ob_sort(void *arg1, void *arg2)
1772 {
1773         void *p1 = ((DupliObject *)arg1)->ob;
1774         void *p2 = ((DupliObject *)arg2)->ob;
1775         int val = 0;
1776         if (p1 < p2) val = -1;
1777         else if (p1 > p2) val = 1;
1778         return val;
1779 }
1780 #endif
1781
1782
1783 static DupliObject *dupli_step(DupliObject *dob)
1784 {
1785         while (dob && dob->no_draw)
1786                 dob = dob->next;
1787         return dob;
1788 }
1789
1790 static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
1791 {
1792         RegionView3D *rv3d = ar->regiondata;
1793         ListBase *lb;
1794         DupliObject *dob_prev = NULL, *dob, *dob_next = NULL;
1795         Base tbase;
1796         BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
1797         GLuint displist = 0;
1798         short transflag, use_displist = -1;  /* -1 is initialize */
1799         char dt, dtx;
1800         
1801         if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
1802         
1803         tbase.flag = OB_FROMDUPLI | base->flag;
1804         lb = object_duplilist(scene, base->object);
1805         // BLI_sortlist(lb, dupli_ob_sort); // might be nice to have if we have a dupli list with mixed objects.
1806
1807         dob = dupli_step(lb->first);
1808         if (dob) dob_next = dupli_step(dob->next);
1809
1810         for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
1811                 tbase.object = dob->ob;
1812
1813                 /* extra service: draw the duplicator in drawtype of parent */
1814                 /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
1815                 dt = tbase.object->dt;   tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
1816                 dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
1817
1818                 /* negative scale flag has to propagate */
1819                 transflag = tbase.object->transflag;
1820                 if (base->object->transflag & OB_NEG_SCALE)
1821                         tbase.object->transflag ^= OB_NEG_SCALE;
1822
1823                 UI_ThemeColorBlend(color, TH_BACK, 0.5);
1824
1825                 /* generate displist, test for new object */
1826                 if (dob_prev && dob_prev->ob != dob->ob) {
1827                         if (use_displist == 1)
1828                                 glDeleteLists(displist, 1);
1829
1830                         use_displist = -1;
1831                 }
1832
1833                 /* generate displist */
1834                 if (use_displist == -1) {
1835
1836                         /* note, since this was added, its checked dob->type==OB_DUPLIGROUP
1837                          * however this is very slow, it was probably needed for the NLA
1838                          * offset feature (used in group-duplicate.blend but no longer works in 2.5)
1839                          * so for now it should be ok to - campbell */
1840
1841                         if (/* if this is the last no need  to make a displist */
1842                             (dob_next == NULL || dob_next->ob != dob->ob) ||
1843                             /* lamp drawing messes with matrices, could be handled smarter... but this works */
1844                             (dob->ob->type == OB_LAMP) ||
1845                             (dob->type == OB_DUPLIGROUP && dob->animated) ||
1846                             !(bb_tmp = object_get_boundbox(dob->ob)))
1847                         {
1848                                 // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2);
1849                                 use_displist = 0;
1850                         }
1851                         else {
1852                                 // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2);
1853                                 bb = *bb_tmp; /* must make a copy  */
1854
1855                                 /* disable boundbox check for list creation */
1856                                 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
1857                                 /* need this for next part of code */
1858                                 unit_m4(dob->ob->obmat);    /* obmat gets restored */
1859
1860                                 displist = glGenLists(1);
1861                                 glNewList(displist, GL_COMPILE);
1862                                 draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1863                                 glEndList();
1864
1865                                 use_displist = 1;
1866                                 object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
1867                         }
1868                 }
1869                 if (use_displist) {
1870                         glMultMatrixf(dob->mat);
1871                         if (ED_view3d_boundbox_clip(rv3d, dob->mat, &bb))
1872                                 glCallList(displist);
1873                         glLoadMatrixf(rv3d->viewmat);
1874                 }
1875                 else {
1876                         copy_m4_m4(dob->ob->obmat, dob->mat);
1877                         draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1878                 }
1879
1880                 tbase.object->dt = dt;
1881                 tbase.object->dtx = dtx;
1882                 tbase.object->transflag = transflag;
1883         }
1884         
1885         /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
1886         
1887         free_object_duplilist(lb);  /* does restore */
1888         
1889         if (use_displist)
1890                 glDeleteLists(displist, 1);
1891 }
1892
1893 static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
1894 {
1895         /* define the color here so draw_dupli_objects_color can be called
1896          * from the set loop */
1897         
1898         int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE;
1899         /* debug */
1900         if (base->object->dup_group && base->object->dup_group->id.us < 1)
1901                 color = TH_REDALERT;
1902         
1903         draw_dupli_objects_color(scene, ar, v3d, base, color);
1904 }
1905
1906 void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
1907 {
1908         int x, y, w, h; 
1909         rcti r;
1910         /* clamp rect by area */
1911
1912         r.xmin = 0;
1913         r.xmax = ar->winx - 1;
1914         r.ymin = 0;
1915         r.ymax = ar->winy - 1;
1916
1917         /* Constrain rect to depth bounds */
1918         BLI_isect_rcti(&r, rect, rect);
1919
1920         /* assign values to compare with the ViewDepths */
1921         x = rect->xmin;
1922         y = rect->ymin;
1923
1924         w = rect->xmax - rect->xmin;
1925         h = rect->ymax - rect->ymin;
1926
1927         if (w <= 0 || h <= 0) {
1928                 if (d->depths)
1929                         MEM_freeN(d->depths);
1930                 d->depths = NULL;
1931
1932                 d->damaged = FALSE;
1933         }
1934         else if (d->w != w ||
1935                  d->h != h ||
1936                  d->x != x ||
1937                  d->y != y ||
1938                  d->depths == NULL
1939                  )
1940         {
1941                 d->x = x;
1942                 d->y = y;
1943                 d->w = w;
1944                 d->h = h;
1945
1946                 if (d->depths)
1947                         MEM_freeN(d->depths);
1948
1949                 d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
1950                 
1951                 d->damaged = TRUE;
1952         }
1953
1954         if (d->damaged) {
1955                 glReadPixels(ar->winrct.xmin + d->x, ar->winrct.ymin + d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
1956                 glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
1957                 d->damaged = FALSE;
1958         }
1959 }
1960
1961 /* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
1962 void ED_view3d_depth_update(ARegion *ar)
1963 {
1964         RegionView3D *rv3d = ar->regiondata;
1965         
1966         /* Create storage for, and, if necessary, copy depth buffer */
1967         if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
1968         if (rv3d->depths) {
1969                 ViewDepths *d = rv3d->depths;
1970                 if (d->w != ar->winx ||
1971                     d->h != ar->winy ||
1972                     !d->depths)
1973                 {
1974                         d->w = ar->winx;
1975                         d->h = ar->winy;
1976                         if (d->depths)
1977                                 MEM_freeN(d->depths);
1978                         d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
1979                         d->damaged = 1;
1980                 }
1981                 
1982                 if (d->damaged) {
1983                         glReadPixels(ar->winrct.xmin, ar->winrct.ymin, d->w, d->h,
1984                                      GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
1985                         
1986                         glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
1987                         
1988                         d->damaged = 0;
1989                 }
1990         }
1991 }
1992
1993 /* utility function to find the closest Z value, use for autodepth */
1994 float view3d_depth_near(ViewDepths *d)
1995 {
1996         /* convert to float for comparisons */
1997         const float near = (float)d->depth_range[0];
1998         const float far_real = (float)d->depth_range[1];
1999         float far = far_real;
2000
2001         const float *depths = d->depths;
2002         float depth = FLT_MAX;
2003         int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
2004
2005         /* far is both the starting 'far' value
2006          * and the closest value found. */      
2007         while (i--) {
2008                 depth = *depths++;
2009                 if ((depth < far) && (depth > near)) {
2010                         far = depth;
2011                 }
2012         }
2013
2014         return far == far_real ? FLT_MAX : far;
2015 }
2016
2017 void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
2018 {
2019         short zbuf = v3d->zbuf;
2020         RegionView3D *rv3d = ar->regiondata;
2021
2022         setwinmatrixview3d(ar, v3d, NULL);  /* 0= no pick rect */
2023         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
2024
2025         mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
2026         invert_m4_m4(rv3d->persinv, rv3d->persmat);
2027         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
2028
2029         glClear(GL_DEPTH_BUFFER_BIT);
2030
2031         glLoadMatrixf(rv3d->viewmat);
2032
2033         v3d->zbuf = TRUE;
2034         glEnable(GL_DEPTH_TEST);
2035
2036         draw_gpencil_view3d(scene, v3d, ar, 1);
2037         
2038         v3d->zbuf = zbuf;
2039
2040 }
2041
2042 void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *))
2043 {
2044         RegionView3D *rv3d = ar->regiondata;
2045         Base *base;
2046         short zbuf = v3d->zbuf;
2047         short flag = v3d->flag;
2048         float glalphaclip = U.glalphaclip;
2049         int obcenter_dia = U.obcenter_dia;
2050         /* temp set drawtype to solid */
2051         
2052         /* Setting these temporarily is not nice */
2053         v3d->flag &= ~V3D_SELECT_OUTLINE;
2054         U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
2055         U.obcenter_dia = 0;
2056         
2057         setwinmatrixview3d(ar, v3d, NULL);  /* 0= no pick rect */
2058         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
2059         
2060         mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
2061         invert_m4_m4(rv3d->persinv, rv3d->persmat);
2062         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
2063         
2064         glClear(GL_DEPTH_BUFFER_BIT);
2065         
2066         glLoadMatrixf(rv3d->viewmat);
2067 //      persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
2068         
2069         if (rv3d->rflag & RV3D_CLIPPING) {
2070                 ED_view3d_clipping_set(rv3d);
2071         }
2072         
2073         v3d->zbuf = TRUE;
2074         glEnable(GL_DEPTH_TEST);
2075         
2076         /* draw set first */
2077         if (scene->set) {
2078                 Scene *sce_iter;
2079                 for (SETLOOPER(scene->set, sce_iter, base)) {
2080                         if (v3d->lay & base->lay) {
2081                                 if (func == NULL || func(base)) {
2082                                         draw_object(scene, ar, v3d, base, 0);
2083                                         if (base->object->transflag & OB_DUPLI) {
2084                                                 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2085                                         }
2086                                 }
2087                         }
2088                 }
2089         }
2090         
2091         for (base = scene->base.first; base; base = base->next) {
2092                 if (v3d->lay & base->lay) {
2093                         if (func == NULL || func(base)) {
2094                                 /* dupli drawing */
2095                                 if (base->object->transflag & OB_DUPLI) {
2096                                         draw_dupli_objects(scene, ar, v3d, base);
2097                                 }
2098                                 draw_object(scene, ar, v3d, base, 0);
2099                         }
2100                 }
2101         }
2102         
2103         /* this isn't that nice, draw xray objects as if they are normal */
2104         if (v3d->afterdraw_transp.first ||
2105             v3d->afterdraw_xray.first ||
2106             v3d->afterdraw_xraytransp.first)
2107         {
2108                 View3DAfter *v3da, *next;
2109                 int mask_orig;
2110
2111                 v3d->xray = TRUE;
2112                 
2113                 /* transp materials can change the depth mask, see #21388 */
2114                 glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
2115
2116
2117                 if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
2118                         glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
2119                         for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
2120                                 next = v3da->next;
2121                                 draw_object(scene, ar, v3d, v3da->base, 0);
2122                         }
2123                         glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
2124                 }
2125
2126                 /* draw 3 passes, transp/xray/xraytransp */
2127                 v3d->xray = FALSE;
2128                 v3d->transp = TRUE;
2129                 for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
2130                         next = v3da->next;
2131                         draw_object(scene, ar, v3d, v3da->base, 0);
2132                         BLI_remlink(&v3d->afterdraw_transp, v3da);
2133                         MEM_freeN(v3da);
2134                 }
2135
2136                 v3d->xray = TRUE;
2137                 v3d->transp = FALSE;
2138                 for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
2139                         next = v3da->next;
2140                         draw_object(scene, ar, v3d, v3da->base, 0);
2141                         BLI_remlink(&v3d->afterdraw_xray, v3da);
2142                         MEM_freeN(v3da);
2143                 }
2144
2145                 v3d->xray = TRUE;
2146                 v3d->transp = TRUE;
2147                 for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
2148                         next = v3da->next;
2149                         draw_object(scene, ar, v3d, v3da->base, 0);
2150                         BLI_remlink(&v3d->afterdraw_xraytransp, v3da);
2151                         MEM_freeN(v3da);
2152                 }
2153
2154                 
2155                 v3d->xray = FALSE;
2156                 v3d->transp = FALSE;
2157
2158                 glDepthMask(mask_orig);
2159         }
2160         
2161         if (rv3d->rflag & RV3D_CLIPPING)
2162                 ED_view3d_clipping_disable();
2163         
2164         v3d->zbuf = zbuf;
2165         if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
2166
2167         U.glalphaclip = glalphaclip;
2168         v3d->flag = flag;
2169         U.obcenter_dia = obcenter_dia;
2170 }
2171
2172 typedef struct View3DShadow {
2173         struct View3DShadow *next, *prev;
2174         GPULamp *lamp;
2175 } View3DShadow;
2176
2177 static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par,
2178                                    float obmat[][4], ListBase *shadows)
2179 {
2180         GPULamp *lamp;
2181         Lamp *la = (Lamp *)ob->data;
2182         View3DShadow *shadow;
2183         
2184         lamp = GPU_lamp_from_blender(scene, ob, par);
2185         
2186         if (lamp) {
2187                 GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
2188                 GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
2189                 
2190                 if ((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
2191                         shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
2192                         shadow->lamp = lamp;
2193                         BLI_addtail(shadows, shadow);
2194                 }
2195         }
2196 }
2197
2198 static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
2199 {
2200         ListBase shadows;
2201         View3DShadow *shadow;
2202         Scene *sce_iter;
2203         Base *base;
2204         Object *ob;
2205         
2206         shadows.first = shadows.last = NULL;
2207         
2208         /* update lamp transform and gather shadow lamps */
2209         for (SETLOOPER(scene, sce_iter, base)) {
2210                 ob = base->object;
2211                 
2212                 if (ob->type == OB_LAMP)
2213                         gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
2214                 
2215                 if (ob->transflag & OB_DUPLI) {
2216                         DupliObject *dob;
2217                         ListBase *lb = object_duplilist(scene, ob);
2218                         
2219                         for (dob = lb->first; dob; dob = dob->next)
2220                                 if (dob->ob->type == OB_LAMP)
2221                                         gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
2222                         
2223                         free_object_duplilist(lb);
2224                 }
2225         }
2226         
2227         /* render shadows after updating all lamps, nested object_duplilist
2228          * don't work correct since it's replacing object matrices */
2229         for (shadow = shadows.first; shadow; shadow = shadow->next) {
2230                 /* this needs to be done better .. */
2231                 float viewmat[4][4], winmat[4][4];
2232                 int drawtype, lay, winsize, flag2 = v3d->flag2;
2233                 ARegion ar = {NULL};
2234                 RegionView3D rv3d = {{{0}}};
2235                 
2236                 drawtype = v3d->drawtype;
2237                 lay = v3d->lay;
2238                 
2239                 v3d->drawtype = OB_SOLID;
2240                 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
2241                 v3d->flag2 &= ~V3D_SOLID_TEX;
2242                 v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
2243                 
2244                 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
2245
2246                 ar.regiondata = &rv3d;
2247                 ar.regiontype = RGN_TYPE_WINDOW;
2248                 rv3d.persp = RV3D_CAMOB;
2249                 copy_m4_m4(rv3d.winmat, winmat);
2250                 copy_m4_m4(rv3d.viewmat, viewmat);
2251                 invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
2252                 mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
2253                 invert_m4_m4(rv3d.persinv, rv3d.viewinv);
2254
2255                 ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE);
2256                 GPU_lamp_shadow_buffer_unbind(shadow->lamp);
2257                 
2258                 v3d->drawtype = drawtype;
2259                 v3d->lay = lay;
2260                 v3d->flag2 = flag2;
2261         }
2262         
2263         BLI_freelistN(&shadows);
2264 }
2265
2266 /* *********************** customdata **************** */
2267
2268 CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
2269 {
2270         CustomDataMask mask = 0;
2271
2272         if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) ||
2273             ((v3d->drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
2274         {
2275                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
2276
2277                 if (scene_use_new_shading_nodes(scene)) {
2278                         if (v3d->drawtype == OB_MATERIAL)
2279                                 mask |= CD_MASK_ORCO;
2280                 }
2281                 else {
2282                         if (scene->gm.matmode == GAME_MAT_GLSL)
2283                                 mask |= CD_MASK_ORCO;
2284                 }
2285         }
2286
2287         return mask;
2288 }
2289
2290 CustomDataMask ED_view3d_object_datamask(Scene *scene)
2291 {
2292         Object *ob = scene->basact ? scene->basact->object : NULL;
2293         CustomDataMask mask = 0;
2294
2295         if (ob) {
2296                 /* check if we need tfaces & mcols due to face select or texture paint */
2297                 if (paint_facesel_test(ob) || (ob->mode & OB_MODE_TEXTURE_PAINT)) {
2298                         mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
2299                 }
2300
2301                 /* check if we need mcols due to vertex paint or weightpaint */
2302                 if (ob->mode & OB_MODE_VERTEX_PAINT) {
2303                         mask |= CD_MASK_MCOL;
2304                 }
2305
2306                 if (ob->mode & OB_MODE_WEIGHT_PAINT) {
2307                         mask |= CD_MASK_PREVIEW_MCOL;
2308                 }
2309         }
2310
2311         return mask;
2312 }
2313
2314 /* goes over all modes and view3d settings */
2315 CustomDataMask ED_view3d_screen_datamask(bScreen *screen)
2316 {
2317         Scene *scene = screen->scene;
2318         CustomDataMask mask = CD_MASK_BAREMESH;
2319         ScrArea *sa;
2320         
2321         /* check if we need tfaces & mcols due to view mode */
2322         for (sa = screen->areabase.first; sa; sa = sa->next) {
2323                 if (sa->spacetype == SPACE_VIEW3D) {
2324                         mask |= ED_view3d_datamask(scene, (View3D *)sa->spacedata.first);
2325                 }
2326         }
2327
2328         mask |= ED_view3d_object_datamask(scene);
2329
2330         return mask;
2331 }
2332
2333 void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4])
2334 {
2335         RegionView3D *rv3d = ar->regiondata;
2336
2337         /* setup window matrices */
2338         if (winmat)
2339                 copy_m4_m4(rv3d->winmat, winmat);
2340         else
2341                 setwinmatrixview3d(ar, v3d, NULL);  /* NULL= no pickrect */
2342
2343         /* setup view matrix */
2344         if (viewmat)
2345                 copy_m4_m4(rv3d->viewmat, viewmat);
2346         else
2347                 setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
2348
2349         /* update utilitity matrices */
2350         mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
2351         invert_m4_m4(rv3d->persinv, rv3d->persmat);
2352         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
2353
2354         /* calculate pixelsize factor once, is used for lamps and obcenters */
2355         {
2356                 /* note:  '1.0f / len_v3(v1)'  replaced  'len_v3(rv3d->viewmat[0])'
2357                  * because of float point precision problems at large values [#23908] */
2358                 float v1[3], v2[3];
2359                 float len1, len2;
2360
2361                 v1[0] = rv3d->persmat[0][0];
2362                 v1[1] = rv3d->persmat[1][0];
2363                 v1[2] = rv3d->persmat[2][0];
2364
2365                 v2[0] = rv3d->persmat[0][1];
2366                 v2[1] = rv3d->persmat[1][1];
2367                 v2[2] = rv3d->persmat[2][1];
2368
2369                 len1 = 1.0f / len_v3(v1);
2370                 len2 = 1.0f / len_v3(v2);
2371
2372                 rv3d->pixsize = (2.0f * MAX2(len1, len2)) / (float)MAX2(ar->winx, ar->winy);
2373         }
2374 }
2375
2376 static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[][4], float winmat[][4])
2377 {
2378         RegionView3D *rv3d = ar->regiondata;
2379
2380         ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
2381
2382         /* set for opengl */
2383         glMatrixMode(GL_PROJECTION);
2384         glLoadMatrixf(rv3d->winmat);
2385         glMatrixMode(GL_MODELVIEW);
2386         glLoadMatrixf(rv3d->viewmat);
2387 }
2388
2389 void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
2390                               int winx, int winy, float viewmat[][4], float winmat[][4],
2391                               int draw_background)
2392 {
2393         RegionView3D *rv3d = ar->regiondata;
2394         Base *base;
2395         float backcol[3];
2396         int bwinx, bwiny;
2397         rcti brect;
2398         ImBuf *bg_ibuf = NULL;
2399
2400         glPushMatrix();
2401
2402         /* set temporary new size */
2403         bwinx = ar->winx;
2404         bwiny = ar->winy;
2405         brect = ar->winrct;
2406         
2407         ar->winx = winx;
2408         ar->winy = winy;
2409         ar->winrct.xmin = 0;
2410         ar->winrct.ymin = 0;
2411         ar->winrct.xmax = winx;
2412         ar->winrct.ymax = winy;
2413         
2414         
2415         /* set flags */
2416         G.f |= G_RENDER_OGL;
2417
2418         /* free images which can have changed on frame-change
2419          * warning! can be slow so only free animated images - campbell */
2420         GPU_free_images_anim();
2421         
2422         /* shadow buffers, before we setup matrices */
2423         if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
2424                 gpu_update_lamps_shadows(scene, v3d);
2425
2426         /* if scene has got active clip, use it for render backdrop */
2427         if (draw_background && scene->clip && rv3d->persp == RV3D_CAMOB && v3d->camera) {
2428                 MovieClipUser user = {0};
2429
2430                 BKE_movieclip_user_set_frame(&user, CFRA);
2431                 bg_ibuf = BKE_movieclip_get_ibuf(scene->clip, &user);
2432         }
2433
2434         if (!bg_ibuf) {
2435                 /* set background color, fallback on the view background color
2436                  * (if active clip is set but frame is failed to load fallback to horizon color as background) */
2437                 if (scene->world) {
2438                         if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
2439                                 linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
2440                         else
2441                                 copy_v3_v3(backcol, &scene->world->horr);
2442                         glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
2443                 }
2444                 else {
2445                         UI_ThemeClearColor(TH_BACK);
2446                 }
2447         }
2448
2449         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2450
2451         if (bg_ibuf) {
2452                 unsigned char *pixels, *cp, *dst_cp;
2453                 int i;
2454
2455                 if (bg_ibuf->rect_float && !bg_ibuf->rect)
2456                         IMB_rect_from_float(bg_ibuf);
2457
2458                 dst_cp = pixels = MEM_callocN(4 * sizeof(unsigned char) * bg_ibuf->x * bg_ibuf->y, "draw offscreen clip pixels");
2459                 cp = (unsigned char *)bg_ibuf->rect;
2460                 for (i = 0; i < bg_ibuf->x * bg_ibuf->y; i++, cp += 4, dst_cp += 4) {
2461                         dst_cp[0] = cp[0];
2462                         dst_cp[1] = cp[1];
2463                         dst_cp[2] = cp[2];
2464                         dst_cp[3] = 255;
2465                 }
2466
2467                 glMatrixMode(GL_PROJECTION);
2468                 glPushMatrix();
2469                 glMatrixMode(GL_MODELVIEW);
2470                 glPushMatrix();
2471                 ED_region_pixelspace(ar);
2472
2473                 glPixelZoom((float)winx / bg_ibuf->x, (float)winy / bg_ibuf->y);
2474                 glaDrawPixelsTex(0, 0, bg_ibuf->x, bg_ibuf->y, GL_UNSIGNED_BYTE, pixels);
2475
2476                 glPixelZoom(1.0, 1.0);
2477
2478                 glMatrixMode(GL_PROJECTION);
2479                 glPopMatrix();
2480                 glMatrixMode(GL_MODELVIEW);
2481                 glPopMatrix();
2482
2483                 IMB_freeImBuf(bg_ibuf);
2484                 MEM_freeN(pixels);
2485         }
2486
2487         /* setup view matrices */
2488         view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
2489
2490         if (rv3d->rflag & RV3D_CLIPPING)
2491                 view3d_draw_clipping(rv3d);
2492
2493         /* set zbuffer */
2494         if (v3d->drawtype > OB_WIRE) {
2495                 v3d->zbuf = TRUE;
2496                 glEnable(GL_DEPTH_TEST);
2497         }
2498         else
2499                 v3d->zbuf = FALSE;
2500
2501         if (rv3d->rflag & RV3D_CLIPPING)
2502                 ED_view3d_clipping_set(rv3d);
2503
2504         /* draw set first */
2505         if (scene->set) {
2506                 Scene *sce_iter;
2507                 for (SETLOOPER(scene->set, sce_iter, base)) {
2508                         if (v3d->lay & base->lay) {
2509                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2510                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR | DRAW_SCENESET);
2511                                 
2512                                 if (base->object->transflag & OB_DUPLI)
2513                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2514                         }
2515                 }
2516         }
2517         
2518         /* then draw not selected and the duplis, but skip editmode object */
2519         for (base = scene->base.first; base; base = base->next) {
2520                 if (v3d->lay & base->lay) {
2521                         /* dupli drawing */
2522                         if (base->object->transflag & OB_DUPLI)
2523                                 draw_dupli_objects(scene, ar, v3d, base);
2524
2525                         draw_object(scene, ar, v3d, base, 0);
2526                 }
2527         }
2528
2529         /* must be before xray draw which clears the depth buffer */
2530         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2531         draw_gpencil_view3d(scene, v3d, ar, 1);
2532         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2533
2534         /* transp and X-ray afterdraw stuff */
2535         if (v3d->afterdraw_transp.first)     view3d_draw_transp(scene, ar, v3d);
2536         if (v3d->afterdraw_xray.first)       view3d_draw_xray(scene, ar, v3d, 1);         // clears zbuffer if it is used!
2537         if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, 1);
2538
2539         if (rv3d->rflag & RV3D_CLIPPING)
2540                 ED_view3d_clipping_disable();
2541
2542         /* cleanup */
2543         if (v3d->zbuf) {
2544                 v3d->zbuf = FALSE;
2545                 glDisable(GL_DEPTH_TEST);
2546         }
2547
2548         /* draw grease-pencil stuff */
2549         ED_region_pixelspace(ar);
2550
2551         /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2552         draw_gpencil_view3d(scene, v3d, ar, 0);
2553
2554         /* freeing the images again here could be done after the operator runs, leaving for now */
2555         GPU_free_images_anim();
2556
2557         /* restore size */
2558         ar->winx = bwinx;
2559         ar->winy = bwiny;
2560         ar->winrct = brect;
2561
2562         glPopMatrix();
2563
2564         // XXX, without this the sequencer flickers with opengl draw enabled, need to find out why - campbell
2565         glColor4ub(255, 255, 255, 255);
2566
2567         G.f &= ~G_RENDER_OGL;
2568 }
2569
2570 /* utility func for ED_view3d_draw_offscreen */
2571 ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
2572                                       int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256])
2573 {
2574         RegionView3D *rv3d = ar->regiondata;
2575         ImBuf *ibuf;
2576         GPUOffScreen *ofs;
2577         
2578         /* state changes make normal drawing go weird otherwise */
2579         glPushAttrib(GL_LIGHTING_BIT);
2580
2581         /* bind */
2582         ofs = GPU_offscreen_create(sizex, sizey, err_out);
2583         if (ofs == NULL)
2584                 return NULL;
2585
2586         GPU_offscreen_bind(ofs);
2587
2588         /* render 3d view */
2589         if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
2590                 CameraParams params;
2591
2592                 camera_params_init(&params);
2593                 camera_params_from_object(&params, v3d->camera);
2594                 camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
2595                 camera_params_compute_matrix(&params);
2596
2597                 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background);
2598         }
2599         else {
2600                 ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background);
2601         }
2602
2603         /* read in pixels & stamp */
2604         ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
2605
2606         if (ibuf->rect_float)
2607                 GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
2608         else if (ibuf->rect)
2609                 GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
2610         
2611         //if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
2612         //      BKE_stamp_buf(scene, NULL, rr->rectf, rr->rectx, rr->recty, 4);
2613
2614         /* unbind */
2615         GPU_offscreen_unbind(ofs);
2616         GPU_offscreen_free(ofs);
2617
2618         glPopAttrib();
2619         
2620         if (ibuf->rect_float && ibuf->rect)
2621                 IMB_rect_from_float(ibuf);
2622         
2623         return ibuf;
2624 }
2625
2626 /* creates own 3d views, used by the sequencer */
2627 ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height,
2628                                              unsigned int flag, int drawtype, int draw_background, char err_out[256])
2629 {
2630         View3D v3d = {NULL};
2631         ARegion ar = {NULL};
2632         RegionView3D rv3d = {{{0}}};
2633
2634         /* connect data */
2635         v3d.regionbase.first = v3d.regionbase.last = &ar;
2636         ar.regiondata = &rv3d;
2637         ar.regiontype = RGN_TYPE_WINDOW;
2638
2639         v3d.camera = camera;
2640         v3d.lay = scene->lay;
2641         v3d.drawtype = drawtype;
2642         v3d.flag2 = V3D_RENDER_OVERRIDE;
2643
2644         rv3d.persp = RV3D_CAMOB;
2645
2646         copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
2647         normalize_m4(rv3d.viewinv);
2648         invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
2649
2650         {
2651                 CameraParams params;
2652
2653                 camera_params_init(&params);
2654                 camera_params_from_object(&params, v3d.camera);
2655                 camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
2656                 camera_params_compute_matrix(&params);
2657
2658                 copy_m4_m4(rv3d.winmat, params.winmat);
2659                 v3d.near = params.clipsta;
2660                 v3d.far = params.clipend;
2661                 v3d.lens = params.lens;
2662         }
2663
2664         mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
2665         invert_m4_m4(rv3d.persinv, rv3d.viewinv);
2666
2667         return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, draw_background, err_out);
2668
2669         // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty);
2670 }
2671
2672
2673 /* NOTE: the info that this uses is updated in ED_refresh_viewport_fps(), 
2674  * which currently gets called during SCREEN_OT_animation_step.
2675  */
2676 static void draw_viewport_fps(Scene *scene, ARegion *ar)
2677 {
2678         ScreenFrameRateInfo *fpsi = scene->fps_info;
2679         float fps;
2680         char printable[16];
2681         int i, tot;
2682         
2683         if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
2684                 return;
2685         
2686         printable[0] = '\0';
2687         
2688 #if 0
2689         /* this is too simple, better do an average */
2690         fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
2691 #else
2692         fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
2693         
2694         for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) {
2695                 if (fpsi->redrawtimes_fps[i]) {
2696                         fps += fpsi->redrawtimes_fps[i];
2697                         tot++;
2698                 }
2699         }
2700         if (tot) {
2701                 fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
2702                 
2703                 //fpsi->redrawtime_index++;
2704                 //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
2705                 //      fpsi->redrawtime = 0;
2706                 
2707                 fps = fps / tot;
2708         }
2709 #endif
2710
2711               /* is this more then half a frame behind? */
2712               if (fps + 0.5f < (float)(FPS)) {
2713                 UI_ThemeColor(TH_REDALERT);
2714                 BLI_snprintf(printable, sizeof(printable), "fps: %.2f", fps);
2715         } 
2716         else {
2717                 UI_ThemeColor(TH_TEXT_HI);
2718                 BLI_snprintf(printable, sizeof(printable), "fps: %i", (int)(fps + 0.5f));
2719         }
2720         
2721         BLF_draw_default_ascii(22,  ar->winy - 17, 0.0f, printable, sizeof(printable));
2722 }
2723
2724 static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar)
2725 {
2726         Scene *scene = CTX_data_scene(C);
2727         View3D *v3d = CTX_wm_view3d(C);
2728         RegionView3D *rv3d = CTX_wm_region_view3d(C);
2729         RenderEngineType *type;
2730
2731         if (!rv3d->render_engine) {
2732                 type = RE_engines_find(scene->r.engine);
2733
2734                 if (!(type->view_update && type->view_draw))
2735                         return 0;
2736
2737                 rv3d->render_engine = RE_engine_create(type);
2738                 type->view_update(rv3d->render_engine, C);
2739         }
2740
2741         view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
2742
2743         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2744         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2745
2746         ED_region_pixelspace(ar);
2747
2748         type = rv3d->render_engine->type;
2749         type->view_draw(rv3d->render_engine, C);
2750
2751         return 1;
2752 }
2753
2754 static void view3d_main_area_draw_engine_info(RegionView3D *rv3d, ARegion *ar)
2755 {
2756         if (!rv3d->render_engine || !rv3d->render_engine->text)
2757                 return;
2758
2759         ED_region_info_draw(ar, rv3d->render_engine->text, 1, 0.25);
2760 }
2761
2762 /* warning: this function has duplicate drawing in ED_view3d_draw_offscreen() */
2763 static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit)
2764 {
2765         Scene *scene = CTX_data_scene(C);
2766         View3D *v3d = CTX_wm_view3d(C);
2767         RegionView3D *rv3d = CTX_wm_region_view3d(C);
2768         Base *base;
2769         float backcol[3];
2770         unsigned int lay_used;
2771
2772         /* shadow buffers, before we setup matrices */
2773         if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
2774                 gpu_update_lamps_shadows(scene, v3d);
2775         
2776         /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
2777         if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
2778                 rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
2779                 GPU_default_lights();
2780         }
2781
2782         /* clear background */
2783         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) {
2784                 if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
2785                         linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
2786                 else
2787                         copy_v3_v3(backcol, &scene->world->horr);
2788                 glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
2789         }
2790         else
2791                 UI_ThemeClearColor(TH_BACK);
2792
2793         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2794         
2795         /* setup view matrices */
2796         view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
2797
2798         ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
2799
2800         if (rv3d->rflag & RV3D_CLIPPING)
2801                 view3d_draw_clipping(rv3d);
2802         
2803         /* set zbuffer after we draw clipping region */
2804         if (v3d->drawtype > OB_WIRE) {
2805                 v3d->zbuf = TRUE;
2806                 glEnable(GL_DEPTH_TEST);
2807         }
2808         else
2809                 v3d->zbuf = FALSE;
2810
2811         /* enables anti-aliasing for 3D view drawing */
2812 #if 0
2813         if (!(U.gameflags & USER_DISABLE_AA))
2814                 glEnable(GL_MULTISAMPLE_ARB);
2815 #endif
2816
2817         // needs to be done always, gridview is adjusted in drawgrid() now
2818         rv3d->gridview = v3d->grid;
2819
2820         if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
2821                 if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2822                         drawfloor(scene, v3d, grid_unit);
2823                 }
2824                 if (rv3d->persp == RV3D_CAMOB) {
2825                         if (scene->world) {
2826                                 if (scene->world->mode & WO_STARS) {
2827                                         RE_make_stars(NULL, scene, star_stuff_init_func, star_stuff_vertex_func,
2828                                                       star_stuff_term_func);
2829                                 }
2830                         }
2831                         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2832                                 if (v3d->flag & V3D_DISPBGPICS) draw_bgpic(scene, ar, v3d);
2833                         }
2834                 }
2835         }
2836         else {
2837                 if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2838                         ED_region_pixelspace(ar);
2839                         drawgrid(&scene->unit, ar, v3d, grid_unit);
2840                         /* XXX make function? replaces persp(1) */
2841                         glMatrixMode(GL_PROJECTION);
2842                         glLoadMatrixf(rv3d->winmat);
2843                         glMatrixMode(GL_MODELVIEW);
2844                         glLoadMatrixf(rv3d->viewmat);
2845
2846                         if (v3d->flag & V3D_DISPBGPICS) {
2847                                 draw_bgpic(scene, ar, v3d);
2848                         }
2849                 }
2850         }
2851         
2852         if (rv3d->rflag & RV3D_CLIPPING)
2853                 ED_view3d_clipping_set(rv3d);
2854
2855         /* draw set first */
2856         if (scene->set) {
2857                 Scene *sce_iter;
2858                 for (SETLOOPER(scene->set, sce_iter, base)) {
2859                         
2860                         if (v3d->lay & base->lay) {
2861                                 
2862                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2863                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR | DRAW_SCENESET);
2864                                 
2865                                 if (base->object->transflag & OB_DUPLI) {
2866                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2867                                 }
2868                         }
2869                 }
2870                 
2871                 /* Transp and X-ray afterdraw stuff for sets is done later */
2872         }
2873
2874         lay_used = 0;
2875
2876         /* then draw not selected and the duplis, but skip editmode object */
2877         for (base = scene->base.first; base; base = base->next) {
2878                 lay_used |= base->lay & ((1 << 20) - 1);
2879
2880                 if (v3d->lay & base->lay) {
2881                         
2882                         /* dupli drawing */
2883                         if (base->object->transflag & OB_DUPLI) {
2884                                 draw_dupli_objects(scene, ar, v3d, base);
2885                         }
2886                         if ((base->flag & SELECT) == 0) {
2887                                 if (base->object != scene->obedit)
2888                                         draw_object(scene, ar, v3d, base, 0);
2889                         }
2890                 }
2891         }
2892
2893         if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
2894                 /* find header and force tag redraw */
2895                 ScrArea *sa = CTX_wm_area(C);
2896                 ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
2897                 ED_region_tag_redraw(ar_header); /* can be NULL */
2898                 v3d->lay_used = lay_used;
2899         }
2900
2901         /* draw selected and editmode */
2902         for (base = scene->base.first; base; base = base->next) {
2903                 if (v3d->lay & base->lay) {
2904                         if (base->object == scene->obedit || (base->flag & SELECT) )
2905                                 draw_object(scene, ar, v3d, base, 0);
2906                 }
2907         }
2908
2909 //      REEB_draw();
2910
2911         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2912                 /* must be before xray draw which clears the depth buffer */
2913                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2914                 draw_gpencil_view3d(scene, v3d, ar, 1);
2915                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2916         }
2917
2918         /* Transp and X-ray afterdraw stuff */
2919         if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
2920         if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, 1);         // clears zbuffer if it is used!
2921         if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, 1);
2922         
2923         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
2924
2925         if (rv3d->rflag & RV3D_CLIPPING)
2926                 ED_view3d_clipping_disable();
2927         
2928         BIF_draw_manipulator(C);
2929
2930 #if 0
2931         /* Disable back anti-aliasing */
2932         if (!(U.gameflags & USER_DISABLE_AA))
2933                 glDisable(GL_MULTISAMPLE_ARB);
2934 #endif
2935
2936         if (v3d->zbuf) {
2937                 v3d->zbuf = FALSE;
2938                 glDisable(GL_DEPTH_TEST);
2939         }
2940
2941         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2942                 BDR_drawSketch(C);
2943         }
2944
2945         if ((U.ndof_flag & NDOF_SHOW_GUIDE) && (rv3d->viewlock != RV3D_LOCKED) && (rv3d->persp != RV3D_CAMOB))
2946                 // TODO: draw something else (but not this) during fly mode
2947                 draw_rotation_guide(rv3d);
2948
2949 }
2950
2951 static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const char *grid_unit)
2952 {
2953         Scene *scene = CTX_data_scene(C);
2954         View3D *v3d = CTX_wm_view3d(C);
2955         RegionView3D *rv3d = CTX_wm_region_view3d(C);
2956         bScreen *screen = CTX_wm_screen(C);
2957
2958         Object *ob;
2959
2960         if (rv3d->persp == RV3D_CAMOB)
2961                 drawviewborder(scene, ar, v3d);
2962
2963         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2964                 /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2965                 //      if (v3d->flag2 & V3D_DISPGP)
2966                 draw_gpencil_view3d(scene, v3d, ar, 0);
2967
2968                 drawcursor(scene, ar, v3d);
2969         }
2970         
2971         if (U.uiflag & USER_SHOW_ROTVIEWICON)
2972                 draw_view_axis(rv3d);
2973         else    
2974                 draw_view_icon(rv3d);
2975         
2976         ob = OBACT;
2977         if (U.uiflag & USER_DRAWVIEWINFO)
2978                 draw_selected_name(scene, ob);
2979
2980         if (rv3d->render_engine) {
2981                 view3d_main_area_draw_engine_info(rv3d, ar);
2982                 return;
2983         }
2984
2985         if ((U.uiflag & USER_SHOW_FPS) && screen->animtimer) {
2986                 draw_viewport_fps(scene, ar);
2987         }
2988         else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
2989                 draw_viewport_name(ar, v3d);
2990         }
2991
2992         if (grid_unit) { /* draw below the viewport name */
2993                 char numstr[32] = "";
2994
2995                 UI_ThemeColor(TH_TEXT_HI);
2996                 if (v3d->grid != 1.0f) {
2997                         BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
2998                 }
2999
3000                 BLF_draw_default_ascii(22,  ar->winy - (USER_SHOW_VIEWPORTNAME ? 40 : 20), 0.0f,
3001                                        numstr[0] ? numstr : grid_unit, sizeof(numstr));
3002         }
3003 }
3004
3005 void view3d_main_area_draw(const bContext *C, ARegion *ar)
3006 {
3007         View3D *v3d = CTX_wm_view3d(C);
3008         const char *grid_unit = NULL;
3009
3010         /* draw viewport using external renderer? */
3011         if (!(v3d->drawtype == OB_RENDER && view3d_main_area_draw_engine(C, ar))) {
3012                 /* draw viewport using opengl */
3013                 view3d_main_area_draw_objects(C, ar, &grid_unit);
3014                 ED_region_pixelspace(ar);
3015         }
3016         
3017         view3d_main_area_draw_info(C, ar, grid_unit);
3018
3019         v3d->flag |= V3D_INVALID_BACKBUF;
3020 }
3021