Main Page | Namespace List | Alphabetical List | Class List | File List | Class Members | File Members

Application.cpp

Go to the documentation of this file.
00001 #include "osgVRJPrecompiled.h"
00002 #include "Application.h"
00003 
00004 #include <osgUtil/RenderStage>
00005 #include <osgUtil/RenderGraph>
00006 #include <osg/FrameStamp>
00007 #include <osg/LightModel>
00008 #include <osg/MatrixTransform>
00009 #include <osgUtil/UpdateVisitor>
00010 
00011 #ifdef _OSG096_
00012 #include <osgUtil/DisplayListVisitor>
00013 #else
00014 #include <osgUtil/GLObjectsVisitor>
00015 #endif
00016 
00017 #include <vrj/Kernel/Kernel.h>
00018 
00019 #include <stdexcept>
00020 
00021 using namespace osgVRJ;
00022 
00023 #define CONSTRUCTOR_INITIALIZER_LIST\
00024   _scene_data(0x0),\
00025   _frame_stamp(new osg::FrameStamp),\
00026   _init_visitor(0x0),\
00027   _update_visitor(new osgUtil::UpdateVisitor),\
00028   _global_stateset(new osg::StateSet),\
00029   _scene_decorator(0x0),\
00030   _viewport(0x0),\
00031   _background_color(0,0,0,1),\
00032   _context_in_sync(false),\
00033   _frameNumber(0),\
00034   _initial_time(0.0),\
00035   _head_tracker(),\
00036   _sceneview()
00037 
00038 Application::Application() : vrj::GlApp(),
00039   CONSTRUCTOR_INITIALIZER_LIST
00040 {
00041   this->_construct();
00042 }
00043 
00044 Application::Application(vrj::Kernel* kern) : vrj::GlApp(kern),
00045   CONSTRUCTOR_INITIALIZER_LIST
00046 {
00047   this->_construct();
00048 }
00049 
00050 namespace osgVRJ
00051 {
00052   namespace Detail
00053   {
00054     struct LoadConfigFile
00055     {
00056       void operator() (const std::string& file)
00057       {
00058         vrj::Kernel* kern = vrj::Kernel::instance();
00059         kern->loadConfigFile( file.c_str() );
00060       }
00061     };
00062   };
00063 };
00064 
00065 Application::Application(const std::list<std::string>& configs) : vrj::GlApp(),
00066   CONSTRUCTOR_INITIALIZER_LIST
00067 {
00068   this->_construct();
00069   std::for_each(configs.begin(),configs.end(), Detail::LoadConfigFile());
00070 }
00071 
00072 void Application::_construct()
00073 {
00074   // Crank up the max number of contexts. When you figure out a good way to 
00075   // get the real number, then use it here instead of this hard-coded one. 
00076   // Note: this has to be done early. Waiting for init() or contextInit() is 
00077   // too late.
00078   osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts ( 20 );
00079 }
00080 
00081 Application::~Application()
00082 {
00083 }
00084 
00085 void Application::run()
00086 {
00087   vrj::Kernel* kernel = vrj::Kernel::instance();
00088   kernel->setApplication( this );
00089   kernel->start();
00090   kernel->waitForKernelStop();
00091 }
00092 
00093 // a method to autocenter, places the node in front of viewer
00094 void Application::viewAll ( osg::MatrixTransform* node, osg::Matrix::value_type zScale )
00095 {
00096   // Get the bounding sphere of the group.
00097   osg::BoundingSphere bs = node->getBound();
00098   osg::Vec3 c = bs.center();
00099 
00100   // Push it back so we can see it.
00101   osg::Matrix matrix;
00102   osg::Matrix::value_type z ( zScale * bs.radius() + c[2] );
00103   matrix.makeTranslate( -c[0], -c[1], -z );
00104   node->postMult( matrix );
00105 }
00106 
00107 void Application::contextInit()
00108 {
00109   // Make a new state.
00110   osg::ref_ptr<osg::State> state = new osg::State;
00111 
00112   // init visitor setup
00113 #ifdef _OSG096_
00114   typedef osgUtil::DisplayListVisitor VisitorType;
00115 #else
00116   typedef osgUtil::GLObjectsVisitor VisitorType;
00117 #endif
00118 
00119   VisitorType::Mode dlvMode = VisitorType::COMPILE_STATE_ATTRIBUTES;
00120 #ifndef __sgi
00121   dlvMode |= VisitorType::COMPILE_DISPLAY_LISTS;
00122 #endif
00123 
00124   osg::ref_ptr<VisitorType> dlv = new VisitorType(dlvMode);
00125   dlv->setState( state.get() );
00126   dlv->setNodeMaskOverride( 0xffffffff );
00127 
00128   // render stuff setup
00129   osg::ref_ptr<osgUtil::RenderStage> rs = new osgUtil::RenderStage;
00130   osg::ref_ptr<osgUtil::RenderGraph> rg = new osgUtil::RenderGraph;
00131 
00132   // cull visitor setup
00133   osg::ref_ptr<osgUtil::CullVisitor> cv = new osgUtil::CullVisitor;
00134   cv->setRenderStage( rs.get() );
00135   cv->setRenderGraph( rg.get() );
00136 
00137   osgUtil::SceneView* sv = new osgUtil::SceneView;
00138   sv->setState( state.get() );
00139   sv->setInitVisitor( dlv.get() );
00140   sv->setCullVisitor( cv.get() );
00141   sv->setRenderStage( rs.get() );
00142   sv->setRenderGraph( rg.get() );
00143 
00144   unsigned int unique_context_id = vrj::GlDrawManager::instance()->getCurrentContext();
00145   sv->getState()->setContextID(unique_context_id);
00146 
00147   // allocates things if not already valid,
00148   // then assigns the sceneview instance the
00149   // same values as this class maintains
00150   setUpSceneViewWithData(sv);
00151 
00152   sv->init();
00153   (*_sceneview) = sv;  
00154 }
00155 
00156 void Application::contextPreDraw()
00157 {
00158   osgUtil::SceneView* sv = getContextSpecificSceneView();
00159 
00160   // if necessary, make data members sync up with the sceneview's data
00161   if(!_context_in_sync)
00162     setUpSceneViewWithData(sv);
00163 }
00164 
00165 
00166 // Small class that pushes the state in constructor and pops it in destructor.
00167 // This is for exception safety.
00168 namespace osgVRJ
00169 {
00170   namespace Detail
00171   {
00172     struct OpenGlStackPushPop
00173     {
00174       OpenGlStackPushPop()
00175       {
00176         #if 0
00177         // Clear the errors.
00178         while ( GL_ERROR_NO != ::glGetError() ){}
00179         #endif
00180 
00181         glPushAttrib(GL_ALL_ATTRIB_BITS);
00182 
00183         glMatrixMode(GL_MODELVIEW);
00184         glPushMatrix();
00185 
00186         glMatrixMode(GL_PROJECTION);
00187         glPushMatrix();
00188 
00189         glMatrixMode(GL_TEXTURE);
00190         glPushMatrix();
00191       }
00192       ~OpenGlStackPushPop()
00193       {
00194         // Check for errors.
00195         #if 0
00196         assert ( GL_ERROR_NO == ::glGetError() );
00197         #endif
00198 
00199         glMatrixMode(GL_TEXTURE);
00200         glPopMatrix();
00201 
00202         glMatrixMode(GL_PROJECTION);
00203         glPopMatrix();
00204 
00205         glMatrixMode(GL_MODELVIEW);
00206         glPopMatrix();
00207 
00208         glPopAttrib();
00209       }
00210     };
00211   };
00212 };
00213 
00214 
00215 void Application::draw()
00216 {
00217   // For exception safety. Pushes attributes in constructor, pops them in destructor.
00218   Detail::OpenGlStackPushPop pushPop;
00219 
00220   osgUtil::SceneView* sv = getContextSpecificSceneView();
00221   vrj::GlDrawManager* mgr = vrj::GlDrawManager::instance();
00222   vprASSERT(mgr != NULL);
00223 
00224   // ? constantly adjust the viewport ?
00225   osg::Viewport* vp = sv->getViewport();
00226   setViewportByDrawManager(sv->getViewport(),mgr);
00227 
00228   // constantly update the projection matrix
00229   vrj::GlUserData* userData = mgr->currentUserData();
00230   vrj::Projection* projection = userData->getProjection();
00231   vrj::Frustum frustum = projection->getFrustum();
00232   sv->setProjectionMatrixAsFrustum(frustum[vrj::Frustum::VJ_LEFT],
00233                                    frustum[vrj::Frustum::VJ_RIGHT],
00234                                    frustum[vrj::Frustum::VJ_BOTTOM],
00235                                    frustum[vrj::Frustum::VJ_TOP],
00236                                    frustum[vrj::Frustum::VJ_NEAR],
00237                                    frustum[vrj::Frustum::VJ_FAR]);
00238 
00239   // constantly update the view matrix
00240   gmtl::Matrix44f proj_mat = projection->getViewMatrix();
00241 
00242   osg::ref_ptr<osg::RefMatrix> osg_proj_xform_mat= new osg::RefMatrix;
00243   osg_proj_xform_mat->set(proj_mat.mData);
00244   sv->setViewMatrix(*osg_proj_xform_mat);
00245 
00246   sv->cull();
00247   sv->draw();
00248 }
00249 
00250 // should only be called from a context-specific thread
00251 osgUtil::SceneView* Application::getContextSpecificSceneView()
00252 {
00253   osg::ref_ptr<osgUtil::SceneView> sv = *(_sceneview);
00254   return( sv.get() );
00255 }
00256 
00257 osg::Node* Application::getSceneData()
00258 {
00259   if(_scene_decorator.valid())
00260     return(_scene_decorator.get());
00261 
00262   else
00263     return(_scene_data.get());
00264 }
00265 
00266 double Application::getTimeSinceStart()
00267 {
00268   return(_head_tracker->getTimeStamp().secd() - _initial_time);
00269 }
00270 
00271 void Application::init()
00272 {
00273   _head_tracker.init("VJHead");
00274   _initial_time = _head_tracker->getTimeStamp().secd();
00275 
00276   if(_scene_data.valid())
00277     setSceneData(_scene_data.get());
00278 
00279   // frame stamp setup
00280   _frame_stamp->setFrameNumber(0);
00281   _frame_stamp->setReferenceTime(_initial_time);
00282 
00283   // update visitor setup
00284   _update_visitor->setFrameStamp(_frame_stamp.get());
00285   _update_visitor->setTraversalNumber(_frame_stamp->getFrameNumber());
00286 
00287   // Also set up the global state-set.
00288   this->initGlobalStateSet();
00289 }
00290 
00291 void Application::preFrame()
00292 {
00293   // advance the time value of the frame stamp
00294   _frame_stamp->setFrameNumber(_frameNumber++);
00295   _frame_stamp->setReferenceTime(getTimeSinceStart());
00296 
00297   update();  // traverse the scene
00298 }
00299 
00300 void Application::postFrame()
00301 {
00302   if(!_context_in_sync)
00303     _context_in_sync = true;
00304 }
00305 
00306 // application thread call settings done here will
00307 // be pushed out to all SceneView instances in
00308 // a context specific thread
00309 void Application::initGlobalStateSet()
00310 {
00311   // update visitor setup
00312   if(_update_visitor.valid())
00313     _update_visitor->setFrameStamp(_frame_stamp.get());
00314 
00315   // global state set setup
00316   _global_stateset = new osg::StateSet;
00317   _global_stateset->setGlobalDefaults();
00318   _global_stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON);
00319   _global_stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);
00320   _global_stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
00321 
00322   osg::AlphaFunc* alpha_func = new osg::AlphaFunc;
00323   alpha_func->setFunction(osg::AlphaFunc::GREATER,0.0f);
00324   _global_stateset->setAttributeAndModes(alpha_func,osg::StateAttribute::ON);
00325 
00326   osg::TexEnv* texEnv = new osg::TexEnv;
00327   texEnv->setMode(osg::TexEnv::MODULATE);
00328   _global_stateset->setTextureAttributeAndModes(0,texEnv,osg::StateAttribute::ON);
00329 
00330   osg::LightModel* light_model = new osg::LightModel;
00331   light_model->setAmbientIntensity(osg::Vec4(0.1f,0.1f,0.1f,1.0f));
00332   _global_stateset->setAttributeAndModes(light_model,osg::StateAttribute::ON);
00333 
00334   // background color setup
00335   setBackgroundColor( osg::Vec4(0.2,0.2,0.4,1.0) );
00336 
00337   // flag requesting sync of data members with each of the sceneviews.
00338   _context_in_sync = false;
00339 }
00340 
00341 void Application::setSceneData(osg::Node* data)
00342 {
00343   if(_scene_data == data)
00344     return;
00345 
00346   if(_scene_decorator.valid() && _scene_data.valid())
00347     _scene_decorator->removeChild( _scene_data.get() );
00348 
00349   _scene_data = data;
00350 
00351   if(_scene_decorator.valid() && _scene_data.valid())
00352     _scene_decorator->addChild( _scene_data.get() );
00353 
00354   _context_in_sync = false;
00355 }
00356 
00357 void Application::setSceneDecorator(osg::Group* decor)
00358 {
00359   if(_scene_decorator == decor) return;
00360 
00361   _scene_decorator = decor;
00362 
00363   if( decor && _scene_data.valid())
00364     {
00365       decor->addChild(_scene_data.get());
00366     }
00367 
00368   _context_in_sync = false;
00369 }
00370 
00371 // should only be called from a context-specific thread
00372 void Application::setUpSceneViewWithData(osgUtil::SceneView* sv)
00373 {
00374   // apply the decorator concept when setting the
00375   // scene data for all the sceneviews
00376   if(_scene_decorator.valid())
00377     sv->setSceneData(_scene_decorator.get());
00378 
00379   else if(_scene_data.valid())
00380     sv->setSceneData(_scene_data.get());
00381 
00382   else
00383     sv->setSceneData( 0 );
00384 
00385   // take care of frame stamps
00386   if(_frame_stamp.valid())
00387     sv->setFrameStamp(_frame_stamp.get());
00388 
00389   // take care of global stateset
00390   if(_global_stateset.valid())
00391     sv->setGlobalStateSet(_global_stateset.get());
00392 
00393   // take care of background color
00394 #ifdef _OSG096_
00395   sv->setBackgroundColor(_background_color);
00396 #else
00397   sv->setClearColor( _background_color );
00398 #endif
00399 
00400   sv->setLightingMode(osgUtil::SceneView::NO_SCENEVIEW_LIGHT);
00401   sv->setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR);
00402 }
00403 
00404 void Application::setViewportByDrawManager(osg::Viewport* vp, vrj::GlDrawManager* mgr)
00405 {
00406   float vpX,vpY,vpW,vpH;
00407   unsigned int winX,winY,winW,winH;
00408 
00409   mgr->currentUserData()->getViewport()->getOriginAndSize(vpX,vpY,vpW,vpH);
00410   mgr->currentUserData()->getGlWindow()->getOriginSize(winX,winY,winW,winH);
00411 
00412   unsigned int x,y,w,h;
00413   x = unsigned(vpX*float(winW));
00414   y = unsigned(vpY*float(winH));
00415   w = unsigned(vpW*float(winW));
00416   h = unsigned(vpH*float(winH));
00417 
00418   vp->setViewport(x,y,w,h);
00419 }
00420 
00421 void Application::update()
00422 {
00423   if(_scene_data.valid() && _update_visitor.valid())
00424     {
00425       _update_visitor->reset();
00426       _update_visitor->setFrameStamp(_frame_stamp.get());
00427 
00428       if(_frame_stamp.valid())
00429         {
00430           _update_visitor->setTraversalNumber(_frame_stamp->getFrameNumber());
00431         }
00432 
00433       getSceneData()->accept(*_update_visitor.get());
00434       getSceneData()->getBound();
00435     }
00436 }
00437 
00438 void Application::quit()
00439 {
00440   vrj::Kernel::instance()->stop();
00441 }
00442 
00443 
00445 //
00446 // Set the normalization state.
00447 //
00449 
00450 void Application::normalize ( bool on )
00451 {
00452   const osg::StateSet *temp = this->getGlobalStateSet();
00453   if ( !temp )
00454     throw std::runtime_error ( "Error 4271807142, failed to get global state set." );
00455 
00456   osg::ref_ptr<osg::StateSet> ss ( new osg::StateSet ( *temp ) );
00457   if ( !ss.valid() )
00458     throw std::runtime_error ( "Error 2255713473, failed to copy global state set." );
00459 
00460   ss->setMode ( GL_NORMALIZE, ( ( on ) ? osg::StateAttribute::ON : osg::StateAttribute::OFF ) );
00461   this->setGlobalStateSet ( ss.get() );
00462 }
00463 
00464 
00466 //
00467 // Return the normalization state.
00468 //
00470 
00471 bool Application::normalize() const
00472 {
00473   const osg::StateSet *ss = this->getGlobalStateSet();
00474   return ( ( ss && osg::StateAttribute::ON == ss->getMode ( GL_NORMALIZE ) ) ? true : false );
00475 }

Generated on Thu Mar 31 12:10:27 2005 for osgVRJ by  doxygen 1.4.2