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