Nice, cheers J-S,

K.

2009/9/2 Jean-Sébastien Guay <[email protected]>:
> Hi Kim,
>
>> This looks really useful, I'm surprised I missed the original post.
>>
>> Anyone know where I can get the attachment from?
>
> It's at the bottom of the post here:
>
> http://thread.gmane.org/gmane.comp.graphics.openscenegraph.cvs/6026
>
> or I've attached it too, for your convenience. :-)
>
> J-S
> --
> ______________________________________________________
> Jean-Sebastien Guay    [email protected]
>                               http://www.cm-labs.com/
>                        http://whitestar02.webhop.org/
>
> /* OpenSceneGraph example, osgposter.
> *
> *  Permission is hereby granted, free of charge, to any person obtaining a
> copy
> *  of this software and associated documentation files (the "Software"), to
> deal
> *  in the Software without restriction, including without limitation the
> rights
> *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> *  copies of the Software, and to permit persons to whom the Software is
> *  furnished to do so, subject to the following conditions:
> *
> *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> OR
> *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> THE
> *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM,
> *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> *  THE SOFTWARE.
> */
>
> #include <osg/ArgumentParser>
> #include <osg/Camera>
> #include <osg/Texture2D>
> #include <osgDB/ReadFile>
> #include <osgDB/WriteFile>
> #include <osgViewer/Viewer>
> #include <iostream>
> #include <sstream>
>
> class PrintPosterHandler : public osgGA::GUIEventHandler
> {
> public:
>    typedef std::pair<unsigned int, unsigned int> TilePosition;
>    typedef std::map< TilePosition, osg::ref_ptr<osg::Image> > TileImages;
>
>    PrintPosterHandler()
>    :   _isRunning(false), _isFinished(false),
>        _outputTiles(false), _outputTileExt("bmp"),
>        _currentRow(0), _currentColumn(0),
>        _cameraIndex(0), _cameraRoot(0), _finalPoster(0)
>    {}
>
>    inline void setOutputTiles( bool b ) { _outputTiles = b; }
>    inline bool getOutputTiles() const { return _outputTiles; }
>
>    inline void setOutputTileExtension( const std::string& ext ) {
> _outputTileExt = ext; }
>    inline const std::string& getOutputTileExtension() const { return
> _outputTileExt; }
>
>    inline void setTileSize( int w, int h ) { _tileSize.set(w, h); }
>    inline const osg::Vec2& getTileSize() const { return _tileSize; }
>
>    inline void setPosterSize( int w, int h ) { _posterSize.set(w, h); }
>    inline const osg::Vec2& getPosterSize() const { return _posterSize; }
>
>    inline void setCameraRoot( osg::Group* root ) { _cameraRoot = root; }
>    inline const osg::Group* getCameraRoot() const { return
> _cameraRoot.get(); }
>
>    inline void setFinalPoster( osg::Image* image ) { _finalPoster = image; }
>    inline const osg::Image* getFinalPoster() const { return
> _finalPoster.get(); }
>
>    bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&
> aa )
>    {
>        osgViewer::View* view = dynamic_cast<osgViewer::View*>( &aa );
>        if ( !view ) return false;
>
>        switch( ea.getEventType() )
>        {
>            case osgGA::GUIEventAdapter::FRAME:
>            {
>                if ( view->getDatabasePager() )
>                {
>                    // Wait until all paged LOD are processed
>                    if ( view->getDatabasePager()->getRequestsInProgress() )
>                        break;
>                }
>
>                if ( _isFinished )
>                {
>                    const osg::FrameStamp* fs = view->getFrameStamp();
>                    if ( (fs->getFrameNumber()%2)==0 )
>                    {
>                        // Record images and unref them to free memory
>                        recordImages();
>                    }
>                }
>
>                if ( _isRunning )
>                {
>                    // Every "copy-to-image" process seems to be finished in
> 2 frames.
>                    // So record them and dispatch cameras to next tiles.
>                    const osg::FrameStamp* fs = view->getFrameStamp();
>                    if ( (fs->getFrameNumber()%2)==0 )
>                    {
>                        // Record images and unref them to free memory
>                        recordImages();
>
>                        osg::Camera* camera = 0;
>                        while ( (camera=getAvailableCamera())!=NULL )
>                        {
>                            std::cout << "Binding sub-camera " << _currentRow
> << "_" << _currentColumn
>                                      << " to image..." << std::endl;
>                            bindCameraToImage( camera, _currentRow,
> _currentColumn );
>                            if ( _currentColumn<_tileColumns-1 )
>                                _currentColumn++;
>                            else
>                            {
>                                if ( _currentRow<_tileRows-1 )
>                                {
>                                    _currentRow++;
>                                    _currentColumn = 0;
>                                }
>                                else
>                                {
>                                    _isRunning = false;
>                                    _isFinished = true;
>                                    std::cout << "Sub-cameras dispatching
> finished." << std::endl;
>                                    break;
>                                }
>                            }
>                        }
>                        _cameraIndex = _cameraRoot->getNumChildren();
>                    }
>                }
>                break;
>            }
>
>            case osgGA::GUIEventAdapter::KEYDOWN:
>            {
>                if ( ea.getKey()=='p' || ea.getKey()=='P' )
>                {
>                    if ( !_isRunning && _cameraRoot.valid() )
>                    {
>                        _tileRows = (int)(_posterSize.y() / _tileSize.y());
>                        _tileColumns = (int)(_posterSize.x() /
> _tileSize.x());
>                        _currentRow = 0;
>                        _currentColumn = 0;
>                        _cameraIndex = _cameraRoot->getNumChildren();
>                        _currentViewMatrix =
> view->getCamera()->getViewMatrix();
>                        _currentProjectionMatrix =
> view->getCamera()->getProjectionMatrix();
>                        _images.clear();
>
>                        _isRunning = true;
>                        _isFinished = false;
>                    }
>                    return true;
>                }
>                break;
>            }
>
>            default:
>                break;
>        }
>
>        return false;
>    }
>
> protected:
>    osg::Camera* getAvailableCamera()
>    {
>        // Find an available camera for rendering current tile image.
>        if ( !_cameraIndex || !_cameraRoot.valid() ) return NULL;
>        return dynamic_cast<osg::Camera*>(
> _cameraRoot->getChild(--_cameraIndex) );
>    }
>
>    void bindCameraToImage( osg::Camera* camera, int row, int col )
>    {
>        std::stringstream stream;
>        stream << "image_" << row << "_" << col;
>
>        osg::ref_ptr<osg::Image> image = new osg::Image;
>        image->setName( stream.str() );
>        image->allocateImage( (int)_tileSize.x(), (int)_tileSize.y(), 1,
> GL_RGBA, GL_UNSIGNED_BYTE );
>        _images[TilePosition(row,col)] = image.get();
>
>        // Calculate projection matrix offset of each tile
>        osg::Matrix offsetMatrix =
>            osg::Matrix::scale(_tileColumns, _tileRows, 1.0) *
>            osg::Matrix::translate(_tileColumns-1-2*col, _tileRows-1-2*row,
> 0.0);
>        camera->setViewMatrix( _currentViewMatrix );
>        camera->setProjectionMatrix( _currentProjectionMatrix * offsetMatrix
> );
>
>        // Reattach cameras and new allocated images
>        camera->setRenderingCache( NULL );  // FIXME: Uses for reattaching
> camera with image, maybe inefficient?
>        camera->detach( osg::Camera::COLOR_BUFFER );
>        camera->attach( osg::Camera::COLOR_BUFFER, image.get(), 0, 0 );
>    }
>
>    void recordImages()
>    {
>        for ( TileImages::iterator itr=_images.begin(); itr!=_images.end();
> ++itr )
>        {
>            osg::Image* image = (itr->second).get();
>            if ( _finalPoster.valid() )
>            {
>                // FIXME: A stupid way to combine tile images to final
> result. Any better ideas?
>                unsigned int row = itr->first.first, col = itr->first.second;
>                for ( int s=0; s<image->s(); ++s )
>                {
>                    for ( int t=0; t<image->t(); ++t )
>                    {
>                        unsigned char* src = image->data(s, t);
>                        unsigned char* target = _finalPoster->data(s +
> col*(int)_tileSize.x(), t + row*(int)_tileSize.y());
>                        for ( int u=0; u<4; ++u )
>                            *(target + u) = *(src++);
>                    }
>                }
>            }
>
>            if ( _outputTiles )
>                osgDB::writeImageFile( *image,
> image->getName()+"."+_outputTileExt );
>        }
>        _images.clear();
>    }
>
>    bool _isRunning;
>    bool _isFinished;
>
>    bool _outputTiles;
>    std::string _outputTileExt;
>
>    osg::Vec2 _tileSize;
>    osg::Vec2 _posterSize;
>
>    int _tileRows;
>    int _tileColumns;
>
>    int _currentRow;
>    int _currentColumn;
>    unsigned int _cameraIndex;
>
>    osg::Matrixd _currentViewMatrix;
>    osg::Matrixd _currentProjectionMatrix;
>
>    osg::ref_ptr<osg::Group> _cameraRoot;
>    osg::ref_ptr<osg::Image> _finalPoster;
>    TileImages _images;
> };
>
> int main( int argc, char** argv )
> {
>    osg::ArgumentParser arguments( &argc, argv );
>    arguments.getApplicationUsage()->setDescription(
>        arguments.getApplicationName() + " is the example which demonstrates
> how to render high-resolution images (posters).");
>    arguments.getApplicationUsage()->setCommandLineUsage(
> arguments.getApplicationName()+" [options] scene_file" );
>    arguments.getApplicationUsage()->addCommandLineOption( "-h or --help",
> "Display this information." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--color <r> <g>
> <b>", "The background color." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--cameras <num>",
> "Number of cameras for rendering tiles." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--ext <ext>",
> "The output tiles' extension." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--poster
> <filename>", "The output high-resolution poster file." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--tilesize <w>
> <h>", "Size of each image tile." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--finalsize <w>
> <h>", "Size of the high-resolution poster." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--output-poster",
> "Output the final poster file." );
>    arguments.getApplicationUsage()->addCommandLineOption(
> "--no-output-poster", "Don't output the final poster file." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--output-tiles",
> "Output all tile files." );
>    arguments.getApplicationUsage()->addCommandLineOption(
> "--no-output-tiles", "Don't output all tile files." );
>    arguments.getApplicationUsage()->addCommandLineOption( "--use-fb", "Use
> Frame Buffer for rendering tiles (Recommended).");
>    arguments.getApplicationUsage()->addCommandLineOption( "--use-fbo", "Use
> Frame Buffer Object for rendering tiles.");
>    arguments.getApplicationUsage()->addCommandLineOption(
> "--use-pbuffer","Use Pixel Buffer for rendering tiles.");
>    arguments.getApplicationUsage()->addCommandLineOption(
> "--use-pbuffer-rtt","Use Pixel Buffer RTT for rendering tiles.");
>
>    if ( arguments.read("-h") || arguments.read("--help") )
>    {
>        arguments.getApplicationUsage()->write( std::cout );
>        return 1;
>    }
>
>    bool outputPoster = true, outputTiles = false;
>    int tileWidth = 640, tileHeight = 480;
>    int posterWidth = 6400, posterHeight = 4800;
>    int numCameras = 4;
>    std::string posterName = "poster.bmp", extName = "bmp";
>    osg::Vec4 bgColor(0.2f, 0.2f, 0.6f, 1.0f);
>    osg::Camera::RenderTargetImplementation renderImplementation =
> osg::Camera::FRAME_BUFFER;
>
>    while ( arguments.read("--color", bgColor.r(), bgColor.g(), bgColor.b())
> ) {}
>    while ( arguments.read("--cameras", numCameras) ) {}
>    while ( arguments.read("--tilesize", tileWidth, tileHeight) ) {}
>    while ( arguments.read("--finalsize", posterWidth, posterHeight) ) {}
>    while ( arguments.read("--output-poster") ) { outputPoster = true; }
>    while ( arguments.read("--no-output-poster") ) { outputPoster = false; }
>    while ( arguments.read("--output-tiles") ) { outputTiles = true; }
>    while ( arguments.read("--no-output-tiles") ) { outputTiles = false; }
>    while ( arguments.read("--poster", posterName) ) {}
>    while ( arguments.read("--ext", extName) ) {}
>    while ( arguments.read("--use-fbo")) { renderImplementation =
> osg::Camera::FRAME_BUFFER_OBJECT; }
>    while ( arguments.read("--use-pbuffer")) { renderImplementation =
> osg::Camera::PIXEL_BUFFER; }
>    while ( arguments.read("--use-pbuffer-rtt")) { renderImplementation =
> osg::Camera::PIXEL_BUFFER_RTT; }
>    while ( arguments.read("--use-fb")) { renderImplementation =
> osg::Camera::FRAME_BUFFER; }
>
>    osg::Node* scene = osgDB::readNodeFiles( arguments );
>    if ( !scene ) scene = osgDB::readNodeFile( "cow.osg" );
>    if ( !scene )
>    {
>        std::cout << arguments.getApplicationName() <<": No data loaded" <<
> std::endl;
>        return 1;
>    }
>
>    osg::ref_ptr<osg::Group> root = new osg::Group;
>    root->addChild( scene );
>
>    // Create cameras for rendering tiles offscreen. FrameBuffer is
> recommended because it requires less memory.
>    osg::ref_ptr<osg::Group> cameraRoot = new osg::Group;
>    for ( int i=0; i<numCameras; ++i )
>    {
>        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
>        camera->setClearColor( bgColor );
>        camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
>        camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
>        camera->setRenderOrder( osg::Camera::PRE_RENDER );
>        camera->setRenderTargetImplementation( renderImplementation );
>        camera->setViewport( 0, 0, tileWidth, tileHeight );
>
>        camera->addChild( scene );
>        cameraRoot->addChild( camera.get() );
>    }
>    root->addChild( cameraRoot.get() );
>
>    // Set the printing handler
>    PrintPosterHandler* handler = new PrintPosterHandler;
>    handler->setTileSize( tileWidth, tileHeight );
>    handler->setPosterSize( posterWidth, posterHeight );
>    handler->setCameraRoot( cameraRoot.get() );
>
>    osg::ref_ptr<osg::Image> posterImage = 0;
>    if ( outputPoster )
>    {
>        posterImage = new osg::Image;
>        posterImage->allocateImage( posterWidth, posterHeight, 1, GL_RGBA,
> GL_UNSIGNED_BYTE );
>        handler->setFinalPoster( posterImage.get() );
>    }
>
>    // Start the viewer
>    osgViewer::Viewer viewer;
>    viewer.setSceneData( root.get() );
>    viewer.addEventHandler( handler );
>    viewer.setUpViewInWindow( 100, 100, tileWidth, tileHeight );
>    viewer.run();
>
>    if ( outputPoster )
>    {
>        std::cout << "Writing final result to file..." << std::endl;
>        osgDB::writeImageFile( *posterImage, posterName );
>    }
>    return 0;
> }
>
> SET(TARGET_SRC osgposter.cpp )
> SETUP_EXAMPLE(osgposter)
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to