server/view.cpp

00001 
00002 /* Copyright (c) 2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "view.h"
00019 
00020 #include "channel.h"
00021 #include "compound.h"
00022 #include "config.h"
00023 #include "configVisitor.h"
00024 #include "layout.h"
00025 #include "observer.h"
00026 #include "paths.h"
00027 
00028 #include <eq/net/dataOStream.h>
00029 
00030 using namespace eq::base;
00031 
00032 namespace eq
00033 {
00034 namespace server
00035 {
00036 
00037 View::View()
00038         : _layout( 0 )
00039 {
00040 }
00041 
00042 View::View( const View& from, Config* config )
00043         : eq::View( from )
00044         , _layout( 0 )
00045 {
00046     if( from._observer )
00047     {
00048         const Observer* oldObserver = static_cast< const Observer* >( 
00049             from._observer );
00050         const ObserverPath path( oldObserver->getPath( ));
00051 
00052         _observer = config->getObserver( path );
00053         EQASSERT( _observer );
00054     }
00055 
00056     // _channels will be added by Segment copy ctor
00057 }
00058 
00059 View::~View()
00060 {
00061     // Use copy - Channel::unsetOutput modifies vector
00062     ChannelVector channels = _channels;
00063     for( ChannelVector::const_iterator i = channels.begin();
00064          i != channels.end(); ++i )
00065     {
00066         Channel* channel = *i;
00067         channel->unsetOutput();
00068     }
00069 
00070     EQASSERT( _channels.empty( ));
00071     _channels.clear();
00072 
00073     if( _layout )
00074         _layout->removeView( this );
00075     _layout = 0;
00076 }
00077 
00078 void View::getInstanceData( net::DataOStream& os )
00079 {
00080     // This function is overwritten from eq::Object, since the class is
00081     // intended to be subclassed on the client side. When serializing a
00082     // server::View, we only transmit the effective bits, not all since that
00083     // potentially includes bits from subclassed eq::Views.
00084     const uint64_t dirty = DIRTY_CUSTOM - 1;
00085     os << dirty;
00086     serialize( os, dirty );
00087 }
00088 
00089 namespace
00090 {
00091 class ViewUpdater : public ConfigVisitor
00092 {
00093 public:
00094     ViewUpdater( const ChannelVector& channels ) : _channels( channels ) {}
00095     virtual ~ViewUpdater() {}
00096 
00097     virtual VisitorResult visit( Compound* compound )
00098         {
00099             const Channel* channel = compound->getChannel();
00100             if( !channel )
00101                 return TRAVERSE_CONTINUE;
00102 
00103             if( !compound->isDestination( ))
00104                 return TRAVERSE_PRUNE; // only change destination compounds
00105 
00106             if( std::find( _channels.begin(), _channels.end(), channel ) !=
00107                 _channels.end( )) // our destination channel
00108             {
00109                 compound->updateFrustum();
00110             }
00111 
00112             return TRAVERSE_PRUNE;            
00113         }
00114 private:
00115     const ChannelVector& _channels;
00116 };
00117 }
00118 
00119 void View::deserialize( net::DataIStream& is, const uint64_t dirtyBits )
00120 {
00121     eq::View::deserialize( is, dirtyBits );
00122 
00123     if( dirtyBits & ( DIRTY_WALL | DIRTY_PROJECTION | DIRTY_OVERDRAW ))
00124     {
00125         const ChannelVector& channels = getChannels();
00126         Config*              config   = getConfig();
00127         EQASSERT( config );
00128 
00129         ViewUpdater updater( channels );
00130         config->accept( updater );
00131     }
00132 }
00133 
00134 void View::setViewport( const Viewport& viewport )
00135 {
00136     _viewport = viewport;
00137     setDirty( DIRTY_VIEWPORT );
00138 }
00139 
00140 Config* View::getConfig()
00141 {
00142     EQASSERT( _layout );
00143     return _layout ? _layout->getConfig() : 0;
00144 }
00145 
00146 const Config* View::getConfig() const
00147 {
00148     EQASSERT( _layout );
00149     return _layout ? _layout->getConfig() : 0;
00150 }
00151 
00152 void View::addChannel( Channel* channel )
00153 {
00154     _channels.push_back( channel );
00155 }
00156 
00157 bool View::removeChannel( Channel* channel )
00158 {
00159     ChannelVector::iterator i = find( _channels.begin(), 
00160                                       _channels.end(), channel );
00161 
00162     EQASSERT( i != _channels.end( ));
00163     if( i == _channels.end( ))
00164         return false;
00165 
00166     _channels.erase( i );
00167     return true;
00168 }
00169 
00170 ViewPath View::getPath() const
00171 {
00172     EQASSERT( _layout );
00173     ViewPath path( _layout->getPath( ));
00174     
00175     const ViewVector&   views = _layout->getViews();
00176     ViewVector::const_iterator i = std::find( views.begin(),
00177                                               views.end(), this );
00178     EQASSERT( i != views.end( ));
00179     path.viewIndex = std::distance( views.begin(), i );
00180     return path;
00181 }
00182 
00183 void View::setObserver( Observer* observer )
00184 {
00185     if( _observer == observer )
00186         return;
00187 
00188     _observer = observer;
00189     setDirty( DIRTY_OBSERVER );
00190 }
00191 
00192 std::ostream& operator << ( std::ostream& os, const View* view )
00193 {
00194     if( !view )
00195         return os;
00196     
00197     os << disableFlush << disableHeader << "view" << std::endl;
00198     os << "{" << std::endl << indent;
00199     
00200     const std::string& name = view->getName();
00201     if( !name.empty( ))
00202         os << "name     \"" << name << "\"" << std::endl;
00203 
00204     const eq::Viewport& vp  = view->getViewport();
00205     if( vp.isValid( ) && vp != eq::Viewport::FULL )
00206         os << "viewport " << vp << std::endl;
00207 
00208     const Observer* observer = static_cast< const Observer* >(
00209         view->getObserver( ));
00210     if( observer )
00211     {
00212         const Config* config = view->getConfig();
00213         const std::string& observerName = observer->getName();
00214         if( observerName.empty() ||
00215             config->findObserver( observerName ) != observer )
00216         {
00217             os << observer->getPath() << std::endl;
00218         }
00219         else
00220             os << "observer \"" << observer->getName() << "\"" << std::endl;
00221     } 
00222 
00223     switch( view->getCurrentType( ))
00224     {
00225         case eq::View::TYPE_WALL:
00226             os << view->getWall() << std::endl;
00227             break;
00228         case eq::View::TYPE_PROJECTION:
00229             os << view->getProjection() << std::endl;
00230             break;
00231         default: 
00232             break;
00233     }
00234 
00235     os << exdent << "}" << std::endl << enableHeader << enableFlush;
00236     return os;
00237 }
00238 
00239 }
00240 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8