Equalizer 1.0

eVolve/channel.cpp

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