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: */