1 #ifndef vgui_utils_h_
2 #define vgui_utils_h_
3 //:
4 // \file
5 // \author fsm
6 // \brief  Useful static functions for vgui.
7 //
8 // \verbatim
9 //  Modifications
10 //   991020 AWF Added inversion of translation+scale.
11 //              This is necessary because zoomers demand exact equality
12 //              when checking if they are 2D transformations.
13 // \endverbatim
14 
15 #include <vector>
16 #include "vgui_gl.h"
17 #include "vgui/vgui_adaptor.h"
18 #ifdef _MSC_VER
19 #  include <vcl_msvc_warnings.h>
20 #endif
21 #include <vil1/vil1_rgb.h>
22 #include <vil1/vil1_memory_image_of.h>
23 #include <vil/vil_image_view.h>
24 
25 //: Useful static functions for vgui.
26 class vgui_utils
27 {
28  public:
29   //: Get a memory image (vil1) corresponding to the OpenGL area
30   static vil1_memory_image_of<vil1_rgb<unsigned char> > colour_buffer_to_image();
31 
32   //: Get an image view corresponding to the OpenGL area
33   static vil_image_view<vxl_byte> colour_buffer_to_view();
34 
35   //: Dump the OpenGL area to the given image filename.
36   static void dump_colour_buffer(char const *file);
37 
38   //: Copy front colour buffer to back colour buffer.
39   static void copy_front_to_back();
40 
41   //: Copy back colour buffer to front colour buffer.
42   static void copy_back_to_front();
43 
44   //: Begin software overlay.
45   static void begin_sw_overlay();
46 
47   //: End software overlay.
48   static void end_sw_overlay();
49 
50   // Selection utilities
51   static GLuint* enter_pick_mode(float x, float y, float w, float h=0);
52   static unsigned leave_pick_mode();
53   static void process_hits(int num_hits, GLuint* ptr, std::vector<std::vector<unsigned> >& hits);
54 
55   //: Returns the number of bits per pixel.
56   static int bits_per_pixel(GLenum format, GLenum type);
57 
58   /**
59    * Gets the viewport (GL_VIEWPORT), and corrects for physical to logical
60    * scaling, so that the values are always in units of logical pixels, cross
61    * platform.
62    *
63    * @param view_port A GLint/GLfloat/GLdouble[4] array where the viewport is
64    *                  stored, in logical pixels
65    * @param scale The scale factor used. Defaults to 0, meaning auto determine
66    *              using vgui_adaptor::current. If this is not correct, the
67    *              scale factor can manually be set
68    */
69   template <class T> static void get_glViewport(T *data, double scale=0){_glGet<T, 4>(GL_VIEWPORT, data, scale);};
70 
71   /**
72    * Gets the Scissor ROI (GL_SCISSOR_BOX), and corrects for physical to logical
73    * scaling, so that the values are always in units of logical pixels, cross
74    * platform.
75    *
76    * @param view_port A GLint/GLfloat/GLdouble[4] array where the viewport is
77    *                  stored, in logical pixels
78    * @param scale The scale factor used. Defaults to 0, meaning auto determine
79    *              using vgui_adaptor::current. If this is not correct, the
80    *              scale factor can manually be set
81    */
82   template <class T> static void get_glScissor(T *data, double scale=0){_glGet<T, 4>(GL_SCISSOR_BOX, data, scale);};
83 
84   //: Set the gl viewport in logical pixels
85   static void set_glViewport(GLint x, GLint y,
86                              GLsizei width, GLsizei height,
87                              double scale=0);
88   static void set_glScissor(GLint x, GLint y,
89                             GLsizei width, GLsizei height,
90                             double scale=0);
91 
92   static void set_glLineWidth(GLfloat width, double scale=0);
93   static void set_glPixelZoom(GLfloat xfactor, GLfloat yfactor, double scale=0);
94   static void set_glPointSize(GLfloat size, double scale=0);
95   static void draw_glBitmap(GLsizei width, GLsizei height,
96                             GLfloat xorig, GLfloat yorig,
97                             GLfloat xmove, GLfloat ymove,
98  	                          const GLubyte * bitmap,
99                             double scale=0);
100 
101  private:
102   static vil1_memory_image_of<vil1_rgb<GLubyte> > get_image(double scale=0);
103   static vil_image_view<GLubyte> get_view(double scale=0);
104   static void do_copy(double scale=0);
105 
106   /**
107    * Helper function that sets the DPI scale variable if it is unknown (0)
108    *
109    * @param s If s is non-zero, it is left alone, else it retrieves the scale
110    *          from the current vgui adaptor and sets s to it.
111    */
get_gl_scale_default(double & s)112   static inline void get_gl_scale_default(double &s){ if (s == 0) s = vgui_adaptor::current->get_scale_factor(); }
113 
114 
115   /* For GL_VIEWPORT and GL_SCISSOR_BOX, which are all in physical instead of
116      logical pixels. The only other target I see that might need to be added to
117      this in the future is GL_MAX_VIEWPORT_DIMS. number_scaled assumed only the
118      first n need to be scaled. If it gets to be more complicated, replace with
119      a bit mask or something, but I don't think there's a need for that */
120   template <class T, int number_scaled> static inline void _glGet(GLenum target, T *data, double scale=0)
121   {
122     get_gl_scale_default(scale);
123 
124     _glRawGet(target, data);
125 
126     for(ptrdiff_t x=0; x<number_scaled; x++)
127       data[x]/=scale;
128   }
129   // Clean up with constexpr in c++17
_glRawGet(GLenum target,GLint * data)130   static inline void _glRawGet(GLenum target, GLint* data){glGetIntegerv(target, data);};
_glRawGet(GLenum target,GLfloat * data)131   static inline void _glRawGet(GLenum target, GLfloat* data){glGetFloatv(target, data);};
_glRawGet(GLenum target,GLdouble * data)132   static inline void _glRawGet(GLenum target, GLdouble* data){glGetDoublev(target, data);};
133 
134 };
135 
136 #endif // vgui_utils_h_
137