Skip to content

Instantly share code, notes, and snippets.

@hkusoft
Created March 23, 2021 00:50
Show Gist options
  • Save hkusoft/fa78c4a11b6eb25e38bcb6519eeccba3 to your computer and use it in GitHub Desktop.
Save hkusoft/fa78c4a11b6eb25e38bcb6519eeccba3 to your computer and use it in GitHub Desktop.
OsgSnapshotHelper by David Kou
#include "stdafx.h"
#include "OsgSnapshotHelper.h"
OsgSnapshotHelper::OsgSnapshotHelper(osgViewer::Viewer* pView)
{
pViewer = pView;
// Install custom renderer
osg::ref_ptr<CustomRenderer> customRenderer = new CustomRenderer(pViewer->getCamera());
pViewer->getCamera()->setRenderer(customRenderer.get());
////Important
//pViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
// Do cull and draw to render the scene correctly
customRenderer->setCullOnly(false);
}
void OsgSnapshotHelper::Capture(std::string fileName)
{
if (pViewer)
{
// Add the WindowCaptureCallback now that we have full resolution
GLenum buffer = pViewer->getCamera()->getGraphicsContext()->getTraits()->doubleBuffer ? GL_BACK : GL_FRONT;
pViewer->getCamera()->setFinalDrawCallback(new WindowCaptureCallback(buffer, fileName));
pViewer->renderingTraversals();
pViewer->getCamera()->setFinalDrawCallback(NULL);
}
}
OsgSnapshotHelper::~OsgSnapshotHelper()
{
}
#pragma once
#include <osg/ArgumentParser>
#include <osg/CoordinateSystemNode>
#include <osg/Matrix>
#include <osg/NodeVisitor>
#include <osgUtil/IntersectionVisitor>
#include <osgUtil/GLObjectsVisitor>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/DriveManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/TrackballManipulator>
#include <osgTerrain/Terrain>
#include <osgTerrain/GeometryTechnique>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Renderer>
#include <iostream>
#include <sstream>
class OsgSnapshotHelper
{
/** Capture the frame buffer and write image to disk*/
class WindowCaptureCallback : public osg::Camera::DrawCallback
{
public:
WindowCaptureCallback(GLenum readBuffer, const std::string& name) :
_readBuffer(readBuffer),
_fileName(name)
{
_image = new osg::Image;
}
virtual void operator () (osg::RenderInfo& renderInfo) const
{
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
glReadBuffer(_readBuffer);
#else
osg::notify(osg::NOTICE) << "Error: GLES unable to do glReadBuffer" << std::endl;
#endif
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
if (gc->getTraits())
{
GLenum pixelFormat;
if (gc->getTraits()->alpha)
pixelFormat = GL_RGBA;
else
pixelFormat = GL_RGB;
#if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
if (pixelFormat == GL_RGB)
{
GLint value = 0;
#ifndef GL_IMPLEMENTATION_COLOR_READ_FORMAT
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
#endif
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &value);
if (value != GL_RGB ||
value != GL_UNSIGNED_BYTE)
{
pixelFormat = GL_RGBA;//always supported
}
}
#endif
int width = gc->getTraits()->width;
int height = gc->getTraits()->height;
std::cout << "Capture: size=" << width << "x" << height << ", format=" << (pixelFormat == GL_RGBA ? "GL_RGBA" : "GL_RGB") << std::endl;
_image->readPixels(0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE);
}
if (!_fileName.empty())
{
std::cout << "Writing to: " << _fileName << std::endl;
osgDB::writeImageFile(*_image, _fileName);
}
}
protected:
GLenum _readBuffer;
std::string _fileName;
osg::ref_ptr<osg::Image> _image;
mutable OpenThreads::Mutex _mutex;
};
/** Do Culling only while loading PagedLODs*/
class CustomRenderer : public osgViewer::Renderer
{
public:
CustomRenderer(osg::Camera* camera)
: osgViewer::Renderer(camera),
_cullOnly(true)
{
}
/** Set flag to omit drawing in renderingTraversals */
void setCullOnly(bool on) { _cullOnly = on; }
virtual void operator () (osg::GraphicsContext* /*context*/)
{
if (_graphicsThreadDoesCull)
{
if (_cullOnly)
cull();
else
cull_draw();
}
}
virtual void cull()
{
osgUtil::SceneView* sceneView = _sceneView[0].get();
if (!sceneView || _done) return;
updateSceneView(sceneView);
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
sceneView->inheritCullSettings(*(sceneView->getCamera()));
sceneView->cull();
}
bool _cullOnly;
};
public:
OsgSnapshotHelper(osgViewer::Viewer* pView);
void Capture(std::string fileName);
~OsgSnapshotHelper();
protected:
osgViewer::Viewer* pViewer;
};
@hkusoft
Copy link
Author

hkusoft commented Mar 23, 2021

Please STAR ⭐ this gist if you find it helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment