|
Equalizer
1.3.1-git
|
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::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 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 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 LBASSERT( 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(), getRegions( )); 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 LBWARN << 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::FramesCIter i = frames.begin(); i != frames.end(); ++i ) 00383 { 00384 eq::Frame* frame = *i; 00385 frame->setQuality( eq::Frame::BUFFER_COLOR, frameData.getQuality()); 00386 frame->disableBuffer( eq::Frame::BUFFER_DEPTH ); 00387 frame->getData()->setRange( _drawRange ); 00388 } 00389 00390 eq::Channel::frameReadback( frameID ); 00391 } 00392 00393 void Channel::frameViewFinish( const eq::uint128_t& frameID ) 00394 { 00395 _drawHelp(); 00396 _drawLogo(); 00397 } 00398 00399 void Channel::_drawLogo( ) 00400 { 00401 // Draw the overlay logo 00402 const Window* window = static_cast<Window*>( getWindow( )); 00403 const eq::util::Texture* texture = window->getLogoTexture(); 00404 if( !texture ) 00405 return; 00406 00407 glMatrixMode( GL_PROJECTION ); 00408 glLoadIdentity(); 00409 applyScreenFrustum(); 00410 glMatrixMode( GL_MODELVIEW ); 00411 glLoadIdentity(); 00412 00413 glDisable( GL_DEPTH_TEST ); 00414 glDisable( GL_LIGHTING ); 00415 glEnable( GL_BLEND ); 00416 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 00417 00418 glColor3f( 1.0f, 1.0f, 1.0f ); 00419 const GLenum target = texture->getTarget(); 00420 glEnable( target ); 00421 texture->bind(); 00422 glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 00423 glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 00424 00425 const float tWidth = float( texture->getWidth( ) ); 00426 const float tHeight = float( texture->getHeight( ) ); 00427 00428 const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth; 00429 const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight; 00430 00431 glBegin( GL_QUADS ); { 00432 glTexCoord2f( 0, 0 ); 00433 glVertex3f( 5.0f, 5.0f, 0.0f ); 00434 00435 glTexCoord2f( width, 0 ); 00436 glVertex3f( tWidth + 5.0f, 5.0f, 0.0f ); 00437 00438 glTexCoord2f( width, height ); 00439 glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f ); 00440 00441 glTexCoord2f( 0, height ); 00442 glVertex3f( 5.0f, tHeight + 5.0f, 0.0f ); 00443 00444 } glEnd(); 00445 00446 glDisable( target ); 00447 glDisable( GL_BLEND ); 00448 } 00449 00450 void Channel::_drawHelp() 00451 { 00452 const FrameData& frameData = _getFrameData(); 00453 std::string message = frameData.getMessage(); 00454 00455 if( !frameData.showHelp() && message.empty( )) 00456 return; 00457 00458 applyBuffer(); 00459 applyViewport(); 00460 setupAssemblyState(); 00461 00462 glDisable( GL_LIGHTING ); 00463 glDisable( GL_DEPTH_TEST ); 00464 00465 glColor3f( 1.f, 1.f, 1.f ); 00466 00467 if( frameData.showHelp( )) 00468 { 00469 const eq::Window::Font* font = getWindow()->getSmallFont(); 00470 std::string help = EVolve::getHelp(); 00471 float y = 340.f; 00472 00473 for( size_t pos = help.find( '\n' ); pos != std::string::npos; 00474 pos = help.find( '\n' )) 00475 { 00476 glRasterPos3f( 10.f, y, 0.99f ); 00477 00478 font->draw( help.substr( 0, pos )); 00479 help = help.substr( pos + 1 ); 00480 y -= 16.f; 00481 } 00482 // last line 00483 glRasterPos3f( 10.f, y, 0.99f ); 00484 font->draw( help ); 00485 } 00486 00487 if( !message.empty( )) 00488 { 00489 const eq::Window::Font* font = getWindow()->getMediumFont(); 00490 00491 const eq::Viewport& vp = getViewport(); 00492 const eq::PixelViewport& pvp = getPixelViewport(); 00493 00494 const float width = pvp.w / vp.w; 00495 const float xOffset = vp.x * width; 00496 00497 const float height = pvp.h / vp.h; 00498 const float yOffset = vp.y * height; 00499 const float yMiddle = 0.5f * height; 00500 float y = yMiddle - yOffset; 00501 00502 for( size_t pos = message.find( '\n' ); pos != std::string::npos; 00503 pos = message.find( '\n' )) 00504 { 00505 glRasterPos3f( 10.f - xOffset, y, 0.99f ); 00506 00507 font->draw( message.substr( 0, pos )); 00508 message = message.substr( pos + 1 ); 00509 y -= 22.f; 00510 } 00511 // last line 00512 glRasterPos3f( 10.f - xOffset, y, 0.99f ); 00513 font->draw( message ); 00514 } 00515 00516 EQ_GL_CALL( resetAssemblyState( )); 00517 } 00518 }
1.3.1-git by
1.8.0