00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #if !defined(INVT_HAVE_LIBGL) || !defined(INVT_HAVE_LIBGLU)
00047
00048 #include "Robots/LoBot/ui/LoGLCanvas.H"
00049 #include "Robots/LoBot/misc/LoExcept.H"
00050
00051 namespace lobot {
00052
00053 GLCanvas::GLCanvas()
00054 {
00055 throw missing_libs(MISSING_OPENGL) ;
00056 }
00057
00058
00059 void GLCanvas::set_window(float, float, float, float){}
00060 void GLCanvas::set_viewport(int, int, int, int){}
00061 void GLCanvas::screen_to_world(int, int, double*, double*){}
00062 void GLCanvas::zoom_to(float){}
00063 void GLCanvas::pan(float, float){}
00064 void GLCanvas::reset_zoom_pan(){}
00065
00066 GLCanvas::~GLCanvas(){}
00067
00068 #else // OpenGL available ==> the real McCoy
00069
00070
00071
00072
00073 #include "Robots/LoBot/ui/LoGLCanvas.H"
00074 #include "Robots/LoBot/config/LoConfigHelpers.H"
00075 #include "Robots/LoBot/util/LoMath.H"
00076
00077
00078 #include <GL/glu.h>
00079 #include <GL/gl.h>
00080
00081
00082 #include <algorithm>
00083
00084
00085
00086 namespace lobot {
00087
00088
00089
00090 GLCanvas::GLCanvas()
00091 : m_zoom_level(1)
00092 {
00093 m_window[LEFT] = 0 ;
00094 m_window[RIGHT] = 0 ;
00095 m_window[BOTTOM] = 0 ;
00096 m_window[TOP] = 0 ;
00097
00098 m_viewport[LEFT] = 0 ;
00099 m_viewport[RIGHT] = 0 ;
00100 m_viewport[BOTTOM] = 0 ;
00101 m_viewport[TOP] = 0 ;
00102 }
00103
00104
00105
00106
00107 void GLCanvas::set_window(float left, float right, float bottom, float top)
00108 {
00109 m_window[LEFT] = left ;
00110 m_window[RIGHT] = right ;
00111 m_window[BOTTOM] = bottom ;
00112 m_window[TOP] = top ;
00113
00114 glMatrixMode(GL_PROJECTION) ;
00115 glLoadIdentity() ;
00116 gluOrtho2D(left, right, bottom, top) ;
00117
00118 glMatrixMode(GL_MODELVIEW) ;
00119 glLoadIdentity() ;
00120 }
00121
00122
00123 void GLCanvas::set_viewport(int left, int right, int bottom, int top)
00124 {
00125 const int w = right - left ;
00126 const int h = top - bottom ;
00127 if (w <= 0 || h <= 0)
00128 return ;
00129
00130 const float R =
00131 (m_window[RIGHT] - m_window[LEFT])/(m_window[TOP] - m_window[BOTTOM]) ;
00132 const float r = static_cast<float>(w)/h ;
00133 if (R < r)
00134 {
00135 const int w_adjusted = static_cast<int>(R * h) ;
00136 left = (w - w_adjusted)/2 ;
00137 right = left + w_adjusted ;
00138 }
00139 else
00140 {
00141 const int h_adjusted = static_cast<int>(w/R) ;
00142 bottom = (h - h_adjusted)/2 ;
00143 top = bottom + h_adjusted ;
00144 }
00145
00146 m_viewport[LEFT] = left ;
00147 m_viewport[RIGHT] = right ;
00148 m_viewport[BOTTOM] = bottom ;
00149 m_viewport[TOP] = top ;
00150
00151 glViewport(left, bottom, right - left, top - bottom) ;
00152 }
00153
00154 void GLCanvas::get_viewport(int* x, int* y, int* width, int* height)
00155 {
00156 if (x)
00157 *x = m_viewport[LEFT] ;
00158 if (y)
00159 *y = m_viewport[BOTTOM] ;
00160 if (width)
00161 *width = m_viewport[RIGHT] - m_viewport[LEFT] ;
00162 if (height)
00163 *height = m_viewport[TOP] - m_viewport[BOTTOM] ;
00164 }
00165
00166 void GLCanvas::screen_to_world(int x, int y, double* wx, double* wy)
00167 {
00168 if (! wx || ! wy)
00169 return ;
00170
00171 GLint viewport[4] ;
00172 glGetIntegerv(GL_VIEWPORT, viewport) ;
00173
00174 GLdouble mvmatrix[16] ;
00175 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix) ;
00176
00177 GLdouble projmatrix[16] ;
00178 glGetDoublev (GL_PROJECTION_MATRIX, projmatrix) ;
00179
00180 GLdouble wz ;
00181 gluUnProject(x, viewport[3] - y - 1, 0, mvmatrix, projmatrix, viewport,
00182 wx, wy, & wz) ;
00183 }
00184
00185
00186
00187 void GLCanvas::zoom_to(float zoom_level)
00188 {
00189 zoom_level = clamp(zoom_level, Params::zoom_range()) ;
00190 float zoom_factor = zoom_level/m_zoom_level ;
00191 m_zoom_level = zoom_level ;
00192
00193 float current_width = m_window[RIGHT] - m_window[LEFT] ;
00194 float current_height = m_window[TOP] - m_window[BOTTOM] ;
00195
00196 float new_width = current_width /zoom_factor ;
00197 float new_height = current_height/zoom_factor ;
00198
00199 float width_incr = abs((new_width - current_width )/2) ;
00200 float height_incr = abs((new_height - current_height)/2) ;
00201
00202 if (new_width > current_width)
00203 {
00204 m_window[LEFT] -= width_incr ;
00205 m_window[RIGHT] += width_incr ;
00206 m_window[BOTTOM] -= height_incr ;
00207 m_window[TOP] += height_incr ;
00208 }
00209 else
00210 {
00211 m_window[LEFT] += width_incr ;
00212 m_window[RIGHT] -= width_incr ;
00213 m_window[BOTTOM] += height_incr ;
00214 m_window[TOP] -= height_incr ;
00215 }
00216 set_window(m_window) ;
00217 }
00218
00219 void GLCanvas::pan(float dx, float dy)
00220 {
00221 m_window[LEFT] += dx ;
00222 m_window[RIGHT] += dx ;
00223 m_window[BOTTOM] += dy ;
00224 m_window[TOP] += dy ;
00225
00226 set_window(m_window) ;
00227 }
00228
00229 void GLCanvas::reset_zoom_pan()
00230 {
00231 zoom_to(1) ;
00232 pan(-(m_window[LEFT] + m_window[RIGHT])/2,
00233 -(m_window[BOTTOM] + m_window[TOP])/2) ;
00234 }
00235
00236
00237
00238 GLCanvas::~GLCanvas()
00239 {}
00240
00241
00242
00243
00244 GLCanvas::Params::Params()
00245 : m_zoom_range(get_conf<float>("zoom_pan", "zoom_range",
00246 make_range(0.0001f, 1000.0f)))
00247 {}
00248
00249
00250 GLCanvas::Params::~Params(){}
00251
00252
00253 const range<float>& GLCanvas::Params::zoom_range()
00254 {
00255 return instance().m_zoom_range ;
00256 }
00257
00258
00259
00260 }
00261
00262 #endif // OpenGL availability check
00263
00264
00265
00266
00267