00001 /** 00002 \file Robots/LoBot/ui/LoMainWindow.H 00003 \brief The Lobot/Robolocust main window. 00004 00005 This file defines a class that encapsulates the lobot UI's main 00006 window. All of the different parts of lobot (such as input image 00007 streams, locust models, integration algorithms, etc.) are associated 00008 with corresponding drawables that are responsible for rendering their 00009 respective "source" objects on the main window. 00010 00011 Each drawable is assigned an area within the main window and is 00012 expected to render itself within that area. The geometry 00013 specifications in the lobot configuration file determine a drawable's 00014 rendering area. 00015 */ 00016 00017 // //////////////////////////////////////////////////////////////////// // 00018 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00019 // by the University of Southern California (USC) and the iLab at USC. // 00020 // See http://iLab.usc.edu for information about this project. // 00021 // //////////////////////////////////////////////////////////////////// // 00022 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00023 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00024 // in Visual Environments, and Applications'' by Christof Koch and // 00025 // Laurent Itti, California Institute of Technology, 2001 (patent // 00026 // pending; application number 09/912,225 filed July 23, 2001; see // 00027 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00028 // //////////////////////////////////////////////////////////////////// // 00029 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00030 // // 00031 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00032 // redistribute it and/or modify it under the terms of the GNU General // 00033 // Public License as published by the Free Software Foundation; either // 00034 // version 2 of the License, or (at your option) any later version. // 00035 // // 00036 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00037 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00038 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00039 // PURPOSE. See the GNU General Public License for more details. // 00040 // // 00041 // You should have received a copy of the GNU General Public License // 00042 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00043 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00044 // Boston, MA 02111-1307 USA. // 00045 // //////////////////////////////////////////////////////////////////// // 00046 // 00047 // Primary maintainer for this file: mviswana usc edu 00048 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/ui/LoMainWindow.H $ 00049 // $Id: LoMainWindow.H 13967 2010-09-18 08:00:07Z mviswana $ 00050 // 00051 00052 #ifndef LOBOT_MAIN_WINDOW_DOT_H 00053 #define LOBOT_MAIN_WINDOW_DOT_H 00054 00055 //------------------------------ HEADERS -------------------------------- 00056 00057 // lobot headers 00058 #include "Robots/LoBot/ui/LoDrawable.H" 00059 00060 #include "Robots/LoBot/thread/LoMutex.H" 00061 #include "Robots/LoBot/thread/LoThread.H" 00062 00063 #include "Robots/LoBot/misc/singleton.hh" 00064 00065 // Standard C++ headers 00066 #include <string> 00067 #include <queue> 00068 #include <list> 00069 #include <vector> 00070 00071 //----------------------------- NAMESPACE ------------------------------- 00072 00073 namespace lobot { 00074 00075 //------------------------- CLASS DEFINITION ---------------------------- 00076 00077 // Forward declarations 00078 class RenderBuffer ; 00079 00080 /** 00081 \class lobot::MainWindow 00082 \brief The Lobot/Robolocust main window. 00083 00084 This class implements the functionality of the Robolocust/lobot UI. It 00085 pops up a GLUT window on the screen and manages the rendering of all 00086 the drawables created by the main program and other parts of 00087 Robolocust. All Robolocust drawables are expected to render themselves 00088 using OpenGL. Rendering takes place in a separate thread. 00089 00090 The main window is responsible for managing the visualization of the 00091 laser range finder, the LGMD spike trains and each of the behaviours 00092 and DAMN arbiters. Each drawable element is be assigned an area within 00093 the main window based on the geometry specifications in the individual 00094 sections of the Robolocust config file. 00095 */ 00096 class MainWindow : public singleton<MainWindow>, private Thread { 00097 // Boilerplate code to make generic singleton pattern work 00098 friend class singleton<MainWindow> ; 00099 00100 /// This class uses GLUT to help visualize the different parts of the 00101 /// Robolocust program. This member variable holds the ID of the GLUT 00102 /// window. 00103 int m_window ; 00104 00105 /// Instead of rendering directly to the screen, the Robolocust UI 00106 /// first renders to an off-screen buffer and then copies that buffer 00107 /// to the screen. This indirect approach to rendering helps with 00108 /// screen captures. 00109 RenderBuffer* m_render_buffer ; 00110 00111 /// The Robolocust UI uses the geometry specifications of the 00112 /// individual drawables to compute the dimensions of its main window 00113 /// and always resizes itself to that exact size. These data members 00114 /// are used to keep track of this "ideal" size. 00115 int m_width, m_height ; 00116 00117 /// The main window manages all of the rendering related tasks by 00118 /// maintaining a list of drawable objects. However, instead of a 00119 /// plain list, we use a map that associates drawable names to the 00120 /// drawables. This map is useful in situations where one drawable 00121 /// needs to render something in another drawable's area. 00122 //@{ 00123 typedef std::list<Drawable*> Drawables ; 00124 Drawables m_drawables ; 00125 //@} 00126 00127 /// Because the main thread will add drawables to the main window's 00128 /// drawables list while the main window's thread uses it during 00129 /// rendering, we need to synchronize accesses to the above data 00130 /// structure. 00131 /// 00132 /// DEVNOTE: This member is declared mutable so that it can be passed 00133 /// to the pthread mutex functions without requiring a cast when used 00134 /// from const member functions. 00135 mutable Mutex m_drawables_mutex ; 00136 00137 /// We also need a mutex to protect the m_window variable because the 00138 /// main window is responsible for implementing part of the two-step 00139 /// initialization sequence for drawables. 00140 /// 00141 /// Each drawable may specify OpenGL related initialization in its 00142 /// gl_init() function. Drawables should not call any OpenGL 00143 /// functions in their constructors because it is possible that the 00144 /// GL rendering context may not yet be up when that drawable is 00145 /// created. 00146 /// 00147 /// Since only the main window really knows when GL is ready, it 00148 /// makes sense for this class to invoke Drawable::gl_init() for each 00149 /// member of the drawables list. Usually, this would happen right 00150 /// after the creation of the GL window but before the GL message 00151 /// loop begins. However, some drawables may be added after the GL 00152 /// message loop has commenced. We have to trigger gl_init() for 00153 /// these Johnny-come-latelies just before they get added to the 00154 /// drawables list by checking if m_window denotes a valid GL window 00155 /// or not. Hence the need for this mutex. 00156 Mutex m_window_mutex ; 00157 00158 /// This inner class encapsulates the pixel data returned by the 00159 /// off-screen render buffer and is used in conjunction with the 00160 /// Robolocust UI's screen capture facility. 00161 class ScreenCapture { 00162 std::string m_name ; // file name 00163 const int m_width, m_height ; // dimensions 00164 std::vector<unsigned char> m_data ; // pixel data 00165 00166 public: 00167 /// This constructor is used when we want to save a single frame to 00168 /// a file of the specified name (screenshots taken by user). 00169 ScreenCapture(const std::string& file_name, int width, int height, 00170 const unsigned char* buf, int bufsiz) ; 00171 00172 /// This constructor is meant to be used when automatic, continuous 00173 /// screen captures are on (for later encoding to a movie). 00174 ScreenCapture(int frame_number, int width, int height, 00175 const unsigned char* buf, int bufsiz) ; 00176 00177 /// This method saves the captured frame to the file whose name was 00178 /// either supplied directly by the client (first constructor, 00179 /// single shot mode) or derived from the frame number (second 00180 /// constructor, continuous capture mode). 00181 void save() const ; 00182 } ; 00183 00184 /// Since writing a screen capture frame to disk can take a while and 00185 /// hold up the visualization thread's rendering and user interaction 00186 /// workflow, we refrain from saving these frames right after getting 00187 /// the pixel data from the off-screen render buffer. Instead, we put 00188 /// the frame into a queue and then, when the program is idling, take 00189 /// the next pending frame and write that out. 00190 std::queue<ScreenCapture*> m_capture_queue ; 00191 00192 /// Each screen capture frame will be named like so: frame000.png, 00193 /// frame001.png, frame002.png, and so on. This data member keeps 00194 /// track of the next index number for the frame names. 00195 int m_frame_number ; 00196 00197 /// Private constructor because the main window is a singleton. 00198 MainWindow() ; 00199 00200 /// Since the Robolocust UI uses GLUT (which implements its own main 00201 /// loop), we need to run it in a separate thread from the rest of the 00202 /// Robolocust system. 00203 void run() ; 00204 00205 public: 00206 /// This method adds a drawable to the main window. 00207 void push_back(Drawable*) ; 00208 00209 // STL compatibility 00210 typedef Drawables::const_reference const_reference ; 00211 00212 private: 00213 /// Since GLUT runs its own main loop, independent of the rest of the 00214 /// Robolocust system, we cannot update the visualization as part of 00215 /// the lobot::App object's main loop. Instead, we use a GLUT timer to 00216 /// trigger updates. This method sets up the update timer. 00217 void setup_timer() ; 00218 00219 /// This method is called every time the main window's GLUT update 00220 /// timer fires. It simply invalidates the GLUT window in order to 00221 /// trigger a rendering operation. 00222 void update() ; 00223 00224 /// This method renders all the drawables currently connected to the 00225 /// main window. 00226 void render() ; 00227 00228 /// This method saves the next pending frame in the screen capture 00229 /// queue. It is invoked from the idle handler so as to not tie up the 00230 /// main visualization thread. 00231 void dump_next_frame() ; 00232 00233 public: 00234 /// This function can be used to save a screenshot of the Robolocust 00235 /// UI to the specified file. 00236 void save_screenshot(const std::string& file_name) const ; 00237 00238 private: 00239 /// This method responds to UI window resize events. 00240 void reshape(int width, int height) ; 00241 00242 /// These methods respond to different key presses. We use a dispatch 00243 /// table to "route" key presses to the appropriate handler. 00244 //{@ 00245 void handle_key(unsigned char key) ; 00246 00247 typedef void (MainWindow::*KeyHandler)() ; 00248 typedef std::map<unsigned char, KeyHandler> KeyMap ; 00249 KeyMap m_keymap ; // dispatch table 00250 00251 void reset_zoom_pan() ; 00252 void pause() ; 00253 void quit() ; 00254 //@} 00255 00256 /// These functions and variables take care of different mouse events. 00257 //@{ 00258 int m_drag_button ; 00259 int m_drag_modifiers ; 00260 int m_drag_prev[2] ; 00261 00262 void left_click (int state, int modifiers, int x, int y) ; 00263 void middle_click(int state, int modifiers, int x, int y) ; 00264 void right_click (int state, int modifiers, int x, int y) ; 00265 00266 void left_drag (int x, int y) ; 00267 void middle_drag(int x, int y) ; 00268 void right_drag (int x, int y) ; 00269 //@} 00270 00271 /// GLUT callbacks 00272 //@{ 00273 static void reshape_callback(int width, int height) ; 00274 static void render_callback() ; 00275 static void keyboard_callback(unsigned char key, int mouse_x, int mouse_y) ; 00276 static void click_callback(int button, int state, int x, int y) ; 00277 static void drag_callback(int x, int y) ; 00278 static void timer_callback(int timer_id) ; 00279 static void idle_callback() ; 00280 //@} 00281 00282 public: 00283 /// Destroy the main window. 00284 ~MainWindow() ; 00285 } ; 00286 00287 //----------------------------------------------------------------------- 00288 00289 } // end of namespace encapsulating this file's definitions 00290 00291 #endif 00292 00293 /* So things look consistent in everyone's emacs... */ 00294 /* Local Variables: */ 00295 /* indent-tabs-mode: nil */ 00296 /* End: */