SceneGraph.hh

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 //=============================================================================
00047 //
00048 //  CLASS SceneGraph
00049 //
00050 //=============================================================================
00051 
00052 #ifndef ACG_SCENEGRAPH_HH
00053 #define ACG_SCENEGRAPH_HH
00054 
00055 
00056 //== INCLUDES =================================================================
00057 
00058 #include "BaseNode.hh"
00059 #include "DrawModes.hh"
00060 #include "../GL/gl.hh"
00061 #include "../Math/VectorT.hh"
00062 #include <float.h>
00063 
00064 #include <QMouseEvent>
00065 
00066 //== NAMESPACES ===============================================================
00067 
00068 namespace ACG {
00069 namespace SceneGraph {
00070 
00071 
00072 //== CLASS DEFINITION =========================================================
00073 
00077 template<bool C, typename T = void>
00078 struct enable_if {
00079   typedef T type;
00080 };
00081 
00082 template<typename T>
00083 struct enable_if<false, T> { };
00084 
00085 #define HAS_MEM_FUNC(func) \
00086     template<typename T, typename Sign>                                               \
00087     struct has_##func {                                                               \
00088         template <typename U, U> struct type_check;                                   \
00089         template <typename _1> static char (& chk(type_check<Sign, &_1::func> *))[1]; \
00090         template <typename   > static char (& chk(...))[2];                           \
00091         static bool const value = sizeof(chk<T>(0)) == 1;                             \
00092     };
00093 
00094 HAS_MEM_FUNC(enter)
00095 
00096 // if the enter function is implemented
00097 template<typename Action> 
00098 typename enable_if<has_enter <Action, void (Action::*) (BaseNode *) >::value, void>::type
00099 if_has_enter(Action &_action, BaseNode *_node) {
00100   _action.enter (_node);
00101 }
00102 
00103 // if the enter function isn't implemented
00104 template<typename Action> 
00105 typename enable_if<!has_enter <Action, void (Action::*) (BaseNode *) >::value, void>::type
00106 if_has_enter(Action &, BaseNode *) {
00107 }
00108 
00109 HAS_MEM_FUNC(leave)
00110 
00111 // if the enter function is implemented
00112 template<typename Action> 
00113 typename enable_if<has_leave <Action, void (Action::*) (BaseNode *) >::value, void>::type
00114 if_has_leave(Action &_action, BaseNode *_node) {
00115   _action.leave (_node);
00116 }
00117 
00118 // if the enter function isn't implemented
00119 template<typename Action> 
00120 typename enable_if<!has_enter <Action, void (Action::*) (BaseNode *) >::value, void>::type
00121 if_has_leave(Action &, BaseNode *) {
00122 }
00123 
00124 //----------------------------------------------------------------------------
00125 
00126 
00131 template <class Action>
00132 void
00133 traverse( BaseNode* _node, Action& _action )
00134 {
00135   if (_node)
00136   {
00137     BaseNode::StatusMode status(_node->status());
00138     bool process_children(status != BaseNode::HideChildren);
00139 
00140     if (status != BaseNode::HideSubtree)
00141     {
00142 
00143       if (_node->status() != BaseNode::HideNode)
00144       {
00145         if_has_enter (_action, _node);
00146         if (_node->traverseMode() & BaseNode::NodeFirst)
00147           process_children &= _action(_node);
00148       }
00149 
00150       if (process_children)
00151       {
00152         BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
00153         for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
00154           if (~(*cIt)->traverseMode() & BaseNode::SecondPass)
00155             traverse(*cIt, _action);
00156         for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
00157           if ((*cIt)->traverseMode() & BaseNode::SecondPass)
00158             traverse(*cIt, _action);
00159       }
00160 
00161       if (_node->status() != BaseNode::HideNode)
00162       {
00163         if (_node->traverseMode() & BaseNode::ChildrenFirst)
00164           _action(_node);
00165         if_has_leave (_action, _node);
00166       }
00167     }
00168   }
00169 }
00170 
00171 //----------------------------------------------------------------------------
00172 
00178 template <class Action>
00179 class MetaAction
00180 {
00181   public:
00182     MetaAction (Action & _action, GLState& _state, unsigned int _drawmode) :
00183       action_(_action),
00184       state_(_state),
00185       drawmode_(_drawmode)
00186     {
00187     }
00188 
00189     bool operator()(BaseNode* _node)
00190     {
00191       return action_(_node, state_);
00192     }
00193 
00194     void enter (BaseNode *_node)
00195     {
00196       unsigned int drawmode = ((_node->drawMode() == DrawModes::DEFAULT) ?
00197                                drawmode_ : _node->drawMode());
00198       _node->enter(state_, drawmode);
00199     }
00200 
00201     void leave (BaseNode *_node)
00202     {
00203       unsigned int drawmode = ((_node->drawMode() == DrawModes::DEFAULT) ?
00204                                drawmode_ : _node->drawMode());
00205       _node->leave(state_, drawmode);
00206     }
00207 
00208   private:
00209     Action  &action_;
00210     GLState &state_;
00211     unsigned int drawmode_;
00212 
00213 };
00214 
00215 //----------------------------------------------------------------------------
00216 
00226 template <class Action>
00227 void
00228 traverse( BaseNode*     _node,
00229           Action&       _action,
00230           GLState&      _state,
00231           unsigned int  _drawmode=DrawModes::DEFAULT)
00232 {
00233   MetaAction<Action> action (_action, _state, _drawmode);
00234   traverse (_node, action);
00235 }
00236 
00237 //----------------------------------------------------------------------------
00238 
00239 
00247 class BoundingBoxAction
00248 {
00249 public:
00250 
00251   BoundingBoxAction() :
00252     bbMin_( FLT_MAX,  FLT_MAX,  FLT_MAX),
00253     bbMax_(-FLT_MAX, -FLT_MAX, -FLT_MAX),
00254     state_(false)
00255   { }
00256 
00257   bool operator()(BaseNode* _node)
00258   {
00259     Vec3f bbMin( FLT_MAX,  FLT_MAX,  FLT_MAX);
00260     Vec3f bbMax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
00261     _node->boundingBox(bbMin, bbMax);
00262 
00263     if ((bbMin[0] > bbMax[0]) ||
00264         (bbMin[1] > bbMax[1]) ||
00265         (bbMin[2] > bbMax[2]))
00266       return true;
00267 
00268     bbMin_.minimize(state_.modelview().transform_point (bbMin));
00269     bbMin_.minimize(state_.modelview().transform_point (bbMax));
00270     bbMax_.maximize(state_.modelview().transform_point (bbMin));
00271     bbMax_.maximize(state_.modelview().transform_point (bbMax));
00272     return true;
00273   }
00274 
00275   void enter (BaseNode *_node)
00276   {
00277     _node->enter(state_, DrawModes::DEFAULT);
00278   }
00279 
00280   void leave (BaseNode *_node)
00281   {
00282     _node->leave(state_, DrawModes::DEFAULT);
00283   }
00284 
00286   const Vec3f& bbMin() const { return bbMin_; }
00288   const Vec3f& bbMax() const { return bbMax_; }
00289 
00290 private:
00291 
00292   Vec3f        bbMin_, bbMax_;
00293   GLState      state_;
00294 };
00295 
00296 
00297 //----------------------------------------------------------------------------
00298 
00299 
00308 class FindNodeAction
00309 {
00310 public:
00311 
00313   FindNodeAction(unsigned int _node_id) :
00314     node_id_(_node_id), node_ptr_(0)  {}
00315 
00316   bool operator()(BaseNode* _node)
00317   {
00318     if (_node->id() == node_id_)
00319     {
00320       node_ptr_ = _node;
00321       return false;
00322     }
00323     return true;
00324   }
00325 
00327   BaseNode*  node_ptr() { return node_ptr_; }
00328 
00329 private:
00330 
00331   unsigned int  node_id_;
00332   BaseNode*     node_ptr_;
00333 };
00334 
00335 
00339 ACGDLLEXPORT
00340 BaseNode* find_node( BaseNode* _root, unsigned int _node_idx );
00341 
00342 
00343 //----------------------------------------------------------------------------
00344 
00345 
00354 class CollectDrawModesAction
00355 {
00356 public:
00357 
00358   CollectDrawModesAction() : drawModes_(0) {}
00359 
00360   bool operator()(BaseNode* _node)
00361   {
00362     drawModes_ |= _node->availableDrawModes();
00363     return true;
00364   }
00365 
00367   unsigned int drawModes() const { return drawModes_; }
00368 
00369 private:
00370 
00371   unsigned int drawModes_;
00372 };
00373 
00374 //----------------------------------------------------------------------------
00375 
00376 
00385 class CollectActiveDrawModesAction
00386 {
00387 public:
00388 
00389   CollectActiveDrawModesAction() : drawMode_(0) {}
00390 
00391   bool operator()(BaseNode* _node)
00392   {
00393     drawMode_ |= _node->drawMode();
00394     return true;
00395   }
00396 
00398   unsigned int drawMode() const { return drawMode_; }
00399 
00400 private:
00401 
00402   unsigned int drawMode_;
00403 };
00404 
00405 //----------------------------------------------------------------------------
00406 
00407 
00417 class SetDrawModesAction
00418 {
00419 public:
00420 
00421   SetDrawModesAction(unsigned int _mode) : newModes_(_mode) {}
00422 
00423   bool operator()(BaseNode* _node)
00424   {
00425     if ( newModes_ == DrawModes::DEFAULT )
00426       _node->drawMode( DrawModes::DEFAULT );
00427 
00428     unsigned int availableModes = _node->availableDrawModes();
00429 
00430     if ( availableModes & newModes_ )
00431       _node->drawMode( availableModes & newModes_ );
00432     else
00433       _node->drawMode( DrawModes::DEFAULT );
00434 
00435     return true;
00436   }
00437 
00438 private:
00439   unsigned int newModes_;
00440 };
00441 
00442 
00443 //----------------------------------------------------------------------------
00444 
00445 
00455 class DrawAction
00456 {
00457 public:
00458 
00460   DrawAction(unsigned int _drawMode, bool _blending)
00461     : drawMode_(_drawMode), blending_(_blending) {}
00462 
00463   bool operator()(BaseNode* _node, GLState& _state)
00464   {
00465     // draw only if Material status == DrawAction status
00466     if(_state.blending() == blending_)
00467     {
00468       _node->setDirty (false);
00469       if (_node->drawMode() == DrawModes::DEFAULT)
00470         _node->draw(_state, drawMode_);
00471       else
00472         _node->draw(_state, _node->drawMode());
00473     }
00474     return true;
00475   }
00476 
00477 private:
00478 
00479   unsigned int drawMode_;
00480   bool         blending_;
00481 };
00482 
00483 
00484 //----------------------------------------------------------------------------
00485 
00486 
00495 class ACGDLLEXPORT PickAction
00496 {
00497 public:
00498 
00500   PickAction(GLState &_state, PickTarget _target, unsigned int _drawmode) :
00501     state_(_state),
00502     pickTarget_(_target),
00503     drawmode_(_drawmode) {}
00504 
00505   bool operator()(BaseNode* _node);
00506 
00507   void enter(BaseNode* _node)
00508   {
00509     if (_node->drawMode() == DrawModes::DEFAULT)
00510         _node->enterPick(state_, pickTarget_, drawmode_);
00511       else
00512         _node->enterPick(state_, pickTarget_, _node->drawMode());    
00513   }
00514 
00515   void leave(BaseNode* _node)
00516   {
00517     if (_node->drawMode() == DrawModes::DEFAULT)
00518         _node->leavePick(state_, pickTarget_, drawmode_);
00519       else
00520         _node->leavePick(state_, pickTarget_, _node->drawMode());
00521   }
00522 
00523 private:
00524 
00525   GLState      &state_;
00526   PickTarget   pickTarget_;
00527   unsigned int drawmode_;
00528 };
00529 
00530 
00531 //----------------------------------------------------------------------------
00532 
00533 
00541 class MouseEventAction
00542 {
00543 public:
00544 
00545 
00546   MouseEventAction(QMouseEvent* _event) : event_(_event) {}
00547 
00548   bool operator()(BaseNode* _node, GLState& _state)
00549   {
00550     _node->mouseEvent(_state, event_);
00551     return true;
00552   }
00553 
00554 private:
00555 
00556   QMouseEvent* event_;
00557 };
00558 
00559 //----------------------------------------------------------------------------
00560 
00561 
00569 class CheckDirtyAction
00570 {
00571 public:
00572 
00573 
00574   CheckDirtyAction() : dirty_(false) {}
00575 
00576   bool operator()(BaseNode* _node)
00577   {
00578     dirty_ |= _node->isDirty();
00579     // don't traverse children if current node is _dirty
00580     return !dirty_;
00581   }
00582 
00583   bool isDirty() const { return dirty_; };
00584 
00585 private:
00586 
00587   bool dirty_;
00588 };
00589 
00590 
00591 //=============================================================================
00592 } // namespace SceneGraph
00593 } // namespace ACG
00594 //=============================================================================
00595 #endif // ACG_SCENEGRAPH_HH defined
00596 //=============================================================================
00597 

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .