Moved rendering support into GraphisContext, osgViewer::Viewer/View, and

added frame stamp updating and update traversal to osgViewer::Scene/Viewer.

Updated osgcamera example to use new Viewer API calls instead of using local
rendering calls.
This commit is contained in:
Robert Osfield 2006-12-21 16:56:20 +00:00
parent 8f9d2eeb46
commit 4fc9af7ea0
10 changed files with 311 additions and 96 deletions

View File

@ -71,67 +71,22 @@ int main( int argc, char **argv )
std::cout << argv[0] <<": No data loaded." << std::endl;
return 1;
}
// initialize the view to look at the center of the scene graph
const osg::BoundingSphere& bs = loadedModel->getBound();
osg::Matrix viewMatrix;
viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setSceneData(loadedModel.get());
viewer->setCameraManipulator(new osgGA::TrackballManipulator());
viewer->setUpViewAcrossAllScreens();
viewer->realize();
osgViewer::Viewer viewer;
viewer->getCamera()->setClearColor(osg::Vec4f(0.6f,0.6f,0.8f,1.0f));
osg::ref_ptr<osg::FrameStamp> frameStamp = new osg::FrameStamp;
viewer.setSceneData(loadedModel.get());
unsigned int frameNum = 0;
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
viewer.getCamera()->setClearColor(osg::Vec4f(0.6f,0.6f,0.8f,1.0f));
osgUtil::UpdateVisitor updateVisitor;
updateVisitor.setFrameStamp(frameStamp.get());
setUpFrameStamp(viewer->getCamera(), frameStamp.get(), loadedModel.get());
for(unsigned i=0; i<viewer->getNumSlaves(); ++i)
viewer.setUpViewAcrossAllScreens();
viewer.realize();
while(!viewer.done())
{
osg::View::Slave& slave = viewer->getSlave(i);
setUpFrameStamp(slave._camera.get(), frameStamp.get(), loadedModel.get());
viewer.frame();
}
// record the timer tick at the start of rendering.
osg::Timer_t start_tick = osg::Timer::instance()->tick();
osg::Timer_t previous_tick = start_tick;
while(true)
{
osg::Timer_t current_tick = osg::Timer::instance()->tick();
frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,current_tick));
frameStamp->setFrameNumber(frameNum++);
//std::cout<<"Frame rate "<<1.0/osg::Timer::instance()->delta_s(previous_tick,current_tick)<<std::endl;
previous_tick = current_tick;
// do the update traversal.
loadedModel->accept(updateVisitor);
viewer->frameAdvance();
viewer->frameEventTraversal();
viewer->frameUpdateTraversal();
// viewer->getCamera()->setViewMatrix(viewMatrix);
if (viewer->getCamera() && viewer->getCamera()->getGraphicsContext()) renderCamera(viewer->getCamera());
for(unsigned i=0; i<viewer->getNumSlaves(); ++i)
{
osg::View::Slave& slave = viewer->getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext()) renderCamera(slave._camera.get());
}
}
}

View File

@ -136,6 +136,52 @@ class OSG_EXPORT GraphicsContext : public Referenced
/** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/
static void decrementContextIDUsageCount(unsigned int contextID);
public:
/** Base class for implementing graphics operations.*/
struct OSG_EXPORT Operation : virtual public Referenced
{
Operation(const std::string& name, bool keep):
_name(name),
_keep(keep) {}
/** Set the human readable name of the operation.*/
void setName(const std::string& name) { _name = name; }
/** Get the human readable name of the operation.*/
const std::string& getName() const { return _name; }
/** Set whether the operation should be kept once its been applied.*/
void setKeep(bool keep) { _keep = keep; }
/** Get whether the operation should be kept once its been applied.*/
bool getKeep() const { return _keep; }
/** if this operation is a barrier then release it.*/
virtual void release() {}
/** Do the actual task of this operation.*/
virtual void operator () (GraphicsContext*) {}
std::string _name;
bool _keep;
};
/** Add operation to end of OperationQueue.*/
void add(Operation* operation);
/** Remove operation from OperationQueue.*/
void remove(Operation* operation);
/** Remove named operation from OperationQueue.*/
void remove(const std::string& name);
/** Remove all operations from OperationQueue.*/
void removeAllOperations();
/** Run the operations. */
void runOperations();
public:
/** Get the traits of the GraphicsContext.*/
@ -242,6 +288,12 @@ class OSG_EXPORT GraphicsContext : public Referenced
OpenThreads::Mutex _mutex;
OpenThreads::Thread* _threadOfLastMakeCurrent;
typedef std::list< ref_ptr<Operation> > OperationQueue;
OpenThreads::Mutex _operationsMutex;
osg::ref_ptr<osg::Block> _operationsBlock;
OperationQueue _operations;
osg::ref_ptr<Operation> _currentOperation;
ref_ptr<GraphicsThread> _graphicsThread;
};

View File

@ -81,7 +81,7 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread
public:
GraphicsThread();
/** Base class for implementing GraphicsThread operations.*/
/** Base class for implementing graphics operations.*/
struct OSG_EXPORT Operation : virtual public Referenced
{
Operation(const std::string& name, bool keep):
@ -109,7 +109,7 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread
std::string _name;
bool _keep;
};
/** Add operation to end of OperationQueue, this will be
* executed by the graphics thread once this operation gets to the head of the queue.*/
void add(Operation* operation, bool waitForCompletion=false);

View File

@ -32,27 +32,33 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View
/** set up windows and associated threads.*/
void realize();
void setDone(bool done) { _done = done; }
bool done() { return _done; }
/** Render a complete new frame.
* Calls frameAdvance(), frameEventTraversal(), frameUpateTraversal(), frameCullTraversal() and frameDrawTraversal().
* Note, no internal makeCurrent() is issued before, or swap buffers called after frame(), these operations are the responsibility of the calling code.*/
* Calls frameAdvance(), frameEventTraversal(), frameUpateTraversal(), frameRenderingTraversals(). */
virtual void frame();
virtual void frameAdvance();
virtual void frameEventTraversal();
virtual void frameUpdateTraversal();
virtual void frameCullTraversal();
virtual void frameDrawTraversal();
virtual void frameRenderingTraversals();
/** Release all OpenGL objects associated with this viewer's scenegraph. Note, does not deleted the actual OpenGL objects, it just releases them to the pending GL object delete lists which will need flushing once a valid graphics context is obtained.*/
virtual void releaseAllGLObjects();
/** Clean up all OpenGL objects associated with this viewer's scenegraph. Note, must only be called from the graphics context associated with this viewer.*/
/** Clean up all OpenGL objects associated with this viewer's scenegraph.*/
virtual void cleanup();
public:
void init();
bool _firstFrame;
bool _done;
protected:

View File

@ -115,6 +115,7 @@ void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID)
GraphicsContext::GraphicsContext():
_threadOfLastMakeCurrent(0)
{
_operationsBlock = new Block;
}
GraphicsContext::~GraphicsContext()
@ -248,3 +249,106 @@ void GraphicsContext::setGraphicsThread(GraphicsThread* gt)
}
}
}
void GraphicsContext::add(Operation* operation)
{
osg::notify(osg::INFO)<<"Doing add"<<std::endl;
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
// add the operation to the end of the list
_operations.push_back(operation);
_operationsBlock->set(true);
}
void GraphicsContext::remove(Operation* operation)
{
osg::notify(osg::INFO)<<"Doing remove operation"<<std::endl;
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
for(OperationQueue::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)==operation) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void GraphicsContext::remove(const std::string& name)
{
osg::notify(osg::INFO)<<"Doing remove named operation"<<std::endl;
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
// find the remove all operations with specificed name
for(OperationQueue::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)->getName()==name) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void GraphicsContext::removeAllOperations()
{
osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_operations.clear();
_operationsBlock->set(false);
}
void GraphicsContext::runOperations()
{
for(OperationQueue::iterator itr = _operations.begin();
itr != _operations.end();
)
{
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_currentOperation = *itr;
if (!_currentOperation->getKeep())
{
itr = _operations.erase(itr);
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
else
{
++itr;
}
}
if (_currentOperation.valid())
{
osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;
// call the graphics operation.
(*_currentOperation)(this);
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_currentOperation = 0;
}
}
}
}

View File

@ -223,6 +223,11 @@ void GraphicsThread::remove(const std::string& name)
if ((*itr)->getName()==name) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void GraphicsThread::removeAllOperations()
@ -231,6 +236,11 @@ void GraphicsThread::removeAllOperations()
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_operations.clear();
if (_operations.empty())
{
_operationsBlock->set(false);
}
}

View File

@ -232,7 +232,6 @@ void GraphicsWindowX11::init()
XWindowAttributes watt;
XGetWindowAttributes( _display, _parent, &watt );
// unsigned int parentWindowHeight = watt.height;
osg::notify(osg::NOTICE)<<"First watt.x = "<<watt.x<<" watt.y="<<watt.y<<std::endl;
XSetWindowAttributes swatt;
swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
@ -386,32 +385,29 @@ void GraphicsWindowX11::checkEvents()
switch( ev.type )
{
case Expose :
osg::notify(osg::NOTICE)<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
osg::notify(osg::INFO)<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
break;
case GravityNotify :
osg::notify(osg::NOTICE)<<"GravityNotify"<<std::endl;
osg::notify(osg::INFO)<<"GravityNotify"<<std::endl;
break;
case UnmapNotify :
osg::notify(osg::NOTICE)<<"UnmapNotify"<<std::endl;
osg::notify(osg::INFO)<<"UnmapNotify"<<std::endl;
break;
case ReparentNotify:
osg::notify(osg::NOTICE)<<"ReparentNotify"<<std::endl;
osg::notify(osg::INFO)<<"ReparentNotify"<<std::endl;
break;
case DestroyNotify :
osg::notify(osg::NOTICE)<<"DestroyNotify"<<std::endl;
osg::notify(osg::INFO)<<"DestroyNotify"<<std::endl;
_realized = false;
break;
case ConfigureNotify :
{
osg::notify(osg::NOTICE)<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
XWindowAttributes watt;
XGetWindowAttributes( _display, _window, &watt );
osg::notify(osg::NOTICE)<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
osg::notify(osg::INFO)<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
_traits->_x = ev.xconfigure.x;
_traits->_y = ev.xconfigure.y;
@ -476,7 +472,7 @@ void GraphicsWindowX11::checkEvents()
int dest_x_return, dest_y_return;
Window child_return;
Bool result = XTranslateCoordinates(_display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
XTranslateCoordinates(_display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
wx += (screenOrigin_x - dest_x_return);
wy += (screenOrigin_y - dest_y_return);

View File

@ -24,6 +24,7 @@ Scene::Scene():
_frameStamp->setReferenceTime(0);
_updateVisitor = new osgUtil::UpdateVisitor;
_updateVisitor->setFrameStamp(_frameStamp.get());
_eventQueue = new osgGA::EventQueue;
_eventQueue->setStartTick(_startTick);
@ -111,6 +112,10 @@ void Scene::frameEventTraversal()
void Scene::frameUpdateTraversal()
{
if (!getSceneData()) return;
getSceneData()->accept(*_updateVisitor);
if (_databasePager.valid())
{
// tell the DatabasePager the frame number of that the scene graph is being actively used to render a frame
@ -121,3 +126,6 @@ void Scene::frameUpdateTraversal()
}
}

View File

@ -99,7 +99,7 @@ void View::setUpViewAcrossAllScreens()
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
if (gw)
{
osg::notify(osg::NOTICE)<<" GraphicsWindow has been created successfully."<<std::endl;
osg::notify(osg::INFO)<<" GraphicsWindow has been created successfully."<<std::endl;
}
else
{
@ -140,7 +140,7 @@ void View::setUpViewAcrossAllScreens()
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
if (gw)
{
osg::notify(osg::NOTICE)<<" GraphicsWindow has been created successfully."<<gw<<std::endl;
osg::notify(osg::INFO)<<" GraphicsWindow has been created successfully."<<gw<<std::endl;
gw->getEventQueue()->setUseFixedMouseInputRange(true);
gw->getEventQueue()->getCurrentEventState()->setInputRange(inputRangeMinX, inputRangeMinY, inputRangeMinX+float(width),inputRangeMinY+float(height) );
@ -167,14 +167,37 @@ void View::setUpViewAcrossAllScreens()
assignSceneDataToCameras();
}
// Draw operation, that does a draw on the scene graph.
struct RenderingOperation : public osg::GraphicsContext::Operation
{
RenderingOperation(osgViewer::View* view, osg::Camera* camera, osg::FrameStamp* frameStamp):
osg::GraphicsContext::Operation("Render",true)
{
_sceneView = new osgUtil::SceneView;
_sceneView->setDefaults();
_sceneView->setCamera(camera);
_sceneView->setState(camera->getGraphicsContext()->getState());
_sceneView->setSceneData(view->getSceneData());
_sceneView->setFrameStamp(frameStamp);
}
virtual void operator () (osg::GraphicsContext*)
{
_sceneView->cull();
_sceneView->draw();
}
osg::ref_ptr<osgUtil::SceneView> _sceneView;
};
void View::setUpRenderingSupport()
{
osg::FrameStamp* frameStamp = _scene->getFrameStamp();
if (_camera.valid() && _camera->getGraphicsContext())
{
osg::ref_ptr<osgUtil::SceneView> sceneView = new osgUtil::SceneView;
sceneView->setState(_camera->getGraphicsContext()->getState());
sceneView->setCamera(_camera.get());
_camera->setRenderingCache(0, sceneView.get());
_camera->getGraphicsContext()->add(new RenderingOperation(this, _camera.get(), frameStamp));
}
for(unsigned i=0; i<getNumSlaves(); ++i)
@ -182,11 +205,7 @@ void View::setUpRenderingSupport()
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osg::ref_ptr<osgUtil::SceneView> sceneView = new osgUtil::SceneView;
sceneView->setDefaults();
sceneView->setState(slave._camera->getGraphicsContext()->getState());
sceneView->setCamera(slave._camera.get());
slave._camera->setRenderingCache(0, sceneView.get());
slave._camera->getGraphicsContext()->add(new RenderingOperation(this, slave._camera.get(), frameStamp));
}
}
}

View File

@ -30,7 +30,8 @@ public:
};
Viewer::Viewer():
_firstFrame(true)
_firstFrame(true),
_done(false)
{
}
@ -40,7 +41,7 @@ Viewer::~Viewer()
void Viewer::init()
{
osg::notify(osg::NOTICE)<<"Viewer::init()"<<std::endl;
osg::notify(osg::INFO)<<"Viewer::init()"<<std::endl;
osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();
initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);
@ -54,7 +55,7 @@ void Viewer::init()
void Viewer::realize()
{
osg::notify(osg::NOTICE)<<"Viewer::realize()"<<std::endl;
osg::notify(osg::INFO)<<"Viewer::realize()"<<std::endl;
if (_camera.valid() && _camera->getGraphicsContext())
{
@ -66,7 +67,7 @@ void Viewer::realize()
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osg::notify(osg::NOTICE)<<" slave realize()"<<std::endl;
osg::notify(osg::INFO)<<" slave realize()"<<std::endl;
slave._camera->getGraphicsContext()->realize();
}
}
@ -85,7 +86,7 @@ void Viewer::realize()
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osg::notify(osg::NOTICE)<<" slave realize()"<<std::endl;
osg::notify(osg::INFO)<<" slave realize()"<<std::endl;
slave._camera->getGraphicsContext()->realize();
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(slave._camera->getGraphicsContext());
gw->grabFocusIfPointerInWindow();
@ -98,20 +99,24 @@ void Viewer::realize()
void Viewer::frame()
{
if (_done) return;
if (_firstFrame)
{
init();
_firstFrame = false;
}
frameAdvance();
frameEventTraversal();
frameUpdateTraversal();
frameCullTraversal();
frameDrawTraversal();
frameRenderingTraversals();
}
void Viewer::frameAdvance()
{
if (_done) return;
// osg::notify(osg::NOTICE)<<"Viewer::frameAdvance()."<<std::endl;
_scene->frameAdvance();
@ -119,6 +124,8 @@ void Viewer::frameAdvance()
void Viewer::frameEventTraversal()
{
if (_done) return;
// osg::notify(osg::NOTICE)<<"Viewer::frameEventTraversal()."<<std::endl;
// need to copy events from the GraphicsWindow's into local EventQueue;
@ -201,6 +208,24 @@ void Viewer::frameEventTraversal()
}
#endif
// osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
for(osgGA::EventQueue::Events::iterator itr = events.begin();
itr != events.end();
++itr)
{
osgGA::GUIEventAdapter* event = itr->get();
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
if (event->getKey()=='q') _done = true;
break;
default:
break;
}
}
if (_done) return;
ActionAdapter aa;
for(osgGA::EventQueue::Events::iterator itr = events.begin();
@ -227,6 +252,10 @@ void Viewer::frameEventTraversal()
void Viewer::frameUpdateTraversal()
{
if (_done) return;
if (_scene.valid()) _scene->frameUpdateTraversal();
if (_cameraManipulator.valid())
{
_camera->setViewMatrix(_cameraManipulator->getInverseMatrix());
@ -235,14 +264,50 @@ void Viewer::frameUpdateTraversal()
updateSlaves();
}
void Viewer::frameCullTraversal()
void Viewer::frameRenderingTraversals()
{
osg::notify(osg::NOTICE)<<"Viewer::frameCullTraversal() not implemented yet."<<std::endl;
}
if (_done) return;
void Viewer::frameDrawTraversal()
{
osg::notify(osg::NOTICE)<<"Viewer::frameDrawTraversal() not implemented yet."<<std::endl;
typedef std::set<osg::GraphicsContext*> GraphicsContexts;
GraphicsContexts contexts;
if (_camera.valid() && _camera->getGraphicsContext())
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
if (gw)
{
contexts.insert(gw);
}
}
for(unsigned int i=0; i<getNumSlaves(); ++i)
{
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(slave._camera->getGraphicsContext());
if (gw)
{
contexts.insert(gw);
}
}
}
for(GraphicsContexts::iterator itr = contexts.begin();
itr != contexts.end();
++itr)
{
if (_done) return;
const_cast<osg::GraphicsContext*>(*itr)->makeCurrent();
const_cast<osg::GraphicsContext*>(*itr)->runOperations();
}
for(GraphicsContexts::iterator itr = contexts.begin();
itr != contexts.end();
++itr)
{
const_cast<osg::GraphicsContext*>(*itr)->swapBuffers();
}
}
void Viewer::releaseAllGLObjects()