736 lines
22 KiB
C++
736 lines
22 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
#include <osg/ApplicationUsage>
|
|
#include <osg/Timer>
|
|
#include <osg/Notify>
|
|
#include <osg/Texture2D>
|
|
#include <osg/TextureRectangle>
|
|
#include <osg/ImageStream>
|
|
|
|
#include <osgUtil/DisplayRequirementsVisitor>
|
|
#include <osgDB/FileUtils>
|
|
|
|
#include <osgProducer/OsgCameraGroup>
|
|
|
|
using namespace Producer;
|
|
using namespace osgProducer;
|
|
|
|
OsgCameraGroup::RealizeCallback::~RealizeCallback()
|
|
{
|
|
}
|
|
|
|
class RenderSurfaceRealizeCallback : public Producer::RenderSurface::Callback
|
|
{
|
|
public:
|
|
|
|
RenderSurfaceRealizeCallback(OsgCameraGroup* cameraGroup,OsgSceneHandler* sceneHandler):
|
|
_cameraGroup(cameraGroup),
|
|
_sceneHandler(sceneHandler) {}
|
|
|
|
virtual void operator()( const Producer::RenderSurface & rs)
|
|
{
|
|
|
|
osg::Timer timer;
|
|
osg::Timer_t start_t = timer.tick();
|
|
|
|
if (_cameraGroup->getRealizeCallback())
|
|
{
|
|
(*(_cameraGroup->getRealizeCallback()))(*_cameraGroup,*_sceneHandler,rs);
|
|
}
|
|
else if (_sceneHandler) _sceneHandler->init();
|
|
|
|
osg::Timer_t end_t = timer.tick();
|
|
double time = timer.delta_m(start_t,end_t);
|
|
osg::notify(osg::INFO) << "Time to init = "<<time<<std::endl;
|
|
|
|
}
|
|
|
|
OsgCameraGroup* _cameraGroup;
|
|
OsgSceneHandler* _sceneHandler;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::string findCameraConfigFile(const std::string& configFile)
|
|
{
|
|
std::string foundFile = osgDB::findDataFile(configFile);
|
|
if (foundFile.empty()) return "";
|
|
else return foundFile;
|
|
}
|
|
|
|
std::string extractCameraConfigFile(osg::ArgumentParser& arguments)
|
|
{
|
|
// report the usage options.
|
|
if (arguments.getApplicationUsage())
|
|
{
|
|
arguments.getApplicationUsage()->addCommandLineOption("-c <filename>","Specify camera config file");
|
|
}
|
|
|
|
std::string filename;
|
|
if (arguments.read("-c",filename)) return findCameraConfigFile(filename);
|
|
|
|
char *ptr;
|
|
if( (ptr = getenv( "PRODUCER_CAMERA_CONFIG_FILE" )) )
|
|
{
|
|
osg::notify(osg::DEBUG_INFO) << "PRODUCER_CAMERA_CONFIG_FILE("<<ptr<<")"<<std::endl;
|
|
return findCameraConfigFile(ptr);
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
static osg::ApplicationUsageProxy OsgCameraGroup_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"PRODUCER_CAMERA_CONFIG_FILE <filename>","specify the default producer camera config to use when opening osgProducer based applications.");
|
|
|
|
|
|
OsgCameraGroup::OsgCameraGroup() : Producer::CameraGroup()
|
|
{
|
|
_init();
|
|
}
|
|
|
|
OsgCameraGroup::OsgCameraGroup(Producer::CameraConfig *cfg):
|
|
Producer::CameraGroup(cfg)
|
|
{
|
|
_init();
|
|
}
|
|
|
|
OsgCameraGroup::OsgCameraGroup(const std::string& configFile):
|
|
Producer::CameraGroup(findCameraConfigFile(configFile))
|
|
{
|
|
_init();
|
|
}
|
|
|
|
OsgCameraGroup::OsgCameraGroup(osg::ArgumentParser& arguments):
|
|
Producer::CameraGroup(extractCameraConfigFile(arguments))
|
|
{
|
|
_init();
|
|
_applicationUsage = arguments.getApplicationUsage();
|
|
|
|
for( unsigned int i = 0; i < _cfg->getNumberOfCameras(); i++ )
|
|
{
|
|
Producer::Camera *cam = _cfg->getCamera(i);
|
|
Producer::RenderSurface *rs = cam->getRenderSurface();
|
|
if (rs->getWindowName()== Producer::RenderSurface::defaultWindowName )
|
|
{
|
|
rs->setWindowName(arguments.getApplicationName());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class QuitImageStreamVisitor : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
|
|
QuitImageStreamVisitor():
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
|
|
|
|
|
/** Simply traverse using standard NodeVisitor traverse method.*/
|
|
virtual void apply(osg::Node& node)
|
|
{
|
|
if (node.getStateSet())
|
|
apply(*(node.getStateSet()));
|
|
|
|
traverse(node);
|
|
}
|
|
|
|
virtual void apply(osg::Geode& node)
|
|
{
|
|
if (node.getStateSet())
|
|
apply(*(node.getStateSet()));
|
|
|
|
for(unsigned int i=0;i<node.getNumDrawables();++i)
|
|
{
|
|
osg::Drawable* drawable = node.getDrawable(i);
|
|
if (drawable && drawable->getStateSet())
|
|
apply(*(drawable->getStateSet()));
|
|
}
|
|
}
|
|
|
|
void apply(osg::StateSet& stateset)
|
|
{
|
|
for(unsigned int i=0;i<stateset.getTextureAttributeList().size();++i)
|
|
{
|
|
osg::StateAttribute* texture = stateset.getTextureAttribute(i,osg::StateAttribute::TEXTURE);
|
|
if (texture)
|
|
{
|
|
osg::TextureRectangle* textureRect = dynamic_cast<osg::TextureRectangle*>(texture);
|
|
if (textureRect)
|
|
{
|
|
osg::ImageStream* imageStream = dynamic_cast<osg::ImageStream*>(textureRect->getImage());
|
|
if (imageStream)
|
|
{
|
|
imageStream->quit();
|
|
}
|
|
}
|
|
|
|
osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(texture);
|
|
if (texture2D)
|
|
{
|
|
osg::ImageStream* imageStream = dynamic_cast<osg::ImageStream*>(texture2D->getImage());
|
|
if (imageStream)
|
|
{
|
|
imageStream->quit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
OsgCameraGroup::~OsgCameraGroup()
|
|
{
|
|
// kill the DatabasePager and associated thread if one exists.
|
|
osgDB::Registry::instance()->setDatabasePager(0);
|
|
|
|
osg::Node* node = getTopMostSceneData();
|
|
if (node)
|
|
{
|
|
// kill any ImageStream threads
|
|
QuitImageStreamVisitor qisv;
|
|
node->accept(qisv);
|
|
}
|
|
}
|
|
|
|
|
|
static osg::ApplicationUsageProxy OsgCameraGroup_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_CAMERA_THREADING <value>","Set the threading model using by osgProducer::Viewer/OsgCameraGroup based apps. <value> can be SingleThreaded or ThreadPerCamera");
|
|
static osg::ApplicationUsageProxy OsgCameraGroup_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SHARE_GRAPHICS_CONTEXTS <value>","Set the threading model using by osgProducer::Viewer/OsgCameraGroup based apps. <value> can be ON or OFF");
|
|
|
|
void OsgCameraGroup::_init()
|
|
{
|
|
const char* str = getenv("OSG_CAMERA_THREADING");
|
|
if (str)
|
|
{
|
|
if (strcmp(str,"SingleThreaded")==0) _thread_model = SingleThreaded;
|
|
else if (strcmp(str,"ThreadPerCamera")==0) _thread_model = ThreadPerCamera;
|
|
}
|
|
|
|
str = getenv("OSG_SHARE_GRAPHICS_CONTEXTS");
|
|
if (str)
|
|
{
|
|
if (strcmp(str,"ON")==0) Producer::RenderSurface::shareAllGLContexts(true);
|
|
else if (strcmp(str,"OFF")==0) Producer::RenderSurface::shareAllGLContexts(false);
|
|
}
|
|
|
|
|
|
_scene_data = NULL;
|
|
_global_stateset = NULL;
|
|
_clear_color.set( 0.2f, 0.2f, 0.4f, 1.0f );
|
|
|
|
_fusionDistanceMode = osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE;
|
|
_fusionDistanceValue = 1.0f;
|
|
|
|
_realizeSceneViewOptions = osgUtil::SceneView::STANDARD_SETTINGS;
|
|
|
|
_initialized = false;
|
|
|
|
// set up the time and frame counter.
|
|
_frameNumber = 0;
|
|
_start_tick = _timer.tick();
|
|
|
|
if (!_frameStamp) _frameStamp = new osg::FrameStamp;
|
|
|
|
_applicationUsage = osg::ApplicationUsage::instance();
|
|
|
|
}
|
|
|
|
void OsgCameraGroup::setSceneData( osg::Node *scene )
|
|
{
|
|
if (_scene_data==scene) return;
|
|
|
|
if (_scene_decorator.valid() && _scene_data.valid())
|
|
{
|
|
_scene_decorator->removeChild(_scene_data.get());
|
|
}
|
|
|
|
_scene_data = scene;
|
|
|
|
if (_scene_decorator.valid() && _scene_data.valid())
|
|
{
|
|
_scene_decorator->addChild(scene);
|
|
}
|
|
|
|
updatedSceneData();
|
|
}
|
|
|
|
void OsgCameraGroup::setSceneDecorator( osg::Group* decorator)
|
|
{
|
|
if (_scene_decorator==decorator) return;
|
|
|
|
_scene_decorator = decorator;
|
|
|
|
if (_scene_data.valid() && decorator)
|
|
{
|
|
decorator->addChild(_scene_data.get());
|
|
}
|
|
updatedSceneData();
|
|
}
|
|
|
|
|
|
void OsgCameraGroup::updatedSceneData()
|
|
{
|
|
setUpSceneViewsWithData();
|
|
}
|
|
|
|
void OsgCameraGroup::setUpSceneViewsWithData()
|
|
{
|
|
for(SceneHandlerList::iterator p = _shvec.begin(); p != _shvec.end(); p++ )
|
|
{
|
|
osgUtil::SceneView* sv = (*p)->getSceneView();
|
|
|
|
if (_scene_decorator.valid())
|
|
{
|
|
sv->setSceneData( _scene_decorator.get() );
|
|
}
|
|
else if (_scene_data.valid())
|
|
{
|
|
sv->setSceneData( _scene_data.get() );
|
|
}
|
|
else
|
|
{
|
|
sv->setSceneData( 0 );
|
|
}
|
|
|
|
sv->setFrameStamp( _frameStamp.get() );
|
|
sv->setGlobalStateSet( _global_stateset.get() );
|
|
sv->setFusionDistance( _fusionDistanceMode, _fusionDistanceValue );
|
|
}
|
|
}
|
|
|
|
|
|
void OsgCameraGroup::setFrameStamp( osg::FrameStamp* fs )
|
|
{
|
|
_frameStamp = fs;
|
|
setUpSceneViewsWithData();
|
|
}
|
|
|
|
|
|
void OsgCameraGroup::setGlobalStateSet( osg::StateSet *sset )
|
|
{
|
|
_global_stateset = sset;
|
|
setUpSceneViewsWithData();
|
|
}
|
|
|
|
void OsgCameraGroup::setClearColor( const osg::Vec4& clearColor )
|
|
{
|
|
_clear_color = clearColor;
|
|
for(unsigned int i=0;i<getNumberOfCameras();++i)
|
|
{
|
|
Producer::Camera *cam = _cfg->getCamera(i);
|
|
cam->setClearColor(_clear_color[0],_clear_color[1],_clear_color[2],_clear_color[3]);
|
|
}
|
|
}
|
|
|
|
const osg::Vec4& OsgCameraGroup::getClearColor() const
|
|
{
|
|
return _clear_color;
|
|
}
|
|
|
|
void OsgCameraGroup::setLODScale( float scale )
|
|
{
|
|
getCullSettings().setLODScale(scale);
|
|
setUpSceneViewsWithData();
|
|
}
|
|
|
|
float OsgCameraGroup::getLODScale() const
|
|
{
|
|
return getCullSettings().getLODScale();
|
|
}
|
|
|
|
void OsgCameraGroup::setFusionDistance( osgUtil::SceneView::FusionDistanceMode mode,float value)
|
|
{
|
|
// need to set a local variable?
|
|
_fusionDistanceMode = mode;
|
|
_fusionDistanceValue = value;
|
|
setUpSceneViewsWithData();
|
|
}
|
|
|
|
void OsgCameraGroup::advance()
|
|
{
|
|
if( !_initialized ) return;
|
|
CameraGroup::advance();
|
|
}
|
|
|
|
bool OsgCameraGroup::realize( ThreadingModel thread_model )
|
|
{
|
|
if( _realized ) return _realized;
|
|
_thread_model = thread_model;
|
|
return realize();
|
|
}
|
|
|
|
|
|
// small visitor to check for the existance of particle systems,
|
|
// which currently arn't thread safe, so we would need to disable
|
|
// multithreading of cull and draw.
|
|
class SearchForSpecialNodes : public osg::NodeVisitor
|
|
{
|
|
public:
|
|
SearchForSpecialNodes():
|
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
|
_foundParticles(false),
|
|
_foundPagedLOD(false)
|
|
{
|
|
}
|
|
|
|
virtual void apply(osg::Node& node)
|
|
{
|
|
if (strcmp(node.libraryName(),"osgParticle")==0) _foundParticles = true;
|
|
|
|
if (!_foundParticles ||
|
|
!_foundPagedLOD) traverse(node);
|
|
}
|
|
|
|
virtual void apply(osg::PagedLOD& node)
|
|
{
|
|
_foundPagedLOD = true;
|
|
apply((osg::Node&)node);
|
|
}
|
|
|
|
bool _foundParticles;
|
|
bool _foundPagedLOD;
|
|
};
|
|
|
|
bool OsgCameraGroup::realize()
|
|
{
|
|
if( _initialized ) return _realized;
|
|
|
|
if (!_ds) _ds = osg::DisplaySettings::instance();
|
|
|
|
_shvec.clear();
|
|
|
|
osg::Node* node = getTopMostSceneData();
|
|
if (node)
|
|
{
|
|
// traverse the scene graphs gathering the requirements of the OpenGL buffers.
|
|
osgUtil::DisplayRequirementsVisitor drv;
|
|
drv.setDisplaySettings(_ds.get());
|
|
node->accept(drv);
|
|
}
|
|
|
|
unsigned int numMultiSamples = 0;
|
|
|
|
#ifdef __sgi
|
|
// switch on anti-aliasing by default, just in case we have an Onyx :-)
|
|
numMultiSamples = 4;
|
|
#endif
|
|
|
|
// set up each render stage to clear the appropriate buffers.
|
|
GLbitfield clear_mask=0;
|
|
if (_ds->getRGB()) clear_mask |= GL_COLOR_BUFFER_BIT;
|
|
if (_ds->getDepthBuffer()) clear_mask |= GL_DEPTH_BUFFER_BIT;
|
|
if (_ds->getStencilBuffer()) clear_mask |= GL_STENCIL_BUFFER_BIT;
|
|
|
|
// make sure any camera's which share the same render surface also share the same osg::State.
|
|
// use a std::map to keep track of what render surfaces are associated with what state.
|
|
typedef std::map<Producer::RenderSurface*,osg::State*> RenderSurfaceStateMap;
|
|
RenderSurfaceStateMap _renderSurfaceStateMap;
|
|
|
|
bool needToCreatedNewContextID = true;
|
|
unsigned int contextID = 0;
|
|
|
|
for(unsigned int i = 0; i < _cfg->getNumberOfCameras(); i++ )
|
|
{
|
|
Producer::Camera *cam = _cfg->getCamera(i);
|
|
Producer::RenderSurface* rs = cam->getRenderSurface();
|
|
|
|
cam->setClearColor(_clear_color[0],_clear_color[1],_clear_color[2],_clear_color[3]);
|
|
|
|
// get or create the scene handler.
|
|
osgProducer::OsgSceneHandler *sh;
|
|
sh = dynamic_cast<osgProducer::OsgSceneHandler*>(cam->getSceneHandler());
|
|
if(sh == NULL)
|
|
sh = new osgProducer::OsgSceneHandler(_ds.get());
|
|
|
|
osgUtil::SceneView* sv = sh->getSceneView();
|
|
sv->setDefaults(_realizeSceneViewOptions);
|
|
|
|
if (_renderSurfaceStateMap.count(rs)==0)
|
|
{
|
|
_renderSurfaceStateMap[rs] = sv->getState();
|
|
|
|
if (needToCreatedNewContextID)
|
|
{
|
|
// create a unique contextID for this graphics context.
|
|
contextID = osg::GraphicsContext::createNewContextID();
|
|
|
|
// if we are sharing our graphics context then when needn't create any more.
|
|
needToCreatedNewContextID = !Producer::RenderSurface::allGLContextsAreShared();
|
|
}
|
|
else
|
|
{
|
|
osg::GraphicsContext::incrementContextIDUsageCount(contextID);
|
|
}
|
|
|
|
sv->getState()->setContextID(contextID);
|
|
}
|
|
else
|
|
{
|
|
sv->setState(_renderSurfaceStateMap[rs]);
|
|
}
|
|
|
|
_shvec.push_back( sh );
|
|
cam->setSceneHandler( sh );
|
|
|
|
// set up the clear mask.
|
|
osgUtil::RenderStage *stage = sv->getRenderStage();
|
|
if (stage) stage->setClearMask(clear_mask);
|
|
|
|
// set the realize callback.
|
|
rs->setRealizeCallback( new RenderSurfaceRealizeCallback(this, sh));
|
|
|
|
// set up the visual chooser.
|
|
if (_ds.valid() || numMultiSamples!=0)
|
|
{
|
|
|
|
Producer::VisualChooser* rs_vc = rs->getVisualChooser();
|
|
if (!rs_vc)
|
|
{
|
|
rs_vc = new Producer::VisualChooser;
|
|
rs_vc->setSimpleConfiguration();
|
|
rs->setVisualChooser(rs_vc);
|
|
}
|
|
|
|
unsigned int numStencilBits = 0;
|
|
if (_ds->getStereo())
|
|
{
|
|
switch(_ds->getStereoMode())
|
|
{
|
|
case(osg::DisplaySettings::QUAD_BUFFER):
|
|
rs_vc->useStereo();
|
|
break;
|
|
case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
|
|
case(osg::DisplaySettings::VERTICAL_INTERLACE):
|
|
numStencilBits = 8;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// set up stencil buffer if required.
|
|
numStencilBits = osg::maximum(numStencilBits,_ds->getMinimumNumStencilBits());
|
|
if (numStencilBits > 0)
|
|
{
|
|
rs_vc->setStencilSize(numStencilBits);
|
|
}
|
|
|
|
if (_ds->getAlphaBuffer()) rs_vc->setAlphaSize(_ds->getMinimumNumAlphaBits());
|
|
|
|
rs_vc->setDepthSize(24);
|
|
|
|
if (numMultiSamples)
|
|
{
|
|
#if defined( GLX_SAMPLES_SGIS )
|
|
rs_vc->addExtendedAttribute( GLX_SAMPLES_SGIS, numMultiSamples);
|
|
#endif
|
|
#if defined( GLX_SAMPLES_BUFFER_SGIS )
|
|
rs_vc->addExtendedAttribute( GLX_SAMPLES_BUFFER_SGIS, 1);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
// now set up GraphicsContext wrappers for each of the render surfaces
|
|
// to all core OSG classes to keep track of the graphics context.
|
|
for(RenderSurfaceStateMap::iterator ritr = _renderSurfaceStateMap.begin();
|
|
ritr != _renderSurfaceStateMap.end();
|
|
++ritr)
|
|
{
|
|
Producer::RenderSurface* rs = ritr->first;
|
|
osg::State* state = ritr->second;
|
|
GraphicsContextImplementation* gc = new GraphicsContextImplementation(rs);
|
|
gc->setState(state);
|
|
state->setGraphicsContext(gc);
|
|
_gcList.push_back(gc);
|
|
}
|
|
|
|
if( _global_stateset == NULL && _shvec.size() > 0 )
|
|
{
|
|
SceneHandlerList::iterator p = _shvec.begin();
|
|
_global_stateset = (*p)->getSceneView()->getGlobalStateSet();
|
|
}
|
|
|
|
setUpSceneViewsWithData();
|
|
|
|
// if we are multi-threaded check to see if particle exists in the scene
|
|
// if so we need to disable multi-threading of cameras.
|
|
if (_thread_model == Producer::CameraGroup::ThreadPerCamera)
|
|
{
|
|
if (getTopMostSceneData())
|
|
{
|
|
SearchForSpecialNodes sfsn;
|
|
getTopMostSceneData()->accept(sfsn);
|
|
if (sfsn._foundParticles)
|
|
{
|
|
osg::notify(osg::INFO)<<"Warning: disabling multi-threading of cull and draw"<<std::endl;
|
|
osg::notify(osg::INFO)<<" to avoid threading problems in osgParticle."<<std::endl;
|
|
_thread_model = Producer::CameraGroup::SingleThreaded;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// if we are still multi-thread check to make sure that no render surfaces
|
|
// are shared and don't use shared contexts, if they do we need to
|
|
// disable multi-threading of cameras.
|
|
if (_thread_model == Producer::CameraGroup::ThreadPerCamera)
|
|
{
|
|
std::set<RenderSurface*> renderSurfaceSet;
|
|
for( unsigned int i = 0; i < _cfg->getNumberOfCameras(); i++ )
|
|
{
|
|
Producer::Camera *cam = _cfg->getCamera(i);
|
|
renderSurfaceSet.insert(cam->getRenderSurface());
|
|
}
|
|
if (renderSurfaceSet.size()!=_cfg->getNumberOfCameras())
|
|
{
|
|
// camera's must be sharing a RenderSurface, so we need to ensure that we're
|
|
// running single threaded, to avoid OpenGL threading issues.
|
|
osg::notify(osg::INFO)<<"Warning: disabling multi-threading of cull and draw to avoid"<<std::endl;
|
|
osg::notify(osg::INFO)<<" threading problems when camera's share a RenderSurface."<<std::endl;
|
|
_thread_model = Producer::CameraGroup::SingleThreaded;
|
|
}
|
|
else if (renderSurfaceSet.size()>1 && RenderSurface::allGLContextsAreShared())
|
|
{
|
|
// we have multiple RenderSurface, but with share contexts, which is dangerous for multi-threaded usage,
|
|
// so need to disable multi-threading to prevent problems.
|
|
osg::notify(osg::INFO)<<"Warning: disabling multi-threading of cull and draw to avoid"<<std::endl;
|
|
osg::notify(osg::INFO)<<" threading problems when sharing graphics contexts within RenderSurface."<<std::endl;
|
|
_thread_model = Producer::CameraGroup::SingleThreaded;
|
|
}
|
|
|
|
}
|
|
|
|
if (_thread_model==Producer::CameraGroup::SingleThreaded)
|
|
{
|
|
osg::notify(osg::INFO)<<"OsgCameraGroup::realize() _thread_model==Producer::CameraGroup::SingleThreaded"<<std::endl;
|
|
}
|
|
else
|
|
{
|
|
osg::notify(osg::INFO)<<"OsgCameraGroup::realize() _thread_model==Producer::CameraGroup::ThreadPerCamera"<<std::endl;
|
|
}
|
|
|
|
_initialized = CameraGroup::realize();
|
|
|
|
return _initialized;
|
|
}
|
|
|
|
osg::Node* OsgCameraGroup::getTopMostSceneData()
|
|
{
|
|
if (_scene_decorator.valid())
|
|
return _scene_decorator.get();
|
|
else
|
|
return _scene_data.get();
|
|
}
|
|
|
|
const osg::Node* OsgCameraGroup::getTopMostSceneData() const
|
|
{
|
|
if (_scene_decorator.valid())
|
|
return _scene_decorator.get();
|
|
else
|
|
return _scene_data.get();
|
|
}
|
|
|
|
void OsgCameraGroup::setView(const osg::Matrixd& matrix)
|
|
{
|
|
Producer::Matrix pm(matrix.ptr());
|
|
|
|
setViewByMatrix(pm);
|
|
}
|
|
|
|
osg::Matrixd OsgCameraGroup::getViewMatrix() const
|
|
{
|
|
osg::Matrixd matrix;
|
|
if (_cfg.valid() && _cfg->getNumberOfCameras()>=1)
|
|
{
|
|
const Producer::Camera *cam = _cfg->getCamera(0);
|
|
matrix.set(cam->getViewMatrix());
|
|
}
|
|
return matrix;
|
|
}
|
|
|
|
static osg::Timer_t _last_frame_tick = 0;
|
|
static osg::Timer_t _previous_previous_frame_tick = 0;
|
|
static osg::Timer_t _previous_frame_tick = 0;
|
|
static bool _useStartOfUpdateForFrameTime = true;
|
|
|
|
void OsgCameraGroup::sync()
|
|
{
|
|
CameraGroup::sync();
|
|
|
|
// set the frame stamp for the new frame.
|
|
_frameStamp->setFrameNumber(_frameNumber++);
|
|
|
|
if (_useStartOfUpdateForFrameTime)
|
|
{
|
|
double time_since_start = _timer.delta_s(_start_tick,_timer.tick());
|
|
_frameStamp->setReferenceTime(time_since_start);
|
|
}
|
|
else
|
|
{
|
|
osg::Timer_t endOfNewFrameTick = _last_frame_tick + (_last_frame_tick-_previous_previous_frame_tick);
|
|
double estimatedSwapTimeForFrame = _timer.delta_s(_start_tick,endOfNewFrameTick);
|
|
|
|
_frameStamp->setReferenceTime(estimatedSwapTimeForFrame);
|
|
}
|
|
}
|
|
|
|
void OsgCameraGroup::frame()
|
|
{
|
|
if (!_useStartOfUpdateForFrameTime)
|
|
{
|
|
_previous_previous_frame_tick = _previous_frame_tick;
|
|
_previous_frame_tick = _last_frame_tick;
|
|
_last_frame_tick = _timer.tick();
|
|
}
|
|
|
|
osg::Node* node = getTopMostSceneData();
|
|
if (node) node->getBound();
|
|
|
|
|
|
// pass on the cull settings to the scene views to keep
|
|
// the settings in sync.
|
|
for(SceneHandlerList::iterator itr = _shvec.begin();
|
|
itr != _shvec.end();
|
|
++itr)
|
|
{
|
|
(*itr)->getSceneView()->inheritCullSettings(_cullSettings);
|
|
}
|
|
|
|
|
|
CameraGroup::frame();
|
|
}
|
|
|
|
void OsgCameraGroup::cleanup_frame()
|
|
{
|
|
// first relase all GL objects and switch on the flush of deleted objects
|
|
// in the next frame.
|
|
for(SceneHandlerList::iterator itr = _shvec.begin();
|
|
itr != _shvec.end();
|
|
++itr)
|
|
{
|
|
(*itr)->getSceneView()->releaseAllGLObjects();
|
|
(*itr)->setFlushOfAllDeletedGLObjectsOnNextFrame(true);
|
|
}
|
|
|
|
// make sure that the registry all flushes all its texture objects.
|
|
osgDB::Registry::instance()->releaseGLObjects();
|
|
|
|
// then run the frame to do the actuall OpenGL clean up.
|
|
frame();
|
|
}
|
|
|
|
|