LoMainWindow.H

Go to the documentation of this file.
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: */
Generated on Sun May 8 08:41:31 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3