LoDrawable.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/ui/LoDrawable.H
00003    \brief A base class for rendering things in the Robolocust UI.
00004 
00005    This file defines a base class meant to provide an interface for
00006    rendering the different things that get shown in the Robolocust main
00007    window.
00008 
00009    By default, lobot::Drawable's rendering related methods are all empty.
00010    Every Robolocust object that needs to present some sort of
00011    visualization must define this file's lobot::Drawable class as a base
00012    and override the render_me() method (and any other methods that are
00013    necessary) in order to draw itself.
00014 
00015    NOTE: Robolocust uses OpenGL for visualization. All objects that
00016    derive from lobot::Drawable and override its render_me() and other
00017    methods must, therefore, work in terms of the OpenGL API.
00018 */
00019 
00020 // //////////////////////////////////////////////////////////////////// //
00021 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00022 // by the University of Southern California (USC) and the iLab at USC.  //
00023 // See http://iLab.usc.edu for information about this project.          //
00024 // //////////////////////////////////////////////////////////////////// //
00025 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00026 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00027 // in Visual Environments, and Applications'' by Christof Koch and      //
00028 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00029 // pending; application number 09/912,225 filed July 23, 2001; see      //
00030 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00031 // //////////////////////////////////////////////////////////////////// //
00032 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00033 //                                                                      //
00034 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00035 // redistribute it and/or modify it under the terms of the GNU General  //
00036 // Public License as published by the Free Software Foundation; either  //
00037 // version 2 of the License, or (at your option) any later version.     //
00038 //                                                                      //
00039 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00040 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00041 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00042 // PURPOSE.  See the GNU General Public License for more details.       //
00043 //                                                                      //
00044 // You should have received a copy of the GNU General Public License    //
00045 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00046 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00047 // Boston, MA 02111-1307 USA.                                           //
00048 // //////////////////////////////////////////////////////////////////// //
00049 //
00050 // Primary maintainer for this file: mviswana usc edu
00051 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/ui/LoDrawable.H $
00052 // $Id: LoDrawable.H 13967 2010-09-18 08:00:07Z mviswana $
00053 //
00054 
00055 #ifndef LOBOT_DRAWABLE_DOT_H
00056 #define LOBOT_DRAWABLE_DOT_H
00057 
00058 //------------------------------ HEADERS --------------------------------
00059 
00060 // lobot headers
00061 #include "Robots/LoBot/thread/LoMutex.H"
00062 #include "Robots/LoBot/misc/LoTypes.H"
00063 
00064 // Standard C++ headers
00065 #include <string>
00066 #include <list>
00067 #include <utility>
00068 
00069 //----------------------------- NAMESPACE -------------------------------
00070 
00071 namespace lobot {
00072 
00073 //------------------------- CLASS DEFINITION ----------------------------
00074 
00075 /**
00076    \class lobot::Drawable
00077    \brief A base class for Robolocust drawable objects.
00078 
00079    This class provides a common interface that allows the Robolocust main
00080    window to render each of the different Robolocust objects.
00081 
00082    All drawables will be assigned a drawing area within the main window
00083    and must render themselves inside that area. In some cases, a
00084    drawable's drawing area is computed by lobot::MainWindow. However, in
00085    most cases a drawable's drawing area is simply looked up from the
00086    lobot config file.
00087 
00088    DEVNOTE: By default, this class's methods are all virtual and empty.
00089    They are not pure virtual to ensure that leaf classes that don't care
00090    for visualization are not forced to define unnecessary empty methods.
00091    For example, lobot::SpeedArbiter does not present any visualization;
00092    however, its base class lobot::Arbiter does use lobot::Drawable as a
00093    base so as to allow lobot::TurnArbiter to present its visualization.
00094 
00095    Of course, we could simply have leaf classes that need to visualize,
00096    such as lobot::TurnArbiter, derive directly from lobot::Drawable and
00097    then declare all of lobot::Drawable's methods pure virtual. However,
00098    we choose not to do it this way because the main thread's lobot::App
00099    object would then have to work in terms of the leaf classes/objects.
00100 
00101    For the arbiters, that's not a big deal because the Robolocust system
00102    only uses two DAMN arbiters and they're both singletons.
00103    Unfortunately, the situation is not quite as clean when it comes to
00104    behaviours. If we were to require all the leaf classes to derive from
00105    lobot::Drawable, then lobot::App would have to downcast to each
00106    behaviour's instance and add that to lobot::MainWindow's list of
00107    drawables, which pretty much defeats the whole purpose of having a
00108    polymorphic factory for creating behaviours.
00109 
00110    Instead, by deriving lobot::Behavior from lobot::Drawable, we ensure
00111    that all behaviours are drawables and that the main thread need not
00112    concern itself with the exact type of each object it creates.
00113    Furthermore, a behaviour or other object that does not care to perform
00114    any visualization can rely on the empty virtual functions in
00115    lobot::Drawable instead of being forced to define empty functions.
00116 */
00117 class Drawable {
00118    // Prevent copy and assignment
00119    Drawable(const Drawable&) ;
00120    Drawable& operator=(const Drawable&) ;
00121 
00122    /// Each drawable has a name that must be set by the derived class.
00123    std::string m_name ;
00124 
00125    /// Each drawable has a geometry specification read from the lobot
00126    /// config file. A geometry specification consists of the (x,y)
00127    /// coordinates of the drawable's top-left corner within the
00128    /// Robolocust main window and a [width, height] pair in pixels with
00129    /// width going to the right and height going down (exactly like X
00130    /// Window geometry specs).
00131    ///
00132    /// In some situations, we may want a drawable to be active, i.e.,
00133    /// added to the main window, so that it can process keyboard input
00134    /// but not visible, i.e., the drawable doesn't really draw anything
00135    /// (perhaps it simply renders overlays on other drawables). To make a
00136    /// drawable invisible, simply set its dimensions in its geometry to
00137    /// negative quantities.
00138    //@{
00139 public:
00140    struct Geometry {
00141       int x, y ;
00142       int width, height ;
00143 
00144       /// Default constructor.
00145       Geometry(int x = 0, int y = 0, int width = -1, int height = -1) ;
00146 
00147       /// A convenience constructor for parsing a geometry spec passed in
00148       /// as a whitespace-separated string (e.g., a geometry spec read
00149       /// from the config file).
00150       Geometry(const std::string& geometry) ;
00151    } ;
00152 protected:
00153    Geometry m_geometry ;
00154    //@}
00155 
00156    /// In addition to rendering itself, each drawable also supports
00157    /// rendering arbitrary overlays on top of itself. This is useful, for
00158    /// instance, with the open path behaviour, which likes to paint the
00159    /// candidate open paths on top of the LRF data visualization.
00160    ///
00161    /// Overlays are rendered via callback functions. Client modules
00162    /// register such a callback along with any client data they require
00163    /// to be passed back when the callback is triggered. The client data
00164    /// is always an unsigned long and can be used to pass object
00165    /// pointers that can then be dereferenced inside the callback to
00166    /// invoke a member function.
00167    ///
00168    /// These types are used to define the rendering callbacks.
00169    //@{
00170    typedef void (*RenderCB)(unsigned long client_data) ;
00171    typedef std::pair<RenderCB, unsigned long> RenderHook ;
00172    //@}
00173 private:
00174    /// This data structure is used to hold all of a drawable's overlay
00175    /// rendering callbacks.
00176    //@{
00177    typedef std::list<RenderHook> Hooks ;
00178    Hooks m_hooks ;
00179    //@}
00180 
00181    /// Because overlays will often be added by drawbles running in other
00182    /// threads while the visualization thread reads the list of overlays
00183    /// during its rendering cycle, we need to synchronize accesses to the
00184    /// overlays list.
00185    Mutex m_hooks_mutex ;
00186 
00187    /// Since the rendering functions are invoked by the UI thread and
00188    /// often need to use state data stored in the objects being rendered,
00189    /// which usually belong to other threads (such as the arbiters and
00190    /// behaviours), all drawables will need some mechanism for
00191    /// coordinating access to the afore-mentioned state data. A mutex is
00192    /// just the thing we're looking for to solve this problem.
00193    ///
00194    /// The lobot::Drawable base class takes care of properly creating and
00195    /// destroying this mutex. It also provides an API for locking and
00196    /// unlocking this mutex. However, it cannot enforce the use of the
00197    /// mutex. Derived classes must do so as required at their discretion.
00198    Mutex m_viz_mutex ;
00199 
00200 protected:
00201    /// By default, we always draw a border around each drawable to help
00202    /// clearly demarcate each of them. However, that may not be
00203    /// appropriate or desirable for some drawables. This flag can be used
00204    /// by derived classes to turn the border off on a case-by-case basis.
00205    bool m_border ;
00206 
00207    /// In addition to allowing derived classes to turn the drawable
00208    /// border on or off, we also allow them specify a suitable border
00209    /// color. The default border color is yellow.
00210    GLColor m_border_color ;
00211 
00212    /// A protected constructor because only derived classes can invoke
00213    /// it. And when they do, they must specify the drawable's name and
00214    /// its geometry.
00215    Drawable(const std::string&, const Geometry&) ;
00216 
00217 public:
00218    /// Drawables should refrain from making any OpenGL calls until they
00219    /// can be absolutely sure that the GL rendering context is open for
00220    /// business. Unfortunately, a drawable cannot by itself determine
00221    /// when this happy situation might prevail. Thus, any OpenGL related
00222    /// initialization that a drawable might want to perform will have to
00223    /// be deferred to this function, which will be called by the
00224    /// lobot::MainWindow object when the time is right, viz., after the
00225    /// GL window is created but before the GL message loop commences
00226    /// and, for drawables created after the commencement of the GL
00227    /// message loop, just before they get added to the main window's
00228    /// drawables list.
00229    ///
00230    /// The default implementation of this method does nothing. Derived
00231    /// classes may override it if they need to.
00232    virtual void gl_init() ;
00233 
00234    /// Return this drawable's name.
00235    std::string name() const {return m_name ;}
00236 
00237    /// Return this drawable's geometry.
00238    Geometry geometry() const {return m_geometry ;}
00239 
00240    /// These functions check the visibility of this drawable. A drawable
00241    /// that is not visible will not take up any screen space within the
00242    /// Robolocust UI but can still be configured to actively receive and
00243    /// respond to keyboard input.
00244    //@{
00245    bool invisible() const {return !visible() ;}
00246    bool visible()   const {
00247       return m_geometry.width > 0 && m_geometry.height > 0 ;
00248    }
00249    //@}
00250 
00251    /// This method returns true if this drawable is configured to have a
00252    /// border drawn around its drawing area within the Robolocust UI.
00253    bool border() const {return m_border ;}
00254 
00255    /// This method returns the color in which the drawable's border
00256    /// should be rendered.
00257    const GLColor& border_color() const {return m_border_color ;}
00258 
00259    /// This function allows one drawable to add an overlay to another.
00260    void add_hook(const RenderHook&) ;
00261 
00262    /// This method renders the drawable itself plus any overlays.
00263    void render() ;
00264 
00265 private:
00266    /// A helper function for triggering the rendering hooks.
00267    static void trigger_hook(const RenderHook&) ;
00268 
00269    /// This method renders the drawable and must be overridden in derived
00270    /// classes.
00271    virtual void render_me() ;
00272 
00273 public:
00274    /// Drawables can support zoom/pan and keypress events.
00275    //@{
00276    virtual void zoom_by(float dz) ;
00277    virtual void pan(int curr_x, int curr_y, int prev_x, int prev_y) ;
00278    virtual void reset_zoom_pan() ;
00279    virtual void keypress(unsigned char key) ;
00280    //@}
00281 
00282 protected:
00283    /// API for locking and unlocking the visualization mutex.
00284    ///
00285    /// As mentioned earlier, this class cannot actually enforce proper
00286    /// use of the visualization mutex. (Actually, it could by
00287    /// locking/unlocking before/after the action and render methods;
00288    /// however, that would be too brutal and wasteful as we may only need
00289    /// the locks in small parts of these methods.) Thus, it is up to each
00290    /// derived class to call these functions as and when required.
00291    //@{
00292    void viz_lock()   {m_viz_mutex.acquire() ;}
00293    void viz_unlock() {m_viz_mutex.release() ;}
00294    //@}
00295 
00296    /// Some helper methods.
00297    //@{
00298    void unit_view_volume() const ;
00299    void text_view_volume() const ;
00300    void setup_view_volume(float L, float R, float B, float T) const ;
00301    void restore_view_volume() const ;
00302    //@}
00303 
00304 public:
00305    /// Just as drawables should refrain from performing GL
00306    /// initialization in their constructors (because the GL rendering
00307    /// context might not yet be available), they should also not perform
00308    /// any GL clean-up in their destructors just in case the rendering
00309    /// context is already gone.
00310    ///
00311    /// Instead, subclasses should override this method to perform OpenGL
00312    /// related clean-up. lobot::MainWindow will take care of triggering
00313    /// this function for each drawable just before rendering context is
00314    /// released. The default implementation of this method does nothing.
00315    virtual void gl_cleanup() ;
00316 
00317    /// Clean-up.
00318    virtual ~Drawable() ;
00319 } ;
00320 
00321 //-----------------------------------------------------------------------
00322 
00323 } // end of namespace encapsulating this file's definitions
00324 
00325 #endif
00326 
00327 /* So things look consistent in everyone's emacs... */
00328 /* Local Variables: */
00329 /* indent-tabs-mode: nil */
00330 /* End: */
Generated on Sun May 8 08:05:56 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3