Hello OSGers.
I have been trying to implement a HUD in my unorthodox application. I am
currently displaying 3 models to the screen where I have everything else
transparent. Thus the application works as an overlay on top of whatever other
application the user wishes to run. To do this I am using the pbuffer in OSG,
where I copy all the pixel info over into a struct and then pre multiply the
alpha values of everything and then render it back to the screen.
Because of this I have a very specific way in which I set up my scene and
camera:
Code:
osg::ref_ptr<osg::Referenced> windata = new
osgViewer::GraphicsWindowWin32::WindowData(hWnd);
// Establish Viewer and Camera;
g_viewer = new osgViewer::Viewer();
g_camera = new osg::Camera;
g_camera = g_viewer->getCamera();
// Create and assignTraits for the Graphics Context
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new
osg::GraphicsContext::Traits;
initOSGTraits
(*traits, windata);
osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get());
//Set camera state
g_camera->setGraphicsContext (gc);
g_camera->setDrawBuffer
(GL_NONE);
g_camera->setReadBuffer
(GL_NONE);
g_camera->setProjectionMatrixAsPerspective (30.0f, (double)sWidth
/ (double)sHeight, 1.0, 1000.0);
g_camera->setViewport (new
osg::Viewport(0, 0, sWidth, sHeight));
g_camera->setClearColor
(osg::Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
g_camera->setRenderOrder
(osg::Camera::PRE_RENDER);
g_camera->setRenderTargetImplementation
(osg::Camera::FRAME_BUFFER_OBJECT);
// Set camera direction and perspective
osg::Vec3d eye = osg::Vec3d(0, -100, 0); // position of
the camera
osg::Vec3d center = osg::Vec3d(0, 0, 0); // where does the
camera look.
osg::Vec3d up = osg::Vec3d(0, 0, 1); // the up
vector of the camera
g_camera->setViewMatrixAsLookAt(eye, center, up);
// Establish PBuffer using OSG's image object. Attach it to the camera.
g_image = new osg::Image();
g_image->allocateImage(sWidth, sHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE);
g_camera->attach(osg::Camera::COLOR_BUFFER, g_image);
// Set Callback for adding textures. Makes sharing textures possible.
osgDB::Registry::instance()->setReadFileCallback(new
ReadAndShareImageCallback);
osgDB::Registry::instance()->getOrCreateSharedStateManager();
osg::ref_ptr<osg::Group> models = InitModels();
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(models);
// Run OSG optimizer for efficiency.
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
//Set up threads to windows, getScene data and set GL mode for
rescaling normals.
g_viewer->realize();
g_viewer->setSceneData(root.get());
root->getOrCreateStateSet()->setMode(GL_NORMALIZE,
osg::StateAttribute::ON);
I tried using the example from the OSG for beginners book in chapter 7:
Creating an HUD camera. I also tried to follow the example here
(http://trac.openscenegraph.org/projects/osg//browser/OpenSceneGraph/trunk/examples/osghud/osghud.cpp).
Unfortunately none of these seemed to work for me. In fact nothing showed up
on my screen at all. I was thinking it may be because of the way I define my
camera matrix. Maybe not, Im a bit too much of a newbie to know.
Anyways, I figured a HUD can just as well be a quad that is right up close to
the camera. So I used this code :
Code:
osg::ref_ptr<osg::Geode> geod = new osg::Geode;
osg::ref_ptr< osg::Geometry> geom = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> verts = new osg::Vec3Array;
osg::ref_ptr<osg::Vec3Array> norms = new osg::Vec3Array;
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
float depth = -99.0f;
verts->push_back(osg::Vec3((1.0f / 3.0f), depth, (1)));
verts->push_back(osg::Vec3((1), depth, (1)));
verts->push_back(osg::Vec3((1), depth, -(1)));
verts->push_back(osg::Vec3((1.0f / 3.0f), depth, -(1)));
norms->push_back(osg::Vec3(0.0, 0.0f, 0.0f));
colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 0.8f));
geom->setVertexArray(verts);
geom->setNormalArray(norms, osg::Array::BIND_OVERALL);
geom->setColorArray(colors, osg::Array::BIND_OVERALL);
geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
osg::ref_ptr<osg::StateSet> stateset = geom->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geod->addDrawable(geom);
After playing around I realized that the 0,0 point of the quad was in fact
right in the middle of my scene. But by using the z depth of -99 which is 1
point off my camera z depth I can use the [0,1] range to make it fit where I
want. Thus I get a nice horizontal bar along the left side of the screen.
Now this feels like a somewhat unusual way of doing things. How would I do
this in a more professional way or standardized way, I guess I should say?
Also on a side note, I only get about 36 fps with this application at the
moment. If anyone feels inspired to give me some tips on how to make this more
efficient that would be most appreciated.
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=60885#60885
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org