Equalizer  1.4.1
eVolve/channel.cpp
00001 
00002 /* Copyright (c) 2006-2012, Stefan Eilemann <eile@equalizergraphics.com>
00003  *               2007-2011, Maxim Makhinya  <maxmah@gmail.com>
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * - Redistributions of source code must retain the above copyright notice, this
00009  *   list of conditions and the following disclaimer.
00010  * - Redistributions in binary form must reproduce the above copyright notice,
00011  *   this list of conditions and the following disclaimer in the documentation
00012  *   and/or other materials provided with the distribution.
00013  * - Neither the name of Eyescale Software GmbH nor the names of its
00014  *   contributors may be used to endorse or promote products derived from this
00015  *   software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "channel.h"
00031 
00032 #include "frameData.h"
00033 #include "initData.h"
00034 #include "node.h"
00035 #include "pipe.h"
00036 #include "window.h"
00037 #include "hlp.h"
00038 #include "framesOrderer.h"
00039 
00040 namespace eVolve
00041 {
00042 Channel::Channel( eq::Window* parent )
00043         : eq::Channel( parent )
00044         , _bgColor( eq::Vector3f::ZERO )
00045         , _drawRange( eq::Range::ALL )
00046         , _taint( getenv( "EQ_TAINT_CHANNELS" ))
00047 {
00048     eq::FrameDataPtr frameData = new eq::FrameData;
00049     frameData->setBuffers( eq::Frame::BUFFER_COLOR );
00050     _frame.setFrameData( frameData );
00051 }
00052 
00053 static void checkError( const std::string& msg ) 
00054 {
00055     const GLenum error = glGetError();
00056     if (error != GL_NO_ERROR)
00057         LBERROR << msg << " GL Error: " << error << std::endl;
00058 }
00059 
00060 
00061 bool Channel::configInit( const eq::uint128_t& initID )
00062 {
00063     if( !eq::Channel::configInit( initID ))
00064         return false;
00065 
00066     setNearFar( 0.001f, 10.0f );
00067     return true;
00068 }
00069 
00070 bool Channel::configExit()
00071 {
00072     eq::FrameDataPtr frameData = _frame.getFrameData();
00073     frameData->resetPlugins();
00074 
00075     return eq::Channel::configExit();
00076 }
00077 
00078 void Channel::frameStart( const eq::uint128_t& frameID,
00079                           const uint32_t frameNumber )
00080 {
00081     _drawRange = eq::Range::ALL;
00082     _bgColor = eq::Vector3f( 0.f, 0.f, 0.f );
00083 
00084     const BackgroundMode bgMode = _getFrameData().getBackgroundMode();
00085 
00086     if( bgMode == BG_WHITE )
00087         _bgColor = eq::Vector3f( 1.f, 1.f, 1.f );
00088     else
00089         if( bgMode == BG_COLOR || _taint )
00090              _bgColor = eq::Vector3f( getUniqueColor( )) / 255.f;
00091 
00092     eq::Channel::frameStart( frameID, frameNumber );
00093 }
00094 
00095 void Channel::frameClear( const eq::uint128_t& frameID )
00096 {
00097     applyBuffer();
00098     applyViewport();
00099 
00100     _drawRange = getRange();
00101     if( _drawRange == eq::Range::ALL )
00102         glClearColor( _bgColor.r(), _bgColor.g(), _bgColor.b(), 1.0f );
00103     else
00104         glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
00105 
00106     glClear( GL_COLOR_BUFFER_BIT );
00107 }
00108 
00109 
00110 static void setLights( eq::Matrix4f& invRotationM )
00111 {
00112     GLfloat lightAmbient[]  = {0.05f, 0.05f, 0.05f, 1.0f};
00113     GLfloat lightDiffuse[]  = {0.9f , 0.9f , 0.9f , 1.0f};
00114     GLfloat lightSpecular[] = {0.8f , 0.8f , 0.8f , 1.0f};
00115     GLfloat lightPosition[] = {1.0f , 1.0f , 1.0f , 0.0f};
00116 
00117     glLightfv( GL_LIGHT0, GL_AMBIENT,  lightAmbient  );
00118     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00119     glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00120 
00121     // rotate light in the opposite direction of the model rotation to keep
00122     // light position constant and avoid recalculating normals in the fragment
00123     // shader
00124     glPushMatrix();
00125     glMultMatrixf( invRotationM.array );
00126     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00127     glPopMatrix();
00128 }
00129 
00130 
00131 static eq::Vector4f _getTaintColor( const ColorMode colorMode,
00132                                     const eq::Vector3f& color )
00133 {
00134     if( colorMode == COLOR_MODEL )
00135         return eq::Vector4f::ZERO;
00136 
00137     eq::Vector4f taintColor( color.r(), color.g(), color.b(), 1.0 );
00138     const float alpha = ( colorMode == COLOR_HALF_DEMO ) ? 0.5 : 1.0;
00139 
00140     taintColor /= 255.f;
00141     taintColor      *= alpha;
00142     taintColor.a()   = alpha;
00143     return taintColor;
00144 }
00145 
00146 void Channel::frameDraw( const eq::uint128_t& frameID )
00147 {
00148     // Setup frustum
00149     EQ_GL_CALL( applyBuffer( ));
00150     EQ_GL_CALL( applyViewport( ));
00151     
00152     EQ_GL_CALL( glMatrixMode( GL_PROJECTION ));
00153     EQ_GL_CALL( glLoadIdentity( ));
00154     EQ_GL_CALL( applyFrustum( ));
00155 
00156     EQ_GL_CALL( glMatrixMode( GL_MODELVIEW ));
00157     EQ_GL_CALL( glLoadIdentity( ));
00158 
00159     // Setup lights before applying head transform, so the light will be
00160     // consistent in the cave
00161     const FrameData&    frameData   = _getFrameData();
00162     const eq::Matrix4f& rotation    = frameData.getRotation();
00163     const eq::Vector3f& translation = frameData.getTranslation();
00164 
00165     eq::Matrix4f     invRotationM;
00166     rotation.inverse( invRotationM );
00167     setLights( invRotationM );
00168 
00169     EQ_GL_CALL( applyHeadTransform( ));
00170 
00171     glTranslatef(  translation.x(), translation.y(), translation.z() );
00172     glMultMatrixf( rotation.array );
00173 
00174     Pipe*     pipe     = static_cast<Pipe*>( getPipe( ));
00175     Renderer* renderer = pipe->getRenderer();
00176     LBASSERT( renderer );
00177 
00178     eq::Matrix4f  modelviewM;     // modelview matrix
00179     eq::Matrix3f  modelviewITM;   // modelview inversed transposed matrix
00180     _calcMVandITMV( modelviewM, modelviewITM );
00181 
00182     // set fancy data colors
00183     const eq::Vector4f taintColor = _getTaintColor( frameData.getColorMode(),
00184                                                     getUniqueColor( ));
00185     const int normalsQuality = _getFrameData().getNormalsQuality();
00186 
00187     const eq::Range& range = getRange();
00188     renderer->render( range, modelviewM, modelviewITM, invRotationM,
00189                       taintColor, normalsQuality );
00190     checkError( "error during rendering " );
00191 
00192     _drawRange = range;
00193 
00194 #ifndef NDEBUG
00195     outlineViewport();
00196 #endif
00197 }
00198 
00199 bool Channel::useOrtho() const
00200 {
00201     const FrameData& frameData = _getFrameData();
00202     return frameData.useOrtho();
00203 }
00204 
00205 const FrameData& Channel::_getFrameData() const
00206 {
00207     const Pipe* pipe = static_cast< const Pipe* >( getPipe( ));
00208     return pipe->getFrameData();
00209 }
00210 
00211 void Channel::_calcMVandITMV(
00212                             eq::Matrix4f& modelviewM,
00213                             eq::Matrix3f& modelviewITM ) const
00214 {
00215     const FrameData& frameData = _getFrameData();
00216     const Pipe*      pipe      = static_cast< const Pipe* >( getPipe( ));
00217     const Renderer*  renderer  = pipe->getRenderer();
00218 
00219     if( renderer )
00220     {
00221         const VolumeScaling& volScaling = renderer->getVolumeScaling();
00222 
00223         eq::Matrix4f scale( eq::Matrix4f::ZERO );
00224         scale.at(0,0) = volScaling.W;
00225         scale.at(1,1) = volScaling.H;
00226         scale.at(2,2) = volScaling.D;
00227         scale.at(3,3) = 1.f;
00228 
00229         modelviewM = scale * frameData.getRotation();
00230     }
00231     modelviewM.set_translation( frameData.getTranslation( ));
00232     modelviewM = getHeadTransform() * modelviewM;
00233 
00234     //calculate inverse transposed matrix
00235     eq::Matrix4f modelviewIM;
00236     modelviewM.inverse( modelviewIM );
00237     eq::Matrix3f( modelviewIM ).transpose_to(  modelviewITM  );
00238 }
00239 
00240 
00241 static void _expandPVP( eq::PixelViewport& pvp, const eq::Images& images,
00242                         const eq::Vector2i& offset )
00243 {
00244     for( eq::Images::const_iterator i = images.begin();
00245          i != images.end(); ++i )
00246     {
00247         const eq::PixelViewport imagePVP = (*i)->getPixelViewport() + offset;
00248         pvp.merge( imagePVP );
00249     }
00250 }
00251 
00252 
00253 void Channel::clearViewport( const eq::PixelViewport &pvp )
00254 {
00255     // clear given area
00256     glScissor(  pvp.x, pvp.y, pvp.w, pvp.h );
00257 
00258     if( _drawRange == eq::Range::ALL )
00259         glClearColor( _bgColor.r(), _bgColor.g(), _bgColor.b(), 1.0f );
00260     else
00261         glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
00262 
00263     glClear( GL_COLOR_BUFFER_BIT );
00264 
00265     // restore assembly state
00266     const eq::PixelViewport& windowPVP = getWindow()->getPixelViewport();
00267     glScissor( 0, 0, windowPVP.w, windowPVP.h );
00268 }
00269 
00270 void Channel::_orderFrames( eq::Frames& frames )
00271 {
00272     eq::Matrix4f        modelviewM;   // modelview matrix
00273     eq::Matrix3f        modelviewITM; // modelview inversed transposed matrix
00274     const FrameData&    frameData = _getFrameData();
00275     const eq::Matrix4f& rotation  = frameData.getRotation();
00276 
00277     if( !useOrtho( ))
00278         _calcMVandITMV( modelviewM, modelviewITM );
00279 
00280     orderFrames( frames, modelviewM, modelviewITM, rotation, useOrtho( ));
00281 }
00282 
00283 
00284 void Channel::frameAssemble( const eq::uint128_t& frameID )
00285 {
00286     const bool composeOnly = (_drawRange == eq::Range::ALL);
00287 
00288     _startAssemble();
00289 
00290     const eq::Frames& frames = getInputFrames();
00291     eq::PixelViewport  coveredPVP;
00292     eq::Frames         dbFrames;
00293     eq::Zoom           zoom( eq::Zoom::NONE );
00294 
00295     // Make sure all frames are ready and gather some information on them
00296     for( eq::Frames::const_iterator i = frames.begin();
00297          i != frames.end(); ++i )
00298     {
00299         eq::Frame* frame = *i;
00300         {
00301             eq::ChannelStatistics stat( eq::Statistic::CHANNEL_FRAME_WAIT_READY,
00302                                         this );
00303             frame->waitReady( );
00304         }
00305         const eq::Range& range = frame->getRange();
00306         if( range == eq::Range::ALL ) // 2D frame, assemble directly
00307             eq::Compositor::assembleFrame( frame, this );
00308         else
00309         {
00310             dbFrames.push_back( frame );
00311             zoom = frame->getZoom();
00312             _expandPVP( coveredPVP, frame->getImages(), frame->getOffset() );
00313         }
00314     }
00315     coveredPVP.intersect( getPixelViewport( ));
00316 
00317     if( dbFrames.empty( ))
00318     {
00319         resetAssemblyState();
00320         return;
00321     }
00322 
00323     // calculate correct frames sequence
00324     eq::FrameDataPtr data = _frame.getFrameData();
00325     if( !composeOnly && coveredPVP.hasArea( ))
00326     {
00327         _frame.clear();
00328         data->setRange( _drawRange );
00329         dbFrames.push_back( &_frame );
00330     }
00331 
00332     _orderFrames( dbFrames );
00333 
00334     // Update range
00335     eq::Range newRange( 1.f, 0.f );
00336     for( size_t i = 0; i < dbFrames.size(); ++i )
00337     {
00338         const eq::Range range = dbFrames[i]->getRange();
00339         if( newRange.start > range.start ) newRange.start = range.start;
00340         if( newRange.end   < range.end   ) newRange.end   = range.end;
00341     }
00342     _drawRange = newRange;
00343 
00344     // check if current frame is in proper position, read back if not
00345     if( !composeOnly )
00346     {
00347         if( _bgColor == eq::Vector3f::ZERO && dbFrames.front() == &_frame )
00348             dbFrames.erase( dbFrames.begin( ));
00349         else if( coveredPVP.hasArea())
00350         {
00351             eq::Window::ObjectManager* glObjects = getObjectManager();
00352 
00353             _frame.setOffset( eq::Vector2i( 0, 0 ));
00354             _frame.setZoom( zoom );
00355             data->setPixelViewport( coveredPVP );
00356             _frame.readback( glObjects, getDrawableConfig(), getRegions( ));
00357             clearViewport( coveredPVP );
00358 
00359             // offset for assembly
00360             _frame.setOffset( eq::Vector2i( coveredPVP.x, coveredPVP.y ));
00361         }
00362     }
00363 
00364     // blend DB frames in order
00365     try
00366     {
00367         eq::Compositor::assembleFramesSorted( dbFrames, this, 0, 
00368                                               true /*blendAlpha*/ );
00369     }
00370     catch( const co::Exception& e )
00371     {
00372         LBWARN << e.what() << std::endl;
00373     }
00374 
00375     resetAssemblyState();
00376 }
00377 
00378 void Channel::_startAssemble()
00379 {
00380     applyBuffer();
00381     applyViewport();
00382     setupAssemblyState();
00383 }   
00384 
00385 void Channel::frameReadback( const eq::uint128_t& frameID )
00386 {
00387     // Drop depth buffer flag from all output frames
00388     const eq::Frames& frames = getOutputFrames();
00389     const FrameData& frameData = _getFrameData();
00390     for( eq::FramesCIter i = frames.begin(); i != frames.end(); ++i )
00391     {
00392         eq::Frame* frame = *i;
00393         frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality());
00394         frame->disableBuffer( eq::Frame::BUFFER_DEPTH );
00395         frame->getFrameData()->setRange( _drawRange );
00396     }
00397 
00398     eq::Channel::frameReadback( frameID );
00399 }
00400 
00401 void Channel::frameViewFinish( const eq::uint128_t& frameID )
00402 {
00403     _drawHelp();
00404     _drawLogo();
00405 }
00406 
00407 void Channel::_drawLogo( )
00408 {
00409     // Draw the overlay logo
00410     const Window* window = static_cast<Window*>( getWindow( ));
00411     const eq::util::Texture* texture = window->getLogoTexture();
00412     if( !texture )
00413         return;
00414 
00415     glMatrixMode( GL_PROJECTION );
00416     glLoadIdentity();
00417     applyScreenFrustum();
00418     glMatrixMode( GL_MODELVIEW );
00419     glLoadIdentity();
00420 
00421     glDisable( GL_DEPTH_TEST );
00422     glDisable( GL_LIGHTING );
00423     glEnable( GL_BLEND );
00424     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00425 
00426     glColor3f( 1.0f, 1.0f, 1.0f );
00427     const GLenum target = texture->getTarget();
00428     glEnable( target );
00429     texture->bind();
00430     glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00431     glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00432     
00433     const float tWidth = float( texture->getWidth( ) );
00434     const float tHeight = float( texture->getHeight( ) );
00435 
00436     const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth;
00437     const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight;
00438 
00439     glBegin( GL_QUADS ); {
00440         glTexCoord2f( 0, 0 );
00441         glVertex3f( 5.0f, 5.0f, 0.0f );
00442 
00443         glTexCoord2f( width, 0 );
00444         glVertex3f( tWidth + 5.0f, 5.0f, 0.0f );
00445 
00446         glTexCoord2f( width, height );
00447         glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f );
00448 
00449         glTexCoord2f( 0, height );
00450         glVertex3f( 5.0f, tHeight + 5.0f, 0.0f );
00451 
00452     } glEnd();
00453 
00454     glDisable( target );
00455     glDisable( GL_BLEND );
00456 }
00457 
00458 void Channel::_drawHelp()
00459 {
00460     const FrameData& frameData = _getFrameData();
00461     std::string message = frameData.getMessage();
00462 
00463     if( !frameData.showHelp() && message.empty( ))
00464         return;
00465 
00466     applyBuffer();
00467     applyViewport();
00468     setupAssemblyState();
00469 
00470     glDisable( GL_LIGHTING );
00471     glDisable( GL_DEPTH_TEST );
00472 
00473     glColor3f( 1.f, 1.f, 1.f );
00474 
00475     if( frameData.showHelp( ))
00476     {
00477         const eq::Window::Font* font = getWindow()->getSmallFont();
00478         std::string help = EVolve::getHelp();
00479         float y = 340.f;
00480 
00481         for( size_t pos = help.find( '\n' ); pos != std::string::npos;
00482              pos = help.find( '\n' ))
00483         {
00484             glRasterPos3f( 10.f, y, 0.99f );
00485 
00486             font->draw( help.substr( 0, pos ));
00487             help = help.substr( pos + 1 );
00488             y -= 16.f;
00489         }
00490         // last line
00491         glRasterPos3f( 10.f, y, 0.99f );
00492         font->draw( help );
00493     }
00494 
00495     if( !message.empty( ))
00496     {
00497         const eq::Window::Font* font = getWindow()->getMediumFont();
00498 
00499         const eq::Viewport& vp = getViewport();
00500         const eq::PixelViewport& pvp = getPixelViewport();
00501 
00502         const float width = pvp.w / vp.w;
00503         const float xOffset = vp.x * width;
00504 
00505         const float height = pvp.h / vp.h;
00506         const float yOffset = vp.y * height;
00507         const float yMiddle = 0.5f * height;
00508         float y = yMiddle - yOffset;
00509 
00510         for( size_t pos = message.find( '\n' ); pos != std::string::npos;
00511              pos = message.find( '\n' ))
00512         {
00513             glRasterPos3f( 10.f - xOffset, y, 0.99f );
00514             
00515             font->draw( message.substr( 0, pos ));
00516             message = message.substr( pos + 1 );
00517             y -= 22.f;
00518         }
00519         // last line
00520         glRasterPos3f( 10.f - xOffset, y, 0.99f );
00521         font->draw( message );
00522     }
00523 
00524     EQ_GL_CALL( resetAssemblyState( ));
00525 }
00526 }
Generated on Mon Nov 26 2012 14:41:48 for Equalizer 1.4.1 by  doxygen 1.7.6.1