arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Renderable.h

Go to the documentation of this file.
00001 //------------------------------------------------------------------------
00002 //C++ 
00003 //                   ________    ____   ___ 
00004 //                  |        \  /    | /  /
00005 //                  +---+     \/     |/  /
00006 //                  +--+|  |\    /|     < 
00007 //                  |  ||  | \  / |  |\  \ 
00008 //                  |      |  \/  |  | \  \ 
00009 //                   \_____|      |__|  \__\
00010 //                       Copyright  2002 
00011 //                      Joe Michael Kniss
00012 //               "All Your Base are Belong to Us"
00013 //-------------------------------------------------------------------------
00014 
00015 #ifndef __RENDERABLE_002_DOT_H
00016 #define __RENDERABLE_002_DOT_H
00017 
00018 #include <list>
00019 #include <vector>
00020 #include <eventGutz.h>
00021 #include <smartptr.h>
00022 #include <graphicsGutz.h>
00023 
00024 ////////////////////////////////////////////////////////////////////////////
00025 /// a unique identifier for this species of object, needed 
00026 ///  mostly for GL style picking, since we need to know what
00027 ///  kind of object was picked, so we can forward mouse/key 
00028 ///  events to it
00029 const unsigned int RENDERABLE_NAME = 80081355;
00030 ////////////////////////////////////////////////////////////////////////////
00031 
00032 ////////////////////////////////////////////////////////////////////////////
00033 /// Renderable.
00034 ///
00035 ///  This is the base class, and a new effect/renderer should sub-class from it.
00036 ///
00037 ///  Please note: this object contains a gutz::Manip smart pointer, when it
00038 ///  is constructed (by default) it creates a new manipulator (_manip).  USE IT! 
00039 ///  It is generally assumed that you might want to interact with your object
00040 ///  this is why we create one for you.  If you just want to interact with 
00041 ///  your object with the least amout of effort, call setManipEventsDefault()
00042 ///  and follow the notes on GL picking (below).  If you don't override the
00043 ///  mouse() and move() functions then events are automatically forwarded to your
00044 ///  Manip.  Apply your manip (using OpenGL) like this:
00045 /// \code
00046 ///    glPushMatrix();
00047 ///    {
00048 ///       glMultMatrixf(_manip->getWorldTransform().m);
00049 ///       /* ... draw stuff ...*/
00050 ///    }
00051 ///    glPopMatrix();
00052 /// \endcode 
00053 ///  I usually add the "{}" around a glPush/Pop to keep the code neat and the state 
00054 ///  clear.  Don't forget, if you want interaction using openGL, you have to push 
00055 ///  2 specific unsigned int "names" on the gl-name-stack.
00056 ///
00057 /// NOTE on GL picking (gl interaction): \n
00058 ///   There are 2 strict rules for GL style picking of renderables.  \n
00059 ///   1) push the #RENDERABLE_NAME on the gl name stack first \n
00060 ///   2) push your (Renderable*) pointer onto the stack as an unsigned int \n
00061 ///   Like this:
00062 /// \code
00063 ///   glPushName(RENDERABLE_NAME);
00064 ///   glPushName((unsigned int)(Renderable *)this);
00065 /// \endcode
00066 ///   Item 2 is actually a little tricky.  You should ALWAYS cast to 
00067 ///   Renderable* before casting to unsigned int.
00068 ///   This is VERY important if the type you are setting up is polymorphic;
00069 ///   the "this" pointer may be incorrect when we cast to "Renderable*" in
00070 ///   the UI.  If you cast to "Renderable*" first, any ambiguity is resolved
00071 ///   and you get the right position in the class for the cast-back in the UI
00072 ///
00073 ///   There is a third rule, but it is obvious:\n
00074 ///   3) Pop all names that you pushed onto the stack back off when you are
00075 ///   done rendering. \n
00076 ///   Like this:
00077 /// \code 
00078 ///   glPopName();
00079 ///   glPopName();  /// plus one pop for each additional name you added
00080 /// \endcode
00081 ///   After you are done with items 1 & 2, you can push as much onto the 
00082 ///   stack as you like (within reason), just be sure you pop it all back off
00083 ///   (item 3). \n
00084 ///
00085 ///  Here is what your draw function might look like if you are using OpenGL,
00086 ///   you want interaction, and you are using the _manip for the transformation:
00087 /// \code
00088 ///  void draw(const gutz::RenderEvent &re)
00089 ///  {
00090 ///    glPushName(RENDERABLE_NAME); 
00091 ///    glPushName((unsigned int)(Renderable *)this);
00092 ///    glPushMatrix();
00093 ///    {
00094 ///       glMultMatrixf(_manip->getWorldTransform().m);
00095 ///       /* ... draw your geometry ...*/
00096 ///    }
00097 ///    glPopMatrix();
00098 ///    glPopName();  ///DONT FORGET THESE!!!
00099 ///    glPopName();
00100 ///  }
00101 /// \endcode
00102 ///
00103 /// Why is this object "Counted", see gutz::Counted and gutz::SmartPtr for 
00104 ///   details on what this means. \n
00105 /// This object really needs to be counted, since it is usualy the primary
00106 ///   interface to renderable objects for any framework that uses them.
00107 ///   This may be problematic in situations with polymorphisim in the
00108 ///   hierarchy's derivation.  Oh well, need to deal with this somehow, I think
00109 ///   that this kind of baddness will be rare if you can sepparate the 
00110 ///   appearance from the behavior/data associated with a renderable object. \n
00111 /// NOTE: Please be carefull, you need to make very sure that if a 
00112 ///   renderable pushes its name on the glName stack for GL style picking,
00113 ///   it better have a smartptr to it somewhere, or the object that created
00114 ///   it needs to do the reference counting, since the user interface is 
00115 ///   probably going to keep a smartptr to it too.  This can lead to trouble
00116 ///   if the user interface's smart pointer calls delete on the object because
00117 ///   it has no references, or the objects owner deletes it.  This is the 
00118 ///   classic smart pointer problem; bad things occur when we create objects
00119 ///   on the stack, or we create objects that have automatic deletion, like
00120 ///   non-smart pointer member variables. See gutz::SmartPtr & gutz::Counted
00121 ///
00122 /// See also: gutz::RenderEvent, gutz::MouseEvent, gutz::MouseMoveEvent
00123 /////////////////////////////////////////////////////////////////////////////
00124 
00125 class Renderable : public gutz::Counted {
00126 public:
00127    ~Renderable(){};
00128 
00129    ///////////////////////////////////////////////////////////////////////////
00130    ///@name DRAW!
00131    ///  This is the draw function.  Calling it renders the object. Pure virtual,
00132    ///    you must override this function in a subclass.  
00133    ///@{
00134    virtual void draw(const gutz::RenderEvent &rs) = 0;
00135    ///@}
00136    ///////////////////////////////////////////////////////////////////////////
00137    
00138    ///////////////////////////////////////////////////////////////////////////
00139    ///@name Draw on/off.
00140    ///@{
00141    bool isOn() const     { return _on; }
00142    void setOn(bool yes)  { _on = yes;  }
00143    ///@}
00144    ///////////////////////////////////////////////////////////////////////////
00145 
00146    ///////////////////////////////////////////////////////////////////////////
00147    ///@name Delete. 
00148    ///  Does this object need to be removed from a render list?
00149    ///  This means that the object is finished and anyone with a smart pointer
00150    ///  to it needs to delete the smart pointer and stop using the renderable.
00151    ///@{
00152    bool   needsDelete() const { return _deleteMe; }
00153    void   setDelete(bool yes) { _deleteMe = yes; if(yes) setOn(false);  }
00154    ///@}
00155    ///////////////////////////////////////////////////////////////////////////
00156 
00157    ///////////////////////////////////////////////////////////////////////////
00158    ///@name   Interaction Functions
00159    ///  Return true if the event was for you. By default interaction is
00160    ///    forwarded to your protected manipulator (_manip).  To use it
00161    ///    just apply it in your draw function.  However, if you don't
00162    ///    add any events or call setManipEventsDefault(), you won't have
00163    ///    any interaction.  Override these functions in your base class
00164    ///    to implement custom behaviors.
00165    //@{
00166    virtual  bool key(unsigned char k, int x, int y)    { return false; }
00167    virtual  bool mouse(const gutz::MouseEvent &me)     { return _manip->mouse(me); }
00168    virtual  bool move(const gutz::MouseMoveEvent &mme) { return _manip->move(mme); }
00169    //@}
00170    ///////////////////////////////////////////////////////////////////////////
00171 
00172    ///////////////////////////////////////////////////////////////////////////
00173    ///@name Selected
00174    ///   Is this object currently selected?
00175    ///@{
00176    virtual void setSelected(bool yes)      {_selected = yes;}
00177    bool isSelected() const                 {return _selected;}
00178    ///@}
00179    ///////////////////////////////////////////////////////////////////////////
00180 
00181    ///////////////////////////////////////////////////////////////////////////
00182    ///@name Manipulator Interface
00183    ///@{
00184    gutz::Manip  *getManip() const { return _manip.getPtr(); }
00185    void          setManip(gutz::Manip *const m) { _manip = m; }
00186    /// you have to call this to enable default interaction, OR
00187    ///   customize the manipulators events yourself.
00188    void          setManipEventsDefault()
00189    {
00190       _manip->mapEvent(gutz::GUTZ_LEFT_MOUSE, new gutz::RotateManipEvent(1.0f));
00191       _manip->mapEvent(gutz::GUTZ_MIDDLE_MOUSE, new gutz::TransZManipEvent(1.0f));
00192       _manip->mapEvent(gutz::GUTZ_RIGHT_MOUSE, new gutz::TransXYManipEvent(1.0f));
00193 #if 0
00194       _manip->mapEvent(gutz::OBJ_CENT_ROT,  gutz::GUTZ_LEFT_MOUSE,   1.0f);
00195       _manip->mapEvent(gutz::OBJ_STRANS_XY, gutz::GUTZ_RIGHT_MOUSE,  1.0f);
00196       _manip->mapEvent(gutz::OBJ_STRANS_XZ, gutz::GUTZ_MIDDLE_MOUSE, 1.0f);
00197 #endif
00198    }
00199    ///@}
00200    ///////////////////////////////////////////////////////////////////////////
00201 
00202 protected:
00203    ///////////////////////////////////////////////////////////////////////////
00204    /// since this is a base class/interface it cannot be publicly
00205    /// created.  Only derived classes can construct this guy.
00206    Renderable()
00207       : _on(true), 
00208         _selected(false), 
00209         _deleteMe(false), 
00210         _manip(new gutz::Manip()) 
00211    {}
00212    ///////////////////////////////////////////////////////////////////////////
00213 
00214    ///////////////////////////////////////////////////////////////////////////
00215    ///@name copy/assign
00216    ///@{
00217    Renderable(const Renderable &r)
00218       : _on(r._on),
00219         _selected(false),
00220         _manip(new gutz::Manip())
00221    {
00222       if(r._manip)
00223          *_manip = *(r._manip);
00224    }
00225    Renderable &operator=(const Renderable &r)
00226    {
00227       _on = r._on;
00228       if(r._manip)
00229          *_manip = *(r._manip);
00230       return *this;
00231    }
00232    ///@}
00233    ///////////////////////////////////////////////////////////////////////////
00234 
00235    bool     _on;       ///<is this renderable currently "render-able"?
00236    bool     _selected; ///<is this renderable selected?
00237    bool     _deleteMe; ///<does this object need to be deleted?
00238 
00239    /// You get a manipulator free, no charge
00240    gutz::ManipSP _manip;
00241 
00242 private:
00243 };
00244 
00245 typedef gutz::SmartPtr<Renderable>          RenderableSP;
00246 
00247 ///////////////////////////////////////////////////////////////////////////
00248 ///@name Lists/Vectors of renderables typedefined, for ease of use
00249 //@{
00250 
00251 typedef std::list<RenderableSP>             RenderableList; 
00252 typedef std::list<RenderableSP>::iterator   RenderableListIter;
00253 
00254 typedef std::vector<RenderableSP>           RenderableVec; 
00255 typedef std::vector<RenderableSP>::iterator RenderableVecIter;
00256 //@}
00257 ///////////////////////////////////////////////////////////////////////////
00258 
00259 
00260 #endif
00261 

Send questions, comments, and bug reports to:
jmk