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

Reply via email to