diff --git a/include/osgProducer/OsgSceneHandler b/include/osgProducer/OsgSceneHandler index 3b7126f43..dedb402bd 100644 --- a/include/osgProducer/OsgSceneHandler +++ b/include/osgProducer/OsgSceneHandler @@ -105,6 +105,7 @@ class OSGPRODUCER_EXPORT OsgSceneHandler : public Producer::Camera::SceneHandler osg::ref_ptr _drawCallback; osg::Timer_t _frameStartTick; + osg::Timer_t _previousFrameStartTick; }; } diff --git a/src/osgProducer/OsgCameraGroup.cpp b/src/osgProducer/OsgCameraGroup.cpp index 9995c8dbd..3bfd044df 100644 --- a/src/osgProducer/OsgCameraGroup.cpp +++ b/src/osgProducer/OsgCameraGroup.cpp @@ -573,18 +573,41 @@ osg::Matrixd OsgCameraGroup::getViewMatrix() const 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. - double time_since_start = _timer.delta_s(_start_tick,_timer.tick()); _frameStamp->setFrameNumber(_frameNumber++); - _frameStamp->setReferenceTime(time_since_start); + + 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(); diff --git a/src/osgProducer/OsgSceneHandler.cpp b/src/osgProducer/OsgSceneHandler.cpp index a4f8d3223..d2609feea 100644 --- a/src/osgProducer/OsgSceneHandler.cpp +++ b/src/osgProducer/OsgSceneHandler.cpp @@ -23,6 +23,8 @@ using namespace osgProducer; OsgSceneHandler::OsgSceneHandler( osg::DisplaySettings *ds) : _sceneView(new osgUtil::SceneView(ds)) { + _frameStartTick = 0; + _previousFrameStartTick = 0; } void OsgSceneHandler::init() @@ -41,6 +43,7 @@ void OsgSceneHandler::init() void OsgSceneHandler::clearImplementation(Producer::Camera& /*camera*/) { + _previousFrameStartTick = _frameStartTick; _frameStartTick = osg::Timer::instance()->tick(); osgDB::DatabasePager* dp = osgDB::Registry::instance()->getDatabasePager(); @@ -81,20 +84,41 @@ void OsgSceneHandler::drawImplementation(Producer::Camera &) osgDB::DatabasePager* dp = osgDB::Registry::instance()->getDatabasePager(); if (dp) { + double timeForPreviousFrame = osg::Timer::instance()->delta_s(_previousFrameStartTick, _frameStartTick); double timeForCullAndDraw = osg::Timer::instance()->delta_s(_frameStartTick, osg::Timer::instance()->tick()); - double targetMaxFrameTime = 0.010; // 10ms. + double minimumTargetMaxFrameTime = 0.010; // 10ms. + double targetMaxFrameTime = osg::minimum(timeForPreviousFrame, minimumTargetMaxFrameTime); - double availableTime = targetMaxFrameTime-timeForCullAndDraw; - // availableTime = 0.1; // 2.5 ms + double maximumAvailableTime = 0.0025; // 2.5ms. + double drawCostFactor = 2.0; // must be greater than 1 to account for the extra cost of emptying the OpenGL fifo. + double frameFactor = 0.9; // must be less than 1, to compensate for extra time spent in update and swap buffers etc. + double timeLeftTillEndOfFrame = targetMaxFrameTime*frameFactor - timeForCullAndDraw*drawCostFactor; + double availableTime = timeLeftTillEndOfFrame / drawCostFactor; // account for the fifo when download texture objects. + + static unsigned int _numFramesThatNoTimeAvailable = 0; + static unsigned int _maxNumFramesThatNoTimeAvailable = 10; + + if (_numFramesThatNoTimeAvailable>_maxNumFramesThatNoTimeAvailable) + { + availableTime = 0.0025; // 2.5ms. + } if (availableTime>0.0) { + _numFramesThatNoTimeAvailable = 0; + + // osg::notify(osg::NOTICE)<<"Time available = "<compileGLObjects(*(getSceneView()->getState()),availableTime); // flush deleted GL objects. getSceneView()->flushDeletedGLObjects(availableTime); } + else + { + ++_numFramesThatNoTimeAvailable; + } dp->signalEndFrame(); }