Skip to content

Instantly share code, notes, and snippets.

@jasonbeverage
Created November 18, 2016 16:37
Show Gist options
  • Save jasonbeverage/07df40bdcf5dcb99f53345cce8e8ca72 to your computer and use it in GitHub Desktop.
Save jasonbeverage/07df40bdcf5dcb99f53345cce8e8ca72 to your computer and use it in GitHub Desktop.
Test of a TileRasterizerClass that reuses osg::Camera's as a service to render to textures
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>
#include <osg/Switch>
#include <osg/Types>
#include <osgText/Text>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osg/MatrixTransform>
#include <osgGA/Device>
#include <iostream>
#include <queue>
struct RotateUpdateCallback : public osg::NodeCallback
{
RotateUpdateCallback():
_angle(0.0)
{
}
void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osg::MatrixTransform* mt = static_cast<osg::MatrixTransform*>(node);
_angle+=0.1;
mt->setMatrix(osg::Matrixd::rotate(osg::Quat(_angle, osg::Vec3d(0,0,1))));
OSG_NOTICE << "Rotate " << _angle << std::endl;
traverse(node, nv);
}
double _angle;
};
typedef std::queue< osg::ref_ptr< osg::Texture2D > > TextureQueue;
class TileRasterizer : public osg::Camera
{
public:
TileRasterizer(TextureQueue* queue):
osg::Camera(),
_inProgress(false),
_textureQueue(queue)
{
// active an update traversal.
setNumChildrenRequiringUpdateTraversal(1);
setCullingActive(false);
// set up the RTT camera.
setClearColor(osg::Vec4(1,0,0,0.5));
setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
setReferenceFrame(ABSOLUTE_RF);
setViewport(new osg::Viewport(0, 0, 256, 256));
setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR );
setRenderOrder(PRE_RENDER);
setRenderTargetImplementation(FRAME_BUFFER_OBJECT);
setImplicitBufferAttachmentMask(0, 0);
setCullingMode(NO_CULLING);
osg::Node* cow = osgDB::readNodeFile("cow.osg");
if (!cow)
exit(-1);
osg::MatrixTransform* mt = new osg::MatrixTransform;
mt->addChild(cow);
mt->setUpdateCallback(new RotateUpdateCallback());
cow->setCullingActive(false);
addChild(mt);
double r = getBound().radius();
setProjectionMatrixAsOrtho(-r, r, -r, r, -1000, 1000);
setViewMatrixAsLookAt(osg::Vec3d(0, -2 * r, 0), osg::Vec3d(0, 0, 0), osg::Vec3d(0,0,1));
}
void traverse(osg::NodeVisitor& nv)
{
if (nv.getVisitorType() == nv.CULL_VISITOR)
{
//nop
}
else if (nv.getVisitorType() == nv.UPDATE_VISITOR)
{
// Detach if we have no work and the buffer attachment isn't empty.
//if (!_inProgress && !getBufferAttachmentMap().empty())
if (!getBufferAttachmentMap().empty())
{
detach(osg::Camera::COLOR_BUFFER);
dirtyAttachmentMap();
}
if (!_textureQueue->empty())
{
// Get the next texture
osg::ref_ptr< osg::Texture > texture = _textureQueue->front();
// Setup the viewport and attach to the new texture
setViewport(0, 0, texture->getTextureWidth(), texture->getTextureHeight());
attach(COLOR_BUFFER, texture.get(), 0u, 0u, false);
// Remove the texture from the queue.
_textureQueue->pop();
}
}
if (!getBufferAttachmentMap().empty())
{
osg::Camera::traverse(nv);
}
}
public:
TextureQueue* _textureQueue;
bool _inProgress;
};
TextureQueue textureQueue;
osg::Node* makeCell(int x, int y)
{
osg::Geometry* geometry = new osg::Geometry;
osg::Vec3Array* verts = new osg::Vec3Array;
verts->push_back(osg::Vec3(x, 0, y));
verts->push_back(osg::Vec3(x + 1.0, 0, y));
verts->push_back(osg::Vec3(x + 1.0, 0, y + 1.0));
verts->push_back(osg::Vec3(x, 0, y + 1.0));
geometry->setVertexArray(verts);
osg::Vec4ubArray* colors = new osg::Vec4ubArray;
colors->push_back(osg::Vec4ub(255,255,255,255));
geometry->setColorArray(colors, osg::Array::Binding::BIND_OVERALL);
osg::Vec2Array* texCoords = new osg::Vec2Array;
texCoords->push_back(osg::Vec2f(0.0f, 0.0f));
texCoords->push_back(osg::Vec2f(1.0f, 0.0f));
texCoords->push_back(osg::Vec2f(1.0f, 1.0f));
texCoords->push_back(osg::Vec2f(0.0f, 1.0f));
geometry->setTexCoordArray(0, texCoords);
osg::Texture2D *texture = new osg::Texture2D();
texture->setInternalFormat(GL_RGBA);
texture->setSourceFormat( GL_RGBA );
texture->setResizeNonPowerOfTwoHint( false );
texture->setTextureSize( 256, 256 );
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture::LINEAR);
texture->setSourceType( GL_UNSIGNED_BYTE );
std::stringstream buf;
buf << "texture " << x << "x" << y << std::endl;
texture->setName(buf.str());
//textureQueue.push( texture );
textureQueue.push( texture );
geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
geometry->setUseVertexBufferObjects(true);
geometry->setUseDisplayList(false);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, verts->size()));
osg::Geode* geode =new osg::Geode;
geode->addDrawable( geometry );
return geode;
}
int main(int argc, char** argv)
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
osgViewer::Viewer viewer(arguments);
// set up the camera manipulators.
{
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
keyswitchManipulator->addMatrixManipulator( '5', "Orbit", new osgGA::OrbitManipulator() );
keyswitchManipulator->addMatrixManipulator( '6', "FirstPerson", new osgGA::FirstPersonManipulator() );
keyswitchManipulator->addMatrixManipulator( '7', "Spherical", new osgGA::SphericalManipulator() );
std::string pathfile;
double animationSpeed = 1.0;
while(arguments.read("--speed",animationSpeed) ) {}
char keyForAnimationPath = '8';
while (arguments.read("-p",pathfile))
{
osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
if (apm || !apm->valid())
{
apm->setTimeScale(animationSpeed);
unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
keyswitchManipulator->selectMatrixManipulator(num);
++keyForAnimationPath;
}
}
viewer.setCameraManipulator( keyswitchManipulator.get() );
}
// add the state manipulator
viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
// add the thread model handler
viewer.addEventHandler(new osgViewer::ThreadingHandler);
// add the window size toggle handler
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
// add the stats handler
viewer.addEventHandler(new osgViewer::StatsHandler);
// add the help handler
viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
// add the record camera path handler
viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
// add the LOD Scale handler
viewer.addEventHandler(new osgViewer::LODScaleHandler);
// add the screen capture handler
viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
// load the data
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
if (!loadedModel)
{
std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
return 1;
}
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// report any errors if they have occurred when parsing the program arguments.
if (arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
}
osg::Group* root = new osg::Group;
root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
// Create a few tilerasterizers to do work.
unsigned int numTileRasterizers = 10;
for (unsigned int i = 0; i < numTileRasterizers; i++)
{
root->addChild( new TileRasterizer(&textureQueue) );
}
for(unsigned int x = 0; x < 50; x++)
{
for (unsigned int y = 0; y < 50; y++)
{
root->addChild(makeCell(x, y));
}
}
viewer.setSceneData( root );
viewer.realize();
while (!viewer.done())
{
OSG_NOTICE << "Num textures " << textureQueue.size() << std::endl;
viewer.frame();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment