Equalizer
1.2.1
|
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 }