2016-08-25 18:05:30 +08:00
|
|
|
/* OpenSceneGraph example, osgimpostor.
|
|
|
|
*
|
|
|
|
* 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 <osg/Geometry>
|
|
|
|
#include <osg/Material>
|
|
|
|
#include <osg/MatrixTransform>
|
|
|
|
#include <osg/Quat>
|
|
|
|
#include <osg/Geode>
|
|
|
|
|
|
|
|
#include <osgSim/Impostor>
|
|
|
|
#include <osgSim/InsertImpostorsVisitor>
|
|
|
|
|
|
|
|
#include <osgDB/ReadFile>
|
|
|
|
#include <osgDB/WriteFile>
|
|
|
|
|
|
|
|
#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 "TestManipulator.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
|
|
|
|
int main( int argc, char **argv )
|
|
|
|
{
|
|
|
|
// use an ArgumentParser object to manage the program arguments.
|
|
|
|
osg::ArgumentParser arguments(&argc,argv);
|
|
|
|
|
|
|
|
// construct the viewer.
|
|
|
|
osgViewer::Viewer viewer;
|
|
|
|
|
|
|
|
// set up the camera manipulators.
|
|
|
|
{
|
|
|
|
osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
|
|
|
|
|
|
|
|
// add local test manipulator more suitable for testing impostors.
|
|
|
|
keyswitchManipulator->addMatrixManipulator( '0', "Test", new TestManipulator);
|
|
|
|
|
|
|
|
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', "Orbit", new osgGA::OrbitManipulator() );
|
|
|
|
keyswitchManipulator->addMatrixManipulator( '6', "FirstPerson", new osgGA::FirstPersonManipulator() );
|
|
|
|
keyswitchManipulator->addMatrixManipulator( '7', "Spherical", new osgGA::SphericalManipulator() );
|
|
|
|
|
|
|
|
std::string pathfile;
|
|
|
|
double animationSpeed = 1.0;
|
|
|
|
while(arguments.read("--speed",animationSpeed) ) {}
|
|
|
|
char keyForAnimationPath = '8';
|
|
|
|
while (arguments.read("-p",pathfile))
|
|
|
|
{
|
|
|
|
osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
|
|
|
|
if (apm || !apm->valid())
|
|
|
|
{
|
|
|
|
apm->setTimeScale(animationSpeed);
|
|
|
|
|
|
|
|
unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
|
|
|
|
keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
|
|
|
|
keyswitchManipulator->selectMatrixManipulator(num);
|
|
|
|
++keyForAnimationPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
viewer.setCameraManipulator( keyswitchManipulator.get() );
|
|
|
|
}
|
|
|
|
|
|
|
|
viewer.addEventHandler(new osgViewer::StatsHandler);
|
|
|
|
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
|
|
|
|
|
|
|
|
std::string output_filename;
|
|
|
|
arguments.read("-o", output_filename);
|
|
|
|
|
|
|
|
|
|
|
|
// load the nodes from the commandline arguments.
|
|
|
|
osg::ref_ptr<osg::Node> model = osgDB::readRefNodeFiles(arguments);
|
|
|
|
if (!model)
|
|
|
|
{
|
|
|
|
OSG_NOTICE<<"No model loaded, please specify and model on the the command line"<<std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// the osgSim::InsertImpostorsVisitor used lower down to insert impostors
|
|
|
|
// only operators on subclass of Group's, if the model top node is not
|
|
|
|
// a group then it won't be able to insert an impostor. We therefore
|
|
|
|
// manually insert an impostor above the model.
|
|
|
|
if (dynamic_cast<osg::Group*>(model.get())==0)
|
|
|
|
{
|
|
|
|
const osg::BoundingSphere& bs = model->getBound();
|
|
|
|
if (bs.valid())
|
|
|
|
{
|
|
|
|
|
|
|
|
osgSim::Impostor* impostor = new osgSim::Impostor;
|
|
|
|
|
|
|
|
// standard LOD settings
|
|
|
|
impostor->addChild(model.get());
|
|
|
|
impostor->setRange(0,0.0f,1e7f);
|
|
|
|
impostor->setCenter(bs.center());
|
|
|
|
|
2017-08-16 00:23:49 +08:00
|
|
|
// impostor specific settings.
|
2016-08-25 18:05:30 +08:00
|
|
|
impostor->setImpostorThresholdToBound(5.0f);
|
|
|
|
|
|
|
|
model = impostor;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we insert an impostor node above the model, so we keep a handle
|
|
|
|
// on the rootnode of the model, the is required since the
|
|
|
|
// InsertImpostorsVisitor can add a new root in automatically and
|
|
|
|
// we would know about it, other than by following the parent path
|
|
|
|
// up from model. This is really what should be done, but I'll pass
|
|
|
|
// on it right now as it requires a getRoots() method to be added to
|
|
|
|
// osg::Node, and we're about to make a release so no new features!
|
|
|
|
osg::ref_ptr<osg::Group> rootnode = new osg::Group;
|
|
|
|
rootnode->addChild(model);
|
|
|
|
|
|
|
|
|
|
|
|
// now insert impostors in the model using the InsertImpostorsVisitor.
|
|
|
|
osgSim::InsertImpostorsVisitor ov;
|
|
|
|
|
|
|
|
// traverse the model and collect all osg::Group's and osg::LOD's.
|
|
|
|
// however, don't traverse the rootnode since we want to keep it as
|
|
|
|
// the start of traversal, otherwise the insertImpostor could insert
|
|
|
|
// and Impostor above the current root, making it nolonger a root!
|
|
|
|
model->accept(ov);
|
|
|
|
|
|
|
|
// insert the Impostors above groups and LOD's
|
|
|
|
ov.insertImpostors();
|
|
|
|
|
|
|
|
|
|
|
|
if (!output_filename.empty())
|
|
|
|
{
|
|
|
|
osgDB::writeNodeFile(*rootnode, output_filename);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// add model to viewer.
|
|
|
|
viewer.setSceneData(rootnode);
|
|
|
|
|
|
|
|
return viewer.run();
|
|
|
|
}
|