Hi again Troy,

I was thinking of setting up a googlecode project for this work, because there is at least one other person who might be interested in working with me on it (Paul Melis). I'll see if I can do that soon.

It's done now, here:

http://code.google.com/p/osgboostpython/

Note that I do my work on Windows, I've tried to make my boost-build.jam and Jamroot as platform-independent as possible but you may have to tweak some things to make it build/run. You'll need OSG_ROOT and BOOST_ROOT pointing at the right places for it to build.

Once the python modules are built, copy them into lib/osg, lib/osgGA, lib/osgDB and lib/osgViewer (I've scripted that for Windows but I should really make a "stage" rule in the jam script, feel free to do it if you want).

Then run

  python test/osg/test.py 9

(the 9 runs test #9 only, the file contains 10 different tests)

That will work, it will print the following:

  python apply_Group - node name: g1
  python apply_Group - node name: g2
  python apply_Node - node name: n

You'll see the problem if you comment out the apply_Group method of the DerivedVisitor class in test/osg/test.py. Then it will only print out:

  python apply_Node - node name: g1

when it should print out:

  python apply_Node - node name: g1
  python apply_Node - node name: g2
  python apply_Node - node name: n

which is what the C++ code attached does.

You'll also see in test/osgViewer/test.py the other test I was referring to, the NodeCallback test. If you change the code to set the callback as CullCallback instead of UpdateCallback, you'll see that the model will no longer be displayed, even though traverse() is being called. The C++ code attached also demonstrates that this should not happen - the model should still be displayed after setting a CullCallback as long as the callback calls traverse(). (you can comment out traverse() in the callback's operator() method to see that the model will no longer be displayed).

I hope this helps you help me :-)

I just had a thought, maybe I need to wrap the traverse() methods in osg::Node and osg::Group? Would that allow call_method to call the right one and not slice off the argument? I had not wrapped them because in general I don't think they'd be useful in python code, but maybe they're necessary for this to work? I'll try that and see.

Thanks in advance,

J-S
--
______________________________________________________
Jean-Sebastien Guay    jean-sebastien.g...@cm-labs.com
                               http://www.cm-labs.com/
                        http://whitestar02.webhop.org/
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This application is open source and may be redistributed and/or modified   
 * freely and without restriction, both in commericial and non commericial 
applications,
 * as long as this copyright notice is maintained.
 * 
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osg/Switch>
#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 <iostream>

struct TestVisitor : public osg::NodeVisitor
{
    TestVisitor(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}

    void apply(osg::Node& node)
    {
        std::cout << "in apply(node&), name: " << node.getName() << std::endl;
        traverse(node);
    }

/*
    void apply(osg::Group& group)
    {
        std::cout << "in apply(group&), name: " << group.getName() << std::endl;
        traverse(group);
    }
*/
};

struct TestCallback : public osg::NodeCallback
{
    void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        std::cout << "in callback::operator()" << std::endl;
        traverse(node, nv);
    }
};

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+"
 is the standard OpenSceneGraph example which loads and visualises 3d models.");
    
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+"
 [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("--image 
<filename>","Load an image and render it on a quad");
    arguments.getApplicationUsage()->addCommandLineOption("--dem 
<filename>","Load an image/DEM and render it on a HeightField");
    arguments.getApplicationUsage()->addCommandLineOption("--login <url> 
<username> <password>","Provide authentication information for http file 
access.");

    osgViewer::Viewer viewer(arguments);

    unsigned int helpType = 0;
    if ((helpType = arguments.readHelpType()))
    {
        arguments.getApplicationUsage()->write(std::cout, helpType);
        return 1;
    }
    
    // report any errors if they have occurred when parsing the program 
arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }
    
    if (arguments.argc()<=1)
    {
        
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    std::string url, username, password;
    while(arguments.read("--login",url, username, password))
    {
        if (!osgDB::Registry::instance()->getAuthenticationMap())
        {
            osgDB::Registry::instance()->setAuthenticationMap(new 
osgDB::AuthenticationMap);
            
osgDB::Registry::instance()->getAuthenticationMap()->addAuthenticationDetails(
                url,
                new osgDB::AuthenticationDetails(username, password)
            );
        }
    }

    // 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', "Spherical", new 
osgGA::SphericalManipulator() );

        std::string pathfile;
        char keyForAnimationPath = '6';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new 
osgGA::AnimationPathManipulator(pathfile);
            if (apm || !apm->valid()) 
            {
                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;
    }

    // Test a node visitor. Commenting out the apply(Group&) method above
    // just results in the apply(Node&) method being called for all nodes
    // (g1, g2 and n). In python the same thing results in apply_Node being
    // called only for g1, which is not good. It means the Group part is 
    // being sliced off and Node's version of traverse() is being called.
    osg::Group* g1 = new osg::Group;
    g1->setName("g1");
    osg::Group* g2 = new osg::Group;
    g2->setName("g2");
    g1->addChild(g2);
    osg::Node* n = new osg::Node;
    n->setName("n");
    g2->addChild(n);

    TestVisitor v;
    g1->accept(v);


    // Test a callback set as cull callback. In python this makes the model 
    // not display, even though there's a call to traverse(node, nv) in the
    // callback operator() code. In C++ the exact same code works (the model
    // is displayed as it should). If you remove the call to traverse() here
    // you'll see that the model is not displayed anymore, so it seems the 
    // python wrapper slices off the Group part and calls Node's version of
    // traverse(nv).
    TestCallback* callback = new TestCallback;
    loadedModel->setCullCallback(callback);


    viewer.setSceneData( loadedModel.get() );

    viewer.realize();

    return viewer.run();

}
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to