Equalizer  1.2.1
eVolve/channel.cpp
00001 
00002 /* Copyright (c) 2006-2011, 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::FrameData* frameData = new eq::FrameData;
00049     frameData->setBuffers( eq::Frame::BUFFER_COLOR );
00050     _frame.setData( frameData );
00051 }
00052 
00053 static void checkError( const std::string& msg ) 
00054 {
00055     const GLenum error = glGetError();
00056     if (error != GL_NO_ERROR)
00057         EQERROR << 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 void Channel::frameStart( const eq::uint128_t& frameID,
00071                           const uint32_t frameNumber )
00072 {
00073     _drawRange = eq::Range::ALL;
00074     _bgColor = eq::Vector3f( 0.f, 0.f, 0.f );
00075 
00076     const BackgroundMode bgMode = _getFrameData().getBackgroundMode();
00077 
00078     if( bgMode == BG_WHITE )
00079         _bgColor = eq::Vector3f( 1.f, 1.f, 1.f );
00080     else
00081         if( bgMode == BG_COLOR || _taint )
00082              _bgColor = eq::Vector3f( getUniqueColor( )) / 255.f;
00083 
00084     eq::Channel::frameStart( frameID, frameNumber );
00085 }
00086 
00087 void Channel::frameClear( const eq::uint128_t& frameID )
00088 {
00089     applyBuffer();
00090     applyViewport();
00091 
00092     _drawRange = getRange();
00093     if( _drawRange == eq::Range::ALL )
00094         glClearColor( _bgColor.r(), _bgColor.g(), _bgColor.b(), 1.0f );
00095     else
00096         glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
00097 
00098     glClear( GL_COLOR_BUFFER_BIT );
00099 }
00100 
00101 
00102 static void setLights( eq::Matrix4f& invRotationM )
00103 {
00104     GLfloat lightAmbient[]  = {0.05f, 0.05f, 0.05f, 1.0f};
00105     GLfloat lightDiffuse[]  = {0.9f , 0.9f , 0.9f , 1.0f};
00106     GLfloat lightSpecular[] = {0.8f , 0.8f , 0.8f , 1.0f};
00107     GLfloat lightPosition[] = {1.0f , 1.0f , 1.0f , 0.0f};
00108 
00109     glLightfv( GL_LIGHT0, GL_AMBIENT,  lightAmbient  );
00110     glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
00111     glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );
00112 
00113     // rotate light in the opposite direction of the model rotation to keep
00114     // light position constant and avoid recalculating normals in the fragment
00115     // shader
00116     glPushMatrix();
00117     glMultMatrixf( invRotationM.array );
00118     glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
00119     glPopMatrix();
00120 }
00121 
00122 
00123 static eq::Vector4f _getTaintColor( const ColorMode colorMode,
00124                                     const eq::Vector3f& color )
00125 {
00126     if( colorMode == COLOR_MODEL )
00127         return eq::Vector4f::ZERO;
00128 
00129     eq::Vector4f taintColor( color.r(), color.g(), color.b(), 1.0 );
00130     const float alpha = ( colorMode == COLOR_HALF_DEMO ) ? 0.5 : 1.0;
00131 
00132     taintColor /= 255.f;
00133     taintColor      *= alpha;
00134     taintColor.a()   = alpha;
00135     return taintColor;
00136 }
00137 
00138 void Channel::frameDraw( const eq::uint128_t& frameID )
00139 {
00140     // Setup frustum
00141     EQ_GL_CALL( applyBuffer( ));
00142     EQ_GL_CALL( applyViewport( ));
00143     
00144     EQ_GL_CALL( glMatrixMode( GL_PROJECTION ));
00145     EQ_GL_CALL( glLoadIdentity( ));
00146     EQ_GL_CALL( applyFrustum( ));
00147 
00148     EQ_GL_CALL( glMatrixMode( GL_MODELVIEW ));
00149     EQ_GL_CALL( glLoadIdentity( ));
00150 
00151     // Setup lights before applying head transform, so the light will be
00152     // consistent in the cave
00153     const FrameData&    frameData   = _getFrameData();
00154     const eq::Matrix4f& rotation    = frameData.getRotation();
00155     const eq::Vector3f& translation = frameData.getTranslation();
00156 
00157     eq::Matrix4f     invRotationM;
00158     rotation.inverse( invRotationM );
00159     setLights( invRotationM );
00160 
00161     EQ_GL_CALL( applyHeadTransform( ));
00162 
00163     glTranslatef(  translation.x(), translation.y(), translation.z() );
00164     glMultMatrixf( rotation.array );
00165 
00166     Pipe*     pipe     = static_cast<Pipe*>( getPipe( ));
00167     Renderer* renderer = pipe->getRenderer();
00168     EQASSERT( renderer );
00169 
00170     eq::Matrix4f  modelviewM;     // modelview matrix
00171     eq::Matrix3f  modelviewITM;   // modelview inversed transposed matrix
00172     _calcMVandITMV( modelviewM, modelviewITM );
00173 
00174     // set fancy data colors
00175     const eq::Vector4f taintColor = _getTaintColor( frameData.getColorMode(),
00176                                                     getUniqueColor( ));
00177     const int normalsQuality = _getFrameData().getNormalsQuality();
00178 
00179     const eq::Range& range = getRange();
00180     renderer->render( range, modelviewM, modelviewITM, invRotationM,
00181                       taintColor, normalsQuality );
00182     checkError( "error during rendering " );
00183 
00184     _drawRange = range;
00185 
00186 #ifndef NDEBUG
00187     outlineViewport();
00188 #endif
00189 }
00190 
00191 bool Channel::useOrtho() const
00192 {
00193     const FrameData& frameData = _getFrameData();
00194     return frameData.useOrtho();
00195 }
00196 
00197 const FrameData& Channel::_getFrameData() const
00198 {
00199     const Pipe* pipe = static_cast< const Pipe* >( getPipe( ));
00200     return pipe->getFrameData();
00201 }
00202 
00203 void Channel::_calcMVandITMV(
00204                             eq::Matrix4f& modelviewM,
00205                             eq::Matrix3f& modelviewITM ) const
00206 {
00207     const FrameData& frameData = _getFrameData();
00208     const Pipe*      pipe      = static_cast< const Pipe* >( getPipe( ));
00209     const Renderer*  renderer  = pipe->getRenderer();
00210 
00211     if( renderer )
00212     {
00213         const VolumeScaling& volScaling = renderer->getVolumeScaling();
00214 
00215         eq::Matrix4f scale( eq::Matrix4f::ZERO );
00216         scale.at(0,0) = volScaling.W;
00217         scale.at(1,1) = volScaling.H;
00218         scale.at(2,2) = volScaling.D;
00219         scale.at(3,3) = 1.f;
00220 
00221         modelviewM = scale * frameData.getRotation();
00222     }
00223     modelviewM.set_translation( frameData.getTranslation( ));
00224     modelviewM = getHeadTransform() * modelviewM;
00225 
00226     //calculate inverse transposed matrix
00227     eq::Matrix4f modelviewIM;
00228     modelviewM.inverse( modelviewIM );
00229     eq::Matrix3f( modelviewIM ).transpose_to(  modelviewITM  );
00230 }
00231 
00232 
00233 static void _expandPVP( eq::PixelViewport& pvp, const eq::Images& images,
00234                         const eq::Vector2i& offset )
00235 {
00236     for( eq::Images::const_iterator i = images.begin();
00237          i != images.end(); ++i )
00238     {
00239         const eq::PixelViewport imagePVP = (*i)->getPixelViewport() + offset;
00240         pvp.merge( imagePVP );
00241     }
00242 }
00243 
00244 
00245 void Channel::clearViewport( const eq::PixelViewport &pvp )
00246 {
00247     // clear given area
00248     glScissor(  pvp.x, pvp.y, pvp.w, pvp.h );
00249 
00250     if( _drawRange == eq::Range::ALL )
00251         glClearColor( _bgColor.r(), _bgColor.g(), _bgColor.b(), 1.0f );
00252     else
00253         glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
00254 
00255     glClear( GL_COLOR_BUFFER_BIT );
00256 
00257     // restore assembly state
00258     const eq::PixelViewport& windowPVP = getWindow()->getPixelViewport();
00259     glScissor( 0, 0, windowPVP.w, windowPVP.h );
00260 }
00261 
00262 void Channel::_orderFrames( eq::Frames& frames )
00263 {
00264     eq::Matrix4f        modelviewM;   // modelview matrix
00265     eq::Matrix3f        modelviewITM; // modelview inversed transposed matrix
00266     const FrameData&    frameData = _getFrameData();
00267     const eq::Matrix4f& rotation  = frameData.getRotation();
00268 
00269     if( !useOrtho( ))
00270         _calcMVandITMV( modelviewM, modelviewITM );
00271 
00272     orderFrames( frames, modelviewM, modelviewITM, rotation, useOrtho( ));
00273 }
00274 
00275 
00276 void Channel::frameAssemble( const eq::uint128_t& frameID )
00277 {
00278     const bool composeOnly = (_drawRange == eq::Range::ALL);
00279 
00280     _startAssemble();
00281 
00282     const eq::Frames& frames = getInputFrames();
00283     eq::PixelViewport  coveredPVP;
00284     eq::Frames         dbFrames;
00285     eq::Zoom           zoom( eq::Zoom::NONE );
00286 
00287     // Make sure all frames are ready and gather some information on them
00288     for( eq::Frames::const_iterator i = frames.begin();
00289          i != frames.end(); ++i )
00290     {
00291         eq::Frame* frame = *i;
00292         {
00293             eq::ChannelStatistics stat( eq::Statistic::CHANNEL_FRAME_WAIT_READY,
00294                                         this );
00295             frame->waitReady( );
00296         }
00297         const eq::Range& range = frame->getRange();
00298         if( range == eq::Range::ALL ) // 2D frame, assemble directly
00299             eq::Compositor::assembleFrame( frame, this );
00300         else
00301         {
00302             dbFrames.push_back( frame );
00303             zoom = frame->getZoom();
00304             _expandPVP( coveredPVP, frame->getImages(), frame->getOffset() );
00305         }
00306     }
00307     coveredPVP.intersect( getPixelViewport( ));
00308 
00309     if( dbFrames.empty( ))
00310     {
00311         resetAssemblyState();
00312         return;
00313     }
00314 
00315     // calculate correct frames sequence
00316     eq::FrameData* data = _frame.getData();
00317     if( !composeOnly && coveredPVP.hasArea( ))
00318     {
00319         _frame.clear();
00320         data->setRange( _drawRange );
00321         dbFrames.push_back( &_frame );
00322     }
00323 
00324     _orderFrames( dbFrames );
00325 
00326     // Update range
00327     eq::Range newRange( 1.f, 0.f );
00328     for( size_t i = 0; i < dbFrames.size(); ++i )
00329     {
00330         const eq::Range range = dbFrames[i]->getRange();
00331         if( newRange.start > range.start ) newRange.start = range.start;
00332         if( newRange.end   < range.end   ) newRange.end   = range.end;
00333     }
00334     _drawRange = newRange;
00335 
00336     // check if current frame is in proper position, read back if not
00337     if( !composeOnly )
00338     {
00339         if( _bgColor == eq::Vector3f::ZERO && dbFrames.front() == &_frame )
00340             dbFrames.erase( dbFrames.begin( ));
00341         else if( coveredPVP.hasArea())
00342         {
00343             eq::Window::ObjectManager* glObjects = getObjectManager();
00344 
00345             _frame.setOffset( eq::Vector2i( 0, 0 ));
00346             _frame.setZoom( zoom );
00347             data->setPixelViewport( coveredPVP );
00348             _frame.readback( glObjects, getDrawableConfig( ));
00349             clearViewport( coveredPVP );
00350 
00351             // offset for assembly
00352             _frame.setOffset( eq::Vector2i( coveredPVP.x, coveredPVP.y ));
00353         }
00354     }
00355 
00356     // blend DB frames in order
00357     try
00358     {
00359         eq::Compositor::assembleFramesSorted( dbFrames, this, 0, 
00360                                               true /*blendAlpha*/ );
00361     }
00362     catch( const co::Exception& e )
00363     {
00364         EQWARN << e.what() << std::endl;
00365     }
00366 
00367     resetAssemblyState();
00368 }
00369 
00370 void Channel::_startAssemble()
00371 {
00372     applyBuffer();
00373     applyViewport();
00374     setupAssemblyState();
00375 }   
00376 
00377 void Channel::frameReadback( const eq::uint128_t& frameID )
00378 {
00379     // Drop depth buffer flag from all output frames
00380     const eq::Frames& frames = getOutputFrames();
00381     const FrameData& frameData = _getFrameData();
00382     for( eq::Frames::const_iterator i = frames.begin(); 
00383          i != frames.end(); ++i )
00384     {
00385         eq::Frame* frame = *i;
00386         frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality());
00387         frame->disableBuffer( eq::Frame::BUFFER_DEPTH );
00388         frame->getData()->setRange( _drawRange );
00389     }
00390 
00391     eq::Channel::frameReadback( frameID );
00392 }
00393 
00394 void Channel::frameViewFinish( const eq::uint128_t& frameID )
00395 {
00396     _drawHelp();
00397     _drawLogo();
00398 }
00399 
00400 void Channel::_drawLogo( )
00401 {
00402     // Draw the overlay logo
00403     const Window* window = static_cast<Window*>( getWindow( ));
00404     const eq::util::Texture* texture = window->getLogoTexture();
00405     if( !texture )
00406         return;
00407 
00408     glMatrixMode( GL_PROJECTION );
00409     glLoadIdentity();
00410     applyScreenFrustum();
00411     glMatrixMode( GL_MODELVIEW );
00412     glLoadIdentity();
00413 
00414     glDisable( GL_DEPTH_TEST );
00415     glDisable( GL_LIGHTING );
00416     glEnable( GL_BLEND );
00417     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00418 
00419     glColor3f( 1.0f, 1.0f, 1.0f );
00420     const GLenum target = texture->getTarget();
00421     glEnable( target );
00422     texture->bind();
00423     glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00424     glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00425     
00426     const float tWidth = float( texture->getWidth( ) );
00427     const float tHeight = float( texture->getHeight( ) );
00428 
00429     const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth;
00430     const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight;
00431 
00432     glBegin( GL_QUADS ); {
00433         glTexCoord2f( 0, 0 );
00434         glVertex3f( 5.0f, 5.0f, 0.0f );
00435 
00436         glTexCoord2f( width, 0 );
00437         glVertex3f( tWidth + 5.0f, 5.0f, 0.0f );
00438 
00439         glTexCoord2f( width, height );
00440         glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f );
00441 
00442         glTexCoord2f( 0, height );
00443         glVertex3f( 5.0f, tHeight + 5.0f, 0.0f );
00444 
00445     } glEnd();
00446 
00447     glDisable( target );
00448     glDisable( GL_BLEND );
00449 }
00450 
00451 void Channel::_drawHelp()
00452 {
00453     const FrameData& frameData = _getFrameData();
00454     std::string message = frameData.getMessage();
00455 
00456     if( !frameData.showHelp() && message.empty( ))
00457         return;
00458 
00459     applyBuffer();
00460     applyViewport();
00461     setupAssemblyState();
00462 
00463     glDisable( GL_LIGHTING );
00464     glDisable( GL_DEPTH_TEST );
00465 
00466     glColor3f( 1.f, 1.f, 1.f );
00467 
00468     if( frameData.showHelp( ))
00469     {
00470         const eq::Window::Font* font = getWindow()->getSmallFont();
00471         std::string help = EVolve::getHelp();
00472         float y = 340.f;
00473 
00474         for( size_t pos = help.find( '\n' ); pos != std::string::npos;
00475              pos = help.find( '\n' ))
00476         {
00477             glRasterPos3f( 10.f, y, 0.99f );
00478 
00479             font->draw( help.substr( 0, pos ));
00480             help = help.substr( pos + 1 );
00481             y -= 16.f;
00482         }
00483         // last line
00484         glRasterPos3f( 10.f, y, 0.99f );
00485         font->draw( help );
00486     }
00487 
00488     if( !message.empty( ))
00489     {
00490         const eq::Window::Font* font = getWindow()->getMediumFont();
00491 
00492         const eq::Viewport& vp = getViewport();
00493         const eq::PixelViewport& pvp = getPixelViewport();
00494 
00495         const float width = pvp.w / vp.w;
00496         const float xOffset = vp.x * width;
00497 
00498         const float height = pvp.h / vp.h;
00499         const float yOffset = vp.y * height;
00500         const float yMiddle = 0.5f * height;
00501         float y = yMiddle - yOffset;
00502 
00503         for( size_t pos = message.find( '\n' ); pos != std::string::npos;
00504              pos = message.find( '\n' ))
00505         {
00506             glRasterPos3f( 10.f - xOffset, y, 0.99f );
00507             
00508             font->draw( message.substr( 0, pos ));
00509             message = message.substr( pos + 1 );
00510             y -= 22.f;
00511         }
00512         // last line
00513         glRasterPos3f( 10.f - xOffset, y, 0.99f );
00514         font->draw( message );
00515     }
00516 
00517     EQ_GL_CALL( resetAssemblyState( ));
00518 }
00519 }
Generated on Fri Jun 8 2012 15:44:29 for Equalizer 1.2.1 by  doxygen 1.8.0