Hello Danny,
Sending your message twice will not get you help faster. Good etiquette
would be to wait a little, and if you don't get any response after a few
days then you can send a reminder, like "no one has any idea what I'm
doing wrong?" or something like that. We all have day jobs and sending
the same message multiple times makes it look like you expect us to stop
everything we're doing to help you...
i can't get the camera's children to update and can't find an example
that works.
Your callbacks weren't actually doing anything to the text or the
geometry. I've modified it to show you one example of what you can do.
Basically, just changing the variable with which you calculated the
vertices and which was in the text (factor) will not change them. You
need to update the text in your callback (using text->setText(string) )
and you need to update your osg::Geometry objects in the other callback
(creating new vertex arrays, or perhaps looping through the existing
vertices and modifying those you need to).
In my modifications, I used std::stringstream instead of boost::format
because I don't have boost on this machine. When you send example code,
it's preferable to send code that has no dependencies other than OSG
(and its own dependencies). It makes it more likely that others will be
able to help.
Note also that you had a memory leak in your code:
osg::Geometry* geom = new osg::Geometry;
geom = drawLines(...);
since drawLines creates a new osg::Geometry and returns it, the original
one was never freed. You could change that in two ways to remove the leak:
// still wasteful, but at least there's no leak
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
geom = drawLines(...);
or simply
osg::Geometry* geom = drawLines(...);
Also, I've set the geometry and text objects to DYNAMIC data variance.
If you're modifying drawables (osg::Geometry and osgText::Text are in
this category) or statesets in update callbacks, you need to set them to
DYNAMIC or else you'll get crashes in multithreaded mode.
Do a diff between the file you sent and the one that's attached to this
message to see the changes. Now that I've shown you how to update text
and geometry in the callbacks, it's up to you to make changes to get the
result you want.
Style comment: it works, but I think you'd be able to understand
yourself more if your code was cleaner and better indented.
Hope this helps,
J-S
--
______________________________________________________
Jean-Sebastien Guay jean-sebastien.g...@cm-labs.com
http://www.cm-labs.com/
http://whitestar02.webhop.org/
/* OpenSceneGraph example, osghud.
*
* 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 <boost/format.hpp>
#include <sstream>
#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgGA/TrackballManipulator>
#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/Camera>
#include <osg/RenderInfo>
#include <osgDB/WriteFile>
#include <osgText/Text>
osg::Vec4 colorVec[] = {
osg::Vec4(0.0f, 0.99f, 0.0f, 1.0f),
osg::Vec4(0.85f, 0.00f, 0.0f, 1.0f),
osg::Vec4(0.0f, 0.00f, 0.0f, 1.0f),
osg::Vec4(1.0f, 1.00f, 1.0f, 1.0f),
osg::Vec4(0.0f, 0.00f, 1.0f, 1.0f),
osg::Vec4(0.3f, 0.30f, 0.3f, 1.0f),
osg::Vec4(0.9f, 0.90f, 0.0f, 1.0f)
};
// create LINES
osg::Geometry * drawLines(osg::Vec3Array * vertices, int colorIndex,
osg::PrimitiveSet::Mode lineType)
{
// create Geometry object to store all the vertices and lines primitive.
osg::Geometry* linesGeom = new osg::Geometry();
// Set dynamic data variance since the geometry will be updated in a
callback.
linesGeom->setDataVariance(osg::Object::DYNAMIC);
// Use vertex buffers so display lists won't need to be updated.
linesGeom->setUseDisplayList(false);
// pass the created vertex array to the points geometry object.
linesGeom->setVertexArray(vertices);
// set the colors as before, plus using the above
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(colorVec[colorIndex]);
linesGeom->setColorArray(colors);
linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
// set the normal in the same way color.
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
linesGeom->setNormalArray(normals);
linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
// This time we simply use primitive, and hardwire the number of coords to
use
// since we know up front,
//linesGeom->addPrimitiveSet(new
osg::DrawArrays(osg::PrimitiveSet::LINES,0,vertices->size()));
linesGeom->addPrimitiveSet(new osg::DrawArrays(lineType, 0,
vertices->size()));
osg::StateSet* stateset = linesGeom->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setAttribute(new osg::PolygonOffset(1.0f, 1.0f),
osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setRenderBinDetails(11, "RenderBin");
// add the points geometry to the geode.
return linesGeom;
}
osg::Geometry * drawBox( float left, float bottom, float right, float top , int
color)
{
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(left, bottom , 0.0));
vertices->push_back(osg::Vec3(left, top, 0.0));
vertices->push_back(osg::Vec3(right-1, top-1, 0.0));
vertices->push_back(osg::Vec3(right - 1, bottom - 1, 0.0));
return drawLines(vertices, color, osg::PrimitiveSet::LINE_LOOP);
}
osg::Node* createLabel(const osg::Vec3& pos, float size, const std::string&
label, osgText::Text::AxisAlignment axisAlignment)
{
osg::Geode* geode = new osg::Geode();
std::string timesFont("fonts/arial.ttf");
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(pos);
text->setCharacterSize(size);
text->setAxisAlignment(axisAlignment);
text->setAlignment(osgText::Text::CENTER_CENTER);
text->setText(label);
text->setColor( colorVec[6] );
osg::StateSet* stateset = text->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setAttribute(new osg::PolygonOffset(1.0f, 1.0f),
osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setRenderBinDetails(11, "RenderBin");
}
return geode;
}
osg::Node* createLabel3(const osg::Vec3& pos, float size, const std::string&
label, int colorIndex = 0)
{
osg::Geode* geode = new osg::Geode();
std::string timesFont("fonts/arial.ttf");
//std::string timesFont("fonts/timesi.ttf");
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(pos);
//text->setFontResolution(40,40);
text->setCharacterSize(size);
text->setAlignment(osgText::Text::CENTER_CENTER);
text->setAxisAlignment(osgText::Text::SCREEN);
text->setAutoRotateToScreen(true);
// figure out what this is actually doing.
//text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
text->setText(label);
text->setColor( colorVec[colorIndex] );
osg::StateSet* stateset = text->getOrCreateStateSet();
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setAttribute(new osg::PolygonOffset(1.0f, 1.0f),
osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setRenderBinDetails(11, "RenderBin");
}
return geode;
}
float factor = 1.0;
struct HUDCallback : public osg::NodeCallback
{
HUDCallback(osgText::Text* text) :_factor(1.0), _text(text){}
virtual void operator() ( osg::Node *node, osg::NodeVisitor *nv)
{
osg::Camera * camera = dynamic_cast<osg::Camera *>(node);
osg::notify(osg::NOTICE) << "out callback" << std::endl;
if( camera )
{
osg::notify(osg::NOTICE) << "in callback" << std::endl;
if ( _factor > 10.0 ) _factor = 1.0;
else _factor += .1;
factor = _factor;
osg::notify(osg::NOTICE) << factor << std::endl;
// Update the text in the osgText object.
std::stringstream sstream;
sstream << factor << " DTK-Head Up Displays are simple :-) ";
std::string moretext = sstream.str();
_text->setText( moretext );
}
traverse(node,nv);
}
float _factor;
osg::observer_ptr<osgText::Text> _text;
};
struct geode_cb : public osg::NodeCallback
{
geode_cb() :_factor(1.0){}
virtual void operator() ( osg::Node *node, osg::NodeVisitor *nv)
{
osg::Geode * geode = dynamic_cast<osg::Geode *>(node);
osg::notify(osg::NOTICE) << "out callback" << std::endl;
if( geode )
{
osg::notify(osg::NOTICE) << "in callback" << std::endl;
if ( _factor > 25.0 ) _factor = 1.0;
else _factor += .1;
factor = _factor;
osg::notify(osg::NOTICE) << factor << std::endl;
// Replace vertex array with new one, which updates the geometry.
// Drawables 0 to 5
for( int i = 0; i < 6; i++ ) {
osg::Geometry* geom = geode->getDrawable(i)->asGeometry();
osg::Vec3Array *vertices = new osg::Vec3Array;
vertices->push_back(
osg::Vec3(factor*100*(i+1),factor*(i+1)*100,0));
vertices->push_back(
osg::Vec3(factor*(i+1)*150,factor*(i+1)*100,0));
vertices->push_back(
osg::Vec3(factor*(i+1)*100,factor*(i+1)*150,0));
geom->setVertexArray(vertices);
}
// Drawable 6
{
osg::Geometry* geom = geode->getDrawable(6)->asGeometry();
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(200/factor, 250/factor , 0.0));
vertices->push_back(osg::Vec3(200/factor, 990/factor, 0.0));
vertices->push_back(osg::Vec3(1005/factor-1, 990/factor-1, 0.0));
vertices->push_back(osg::Vec3(1005/factor - 1, 250/factor - 1,
0.0));
geom->setVertexArray(vertices);
}
}
traverse(node,nv);
}
float _factor;
};
osg::Camera* createHUD()
{
// create a camera to set up the projection and model view matrices, and
the subgraph to drawn in the HUD
osg::Camera* camera = new osg::Camera;
// set the projection matrix
camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
// set the view matrix
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
// only clear the depth buffer
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
// draw subgraph after main camera view.
camera->setRenderOrder(osg::Camera::POST_RENDER);
// we don't want the camera to grab event focus from the viewers main
camera(s).
camera->setAllowEventFocus(false);
// add to this camera a subgraph to render
{
osg::Geode* geode = new osg::Geode();
geode->setUpdateCallback( new geode_cb );
{
// Drawables 0 to 5
for( int i = 0; i < 6; i++ ) {
osg::Vec3Array *vertices = new osg::Vec3Array;
vertices->push_back(
osg::Vec3(factor*100*(i+1),factor*(i+1)*100,0));
vertices->push_back(
osg::Vec3(factor*(i+1)*150,factor*(i+1)*100,0));
vertices->push_back(
osg::Vec3(factor*(i+1)*100,factor*(i+1)*150,0));
osg::Geometry *geom = drawLines( vertices, i,
osg::PrimitiveSet::LINE_LOOP);
geom->setUseDisplayList(false);
geode->addDrawable( geom );
}
// Drawable 6
{
geode->addDrawable(drawBox( 200/factor, 250/factor,
1005/factor, 990/factor, 3 ));
}
}
std::string timesFont("fonts/arial.ttf");
// turn lighting off for the text and disable depth test to ensure its
always ontop.
osg::StateSet* stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::Vec3 position(150.0f,800.0f,0.0f);
osg::Vec3 delta(0.0f,-120.0f,0.0f);
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(position);
//std::string moretext = boost::str(boost::format("%.2f
DTK-Head Up Displays are simple :-) ") % factor );
// Using std::stringstream instead of boost::format.
std::stringstream sstream;
sstream << factor << " DTK-Head Up Displays are simple :-) ";
std::string moretext = sstream.str();
osg::notify(osg::NOTICE) << moretext << std::endl;
text->setText( moretext );
// Set dynamic data variance since the text will be updated in a
callback.
text->setDataVariance(osg::Object::DYNAMIC);
//text->setText("Head Up Displays are simple :-)");
position += delta;
// Now that we have the text object, we can create the callback
// passing it to the ctor so it can update it.
camera->setUpdateCallback( new HUDCallback(text) );
}
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(position);
text->setText("All you need to do is create your text in a
subgraph.");
position += delta;
}
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(position);
text->setText("Then place an osg::Camera above the subgraph\n"
"to create an orthographic projection.\n");
position += delta;
}
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(position);
text->setText("Set the Camera's ReferenceFrame to ABSOLUTE_RF to
ensure\n"
"it remains independent from any external model view
matrices.");
position += delta;
}
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(position);
text->setText("And set the Camera's clear mask to just clear the
depth buffer.");
position += delta;
}
{
osgText::Text* text = new osgText::Text;
geode->addDrawable( text );
text->setFont(timesFont);
text->setPosition(position);
text->setText("And finally set the Camera's RenderOrder to
POST_RENDER\n"
"to make sure its drawn last.");
position += delta;
}
{
osg::BoundingBox bb;
for(unsigned int i=0;i<geode->getNumDrawables();++i)
{
bb.expandBy(geode->getDrawable(i)->getBound());
}
osg::Geometry* geom = new osg::Geometry;
osg::Vec3Array* vertices = new osg::Vec3Array;
float depth = bb.zMin()-0.1;
vertices->push_back(osg::Vec3(bb.xMin(),bb.yMax(),depth));
vertices->push_back(osg::Vec3(bb.xMin(),bb.yMin(),depth));
vertices->push_back(osg::Vec3(bb.xMax(),bb.yMin(),depth));
vertices->push_back(osg::Vec3(bb.xMax(),bb.yMax(),depth));
geom->setVertexArray(vertices);
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
geom->setNormalArray(normals);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0,0.8f,0.2f));
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
osg::StateSet* stateset = geom->getOrCreateStateSet();
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
//stateset->setAttribute(new
osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geode->addDrawable(geom);
}
camera->addChild(geode);
}
return camera;
}
struct SnapImage : public osg::Camera::DrawCallback
{
SnapImage(const std::string& filename):
_filename(filename),
_snapImage(false)
{
_image = new osg::Image;
}
virtual void operator () (osg::RenderInfo& renderInfo) const
{
if (!_snapImage) return;
osg::notify(osg::NOTICE)<<"Camera callback"<<std::endl;
osg::Camera* camera = renderInfo.getCurrentCamera();
osg::Viewport* viewport = camera ? camera->getViewport() : 0;
osg::notify(osg::NOTICE)<<"Camera callback "<<camera<<"
"<<viewport<<std::endl;
if (viewport && _image.valid())
{
_image->readPixels(int(viewport->x()),int(viewport->y()),int(viewport->width()),int(viewport->height()),
GL_RGBA,
GL_UNSIGNED_BYTE);
osgDB::writeImageFile(*_image, _filename);
osg::notify(osg::NOTICE)<<"Taken screenshot, and written to
'"<<_filename<<"'"<<std::endl;
}
_snapImage = false;
}
std::string _filename;
mutable bool _snapImage;
mutable osg::ref_ptr<osg::Image> _image;
};
struct SnapeImageHandler : public osgGA::GUIEventHandler
{
SnapeImageHandler(int key,SnapImage* si):
_key(key),
_snapImage(si) {}
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
if (ea.getHandled()) return false;
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey() == _key)
{
osg::notify(osg::NOTICE)<<"event handler"<<std::endl;
_snapImage->_snapImage = true;
return true;
}
break;
}
default:
break;
}
return false;
}
int _key;
osg::ref_ptr<SnapImage> _snapImage;
};
int main( int argc, char **argv )
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
// read the scene from the list of file specified commandline args.
osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);
// if not loaded assume no arguments passed in, try use default mode
instead.
if (!scene) scene = osgDB::readNodeFile("dumptruck.osg");
if (!scene)
{
osg::notify(osg::NOTICE)<<"No model loaded"<<std::endl;
return 1;
}
if (arguments.read("--Viewer"))
{
// construct the viewer.
osgViewer::Viewer viewer;
// create a HUD as slave camera attached to the master view.
viewer.setUpViewAcrossAllScreens();
osgViewer::Viewer::Windows windows;
viewer.getWindows(windows);
if (windows.empty()) return 1;
osg::Camera* hudCamera = createHUD();
// set up cameras to rendering on the first window available.
hudCamera->setGraphicsContext(windows[0]);
//hudCamera->setViewport(0,0,windows[0]->getTraits()->width,
windows[0]->getTraits()->height);
hudCamera->setViewport(0,0,1680, 1280);
viewer.addSlave(hudCamera, false);
// set the scene to render
viewer.setSceneData(scene.get());
return viewer.run();
}
if (arguments.read("--CompositeViewer"))
{
// construct the viewer.
osgViewer::CompositeViewer viewer;
// create the main 3D view
osgViewer::View* view = new osgViewer::View;
viewer.addView(view);
view->setSceneData(scene.get());
view->setUpViewAcrossAllScreens();;
view->setCameraManipulator(new osgGA::TrackballManipulator);
// now create the HUD camera's view
osgViewer::Viewer::Windows windows;
viewer.getWindows(windows);
if (windows.empty()) return 1;
osg::Camera* hudCamera = createHUD();
// set up cameras to rendering on the first window available.
hudCamera->setGraphicsContext(windows[0]);
//hudCamera->setViewport(0,0,windows[0]->getTraits()->width,
windows[0]->getTraits()->height);
hudCamera->setViewport(0,0,1680, 1280);
osgViewer::View* hudView = new osgViewer::View;
hudView->setCamera(hudCamera);
viewer.addView(hudView);
return viewer.run();
}
else
{
// construct the viewer.
osgViewer::Viewer viewer;
//SnapImage* postDrawCallback = new SnapImage("PostDrawCallback.png");
//viewer.getCamera()->setPostDrawCallback(postDrawCallback);
//viewer.addEventHandler(new SnapeImageHandler('p',postDrawCallback));
//SnapImage* finalDrawCallback = new SnapImage("FinalDrawCallback.png");
//viewer.getCamera()->setFinalDrawCallback(finalDrawCallback);
//viewer.addEventHandler(new SnapeImageHandler('f',finalDrawCallback));
osg::ref_ptr<osg::Group> group = new osg::Group;
// add the HUD subgraph.
if (scene.valid()) group->addChild(scene.get());
group->addChild(createHUD());
// set the scene to render
viewer.setSceneData(group.get());
return viewer.run();
}
}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org