Files
OpenSceneGraph/examples/osgframerenderer/gscframerenderer.cpp
2012-11-19 11:25:52 +00:00

383 lines
12 KiB
C++

#include <osgDB/ReadFile>
#include <osgDB/FileNameUtils>
#include <osgDB/WriteFile>
#include <osgViewer/Viewer>
#include <osg/AnimationPath>
#include "UpdateProperty.h"
#include "CameraPathProperty.h"
#include "EventProperty.h"
#include "CaptureSettings.h"
#include <osgGA/StateSetManipulator>
struct ScreenShot : public osg::Camera::DrawCallback
{
ScreenShot() {}
virtual void operator () (osg::RenderInfo& renderInfo) const
{
if (!_frameCapture)
{
OSG_NOTICE<<"No FrameCamera assigned"<<std::endl;
return;
}
unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
CameraNumMap::const_iterator itr = _cameraNumMap.find(renderInfo.getCurrentCamera());
std::string outputFileName = (itr!=_cameraNumMap.end()) ?
_frameCapture->getOutputFileName(itr->second, frameNumber) :
_frameCapture->getOutputFileName(frameNumber);
OSG_NOTICE<<"outputFileName="<<outputFileName<<std::endl;
osg::Camera* camera = renderInfo.getCurrentCamera();
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
if (viewport)
{
OSG_NOTICE<<"Doing read of ="<<viewport->x()<<", "<<viewport->y()<<", "<<viewport->width()<<", "<<viewport->height()<<std::endl;
glReadBuffer(camera->getDrawBuffer());
osg::ref_ptr<osg::Image> image = new osg::Image;
image->readPixels(viewport->x(),viewport->y(),viewport->width(),viewport->height(),
GL_RGB, GL_UNSIGNED_BYTE, 1);
osgDB::writeImageFile(*image, outputFileName);
}
}
typedef std::map<const osg::Camera*, unsigned int> CameraNumMap;
osg::ref_ptr<gsc::CaptureSettings> _frameCapture;
CameraNumMap _cameraNumMap;
};
int main( int argc, char **argv )
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of 3D textures.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
osgViewer::Viewer viewer;
typedef std::list< osg::ref_ptr<gsc::CaptureSettings> > CaptureSettingsList;
CaptureSettingsList frameCaptureList;
osg::ref_ptr<gsc::CaptureSettings> fc = new gsc::CaptureSettings;
double duration = 0.0;
double fps = 0.0f;
unsigned int nframes = 0;
std::string filename;
if (arguments.read("--cs",filename))
{
osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(filename);
gsc::CaptureSettings* input_cs = dynamic_cast<gsc::CaptureSettings*>(object.get());
if (input_cs) fc = input_cs;
else OSG_NOTICE<<"Unable to read CaptureSettings from file: "<<filename<<std::endl;
}
if (arguments.read("-i",filename)) fc->setInputFileName(filename);
if (arguments.read("-o",filename)) fc->setOutputFileName(filename);
if (arguments.read("-p",filename))
{
osg::ref_ptr<gsc::CameraPathProperty> cpp = new gsc::CameraPathProperty;
cpp->setAnimationPathFileName(filename);
double startTime = 0, endTime = 1.0f;
if (cpp->getTimeRange(startTime, endTime))
{
OSG_NOTICE<<"Camera path time range "<<startTime<<", "<<endTime<<std::endl;
if (startTime!=0.0)
{
cpp->resetTimeRange(0.0, endTime-startTime);
if (cpp->getTimeRange(startTime, endTime))
{
OSG_NOTICE<<" new time range "<<startTime<<", "<<endTime<<std::endl;
}
else
{
OSG_NOTICE<<" failed to set new time range "<<startTime<<", "<<endTime<<std::endl;
}
}
duration = endTime;
}
else
{
OSG_NOTICE<<"Camera path time range "<<startTime<<", "<<endTime<<std::endl;
}
fc->addUpdateProperty(cpp.get());
}
if (arguments.read("--offscreen")) fc->setOffscreen(true);
unsigned int width = 1024;
if (arguments.read("-w",width)) fc->setWidth(width);
unsigned int height = 512;
if (arguments.read("-h",height)) fc->setHeight(height);
unsigned int samples = 0;
if (arguments.read("--samples",samples)) fc->setSamples(samples);
unsigned int sampleBuffers = 0;
if (arguments.read("--sampleBuffers",sampleBuffers)) fc->setSampleBuffers(sampleBuffers);
unsigned int ms = 0;
if (arguments.read("--ms",ms))
{
fc->setSamples(ms);
fc->setSampleBuffers(1);
}
if (arguments.read("--stereo"))
{
OSG_NOTICE<<"Enabling stereo"<<std::endl;
fc->setStereo(true);
}
if (arguments.read("-f",fps)) fc->setFrameRate(fps);
if (arguments.read("-n",nframes)) fc->setNumberOfFrames(nframes);
std::string key;
double time;
while(arguments.read("--key-down",time, key) && key.size()>=1)
{
OSG_NOTICE<<"keydown "<<key<<", "<<time<<std::endl;
osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter;
event->setTime(time);
event->setEventType(osgGA::GUIEventAdapter::KEYDOWN);
event->setKey(key[0]);
fc->addUpdateProperty(new gsc::EventProperty(event.get()));
}
while(arguments.read("--key-up",time, key) && key.size()>=1)
{
OSG_NOTICE<<"keyup "<<key<<", "<<time<<std::endl;
osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter;
event->setTime(time);
event->setEventType(osgGA::GUIEventAdapter::KEYUP);
event->setKey(key[0]);
fc->addUpdateProperty(new gsc::EventProperty(event.get()));
}
double mouse_x, mouse_y;
while(arguments.read("--mouse-move",time, mouse_x, mouse_y))
{
OSG_NOTICE<<"mouse move "<<time<<", "<<mouse_x<<", "<<mouse_y<<std::endl;
osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter;
event->setTime(time);
event->setEventType(osgGA::GUIEventAdapter::MOVE);
event->setX(mouse_x);
event->setY(mouse_y);
fc->addUpdateProperty(new gsc::EventProperty(event.get()));
}
while(arguments.read("--mouse-drag",time, mouse_x, mouse_y))
{
OSG_NOTICE<<"mouse drag "<<time<<", "<<mouse_x<<", "<<mouse_y<<std::endl;
osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter;
event->setTime(time);
event->setEventType(osgGA::GUIEventAdapter::DRAG);
event->setX(mouse_x);
event->setY(mouse_y);
fc->addUpdateProperty(new gsc::EventProperty(event.get()));
}
if (duration!=0.0)
{
if (fps!=0.0) nframes = static_cast<unsigned int>(ceil(duration*fps));
else if (nframes!=0) fps = duration/static_cast<double>(nframes);
else
{
fps = 60.0;
nframes = static_cast<unsigned int>(ceil(duration/fps));
}
}
else // duration == 0.0
{
if (fps==0.0) fps=60.0;
if (nframes==0) nframes=1;
duration = static_cast<double>(nframes)/fps;
}
fc->setNumberOfFrames(nframes);
fc->setFrameRate(fps);
OSG_NOTICE<<"Duration="<<duration<<", FPS="<<fps<<", Number of Frames="<<nframes<<std::endl;
if (arguments.read("--output-cs",filename))
{
osgDB::writeObjectFile(*fc, filename);
return 1;
}
if (fc.valid())
{
frameCaptureList.push_back(fc);
}
if (frameCaptureList.empty())
{
OSG_NOTICE<<"No settings provided"<<std::endl;
return 1;
}
// setup viewer
{
osg::ref_ptr<osg::DisplaySettings> ds = new osg::DisplaySettings;
ds->setStereoMode(osg::DisplaySettings::HORIZONTAL_SPLIT);
ds->setStereo(fc->getStereo());
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(ds.get());
traits->readDISPLAY();
if (traits->displayNum<0) traits->displayNum = 0;
traits->x = 0;
traits->y = 0;
traits->width = fc->getWidth();
traits->height = fc->getHeight();
traits->samples = fc->getSamples();
traits->sampleBuffers = fc->getSampleBuffers();
traits->windowDecoration = !(fc->getOffscreen());
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->pbuffer = fc->getOffscreen();
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if (!gc)
{
OSG_NOTICE<<"Failed to created requested graphics context"<<std::endl;
return 1;
}
viewer.getCamera()->setGraphicsContext(gc.get());
viewer.getCamera()->setDisplaySettings(ds.get());
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
if (gw)
{
OSG_INFO<<"GraphicsWindow has been created successfully."<<std::endl;
gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, fc->getWidth(), fc->getHeight());
}
else
{
OSG_NOTICE<<"PixelBuffer has been created succseffully "<<traits->width<<", "<<traits->height<<std::endl;
}
double fovy, aspectRatio, zNear, zFar;
viewer.getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
double newAspectRatio = double(traits->width) / double(traits->height);
double aspectRatioChange = newAspectRatio / aspectRatio;
if (aspectRatioChange != 1.0)
{
viewer.getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
}
viewer.getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
viewer.getCamera()->setDrawBuffer(buffer);
viewer.getCamera()->setReadBuffer(buffer);
}
viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
viewer.realize();
// set up screen shot
osg::ref_ptr<ScreenShot> screenShot = new ScreenShot;
{
osgViewer::Viewer::Cameras cameras;
viewer.getCameras(cameras);
if (cameras.size()>1)
{
unsigned int cameraNum = 0;
for(osgViewer::Viewer::Cameras::iterator itr = cameras.begin();
itr != cameras.end();
++itr, ++cameraNum)
{
osg::Camera* camera = *itr;
camera->setFinalDrawCallback(screenShot.get());
screenShot->_cameraNumMap[camera] = cameraNum;
}
}
else if (cameras.size()==1)
{
osg::Camera* camera = cameras.front();
camera->setFinalDrawCallback(screenShot.get());
}
else
{
OSG_NOTICE<<"No usable Cameras created."<<std::endl;
return 1;
}
}
for(CaptureSettingsList::iterator itr = frameCaptureList.begin();
itr != frameCaptureList.end();
++itr)
{
gsc::CaptureSettings* fc = itr->get();
screenShot->_frameCapture = fc;
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(fc->getInputFileName());
if (!model) break;
viewer.setSceneData(model.get());
double simulationTime = 0.0;
for(unsigned int i=0; i<fc->getNumberOfFrames(); ++i)
{
OSG_NOTICE<<"fc.getOutputFileName("<<i<<")="<<fc->getOutputFileName(i)<<std::endl;
viewer.advance(simulationTime);
gsc::CaptureSettings::Properties& pl = fc->getProperties();
for(gsc::CaptureSettings::Properties::iterator plitr = pl.begin();
plitr != pl.end();
++plitr)
{
(*plitr)->update(&viewer);
}
viewer.eventTraversal();
viewer.updateTraversal();
viewer.renderingTraversals();
// advance simulationTime and number of frames rendered
simulationTime += 1.0/fc->getFrameRate();
}
}
osg::ref_ptr<osg::Object> object = new osgGA::StateSetManipulator;
osg::ref_ptr<osgGA::StateSetManipulator> ss = dynamic_cast<osgGA::StateSetManipulator*>(object.get());
return 0;
}