[osg-users] Setting the transform matrices
Chris Kuliukas
chris at kuliukas.com
Fri Sep 1 19:48:14 PDT 2017
Oops, forgot that most readers are on the mailing list. Here is the code which breaks with vertex attrib aliasing:
Code:
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
*
* This application is open source and may be redistributed and/or modified
* freely and without restriction, both in commercial and non commercial 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 <osg/Types>
#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 <osgGA/Device>
#include <iostream>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/Point>
#include <osg/PointSprite>
#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ModularProgram>
#include <osgParticle/AccelOperator>
#include <osgParticle/DampingOperator>
#include <osgParticle/BounceOperator>
#include <osgParticle/SinkOperator>
void createFountainEffect(osgParticle::ModularEmitter* emitter, osgParticle::ModularProgram* program)
{
// Emit specific number of particles every frame
osg::ref_ptr<osgParticle::RandomRateCounter> rrc = new osgParticle::RandomRateCounter;
rrc->setRateRange(500, 2000);
// Accelerate particles in the given gravity direction.
osg::ref_ptr<osgParticle::AccelOperator> accel = new osgParticle::AccelOperator;
accel->setToGravity();
// Multiply each particle's velocity by a damping constant.
osg::ref_ptr<osgParticle::DampingOperator> damping = new osgParticle::DampingOperator;
damping->setDamping(0.9f);
// Bounce particles off objects defined by one or more domains.
// Supported domains include triangle, rectangle, plane, disk and sphere.
// Since a bounce always happens instantaneously, it will not work correctly with unstable delta-time.
// At present, even the floating error of dt (which are applied to ParticleSystem and Operator separately)
// causes wrong bounce results. Some one else may have better solutions for this.
osg::ref_ptr<osgParticle::BounceOperator> bounce = new osgParticle::BounceOperator;
bounce->setFriction(-0.05);
bounce->setResilience(0.35);
bounce->addDiskDomain(osg::Vec3(0.0f, 0.0f, -2.0f), osg::Z_AXIS, 8.0f);
bounce->addPlaneDomain(osg::Plane(osg::Z_AXIS, 5.0f));
// Kill particles going inside/outside of specified domains.
osg::ref_ptr<osgParticle::SinkOperator> sink = new osgParticle::SinkOperator;
sink->setSinkStrategy(osgParticle::SinkOperator::SINK_OUTSIDE);
sink->addSphereDomain(osg::Vec3(), 20.0f);
emitter->setCounter(rrc.get());
program->addOperator(accel.get());
program->addOperator(damping.get());
program->addOperator(bounce.get());
program->addOperator(sink.get());
}
const std::string OSG_DATA_FOLDER("C:/Users/User/Desktop/OpenSceneGraph/OpenSceneGraph-Data/");
int main(int argc, char** argv)
{
auto useVertexAttributeAliasing = false;
auto useModelViewAndProjectionUniforms = true;
bool useShaders = false;
if (argc > 1) {
auto caseNo = atoi(argv[1]);
// 8 pemutations of 3 options, 0-7
// Case 4 : Black cow
// Case 5 : Black cow, purple particle smoke
// Case 6 : Black cow
useVertexAttributeAliasing = (0x4 & caseNo)!=0;
useModelViewAndProjectionUniforms = (0x2 & caseNo) != 0;
useShaders = (0x1 & caseNo) != 0;
}
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer viewer(arguments);
std::string textureFile(OSG_DATA_FOLDER + "Images/smoke.rgb");
while (arguments.read("--texture", textureFile)) {}
float pointSize = 20.0f;
while (arguments.read("--point", pointSize)) {}
double visibilityDistance = -1.0f;
while (arguments.read("--visibility", visibilityDistance)) {}
bool customShape = false;
while (arguments.read("--enable-custom")) { customShape = true; }
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;
}
// 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', "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());
}
// 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::readRefNodeFiles(arguments);
// 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;
}
/***
Customize particle template and system attributes
***/
osg::ref_ptr<osgParticle::ParticleSystem> ps = new osgParticle::ParticleSystem;
ps->getDefaultParticleTemplate().setLifeTime(5.0f);
if (customShape)
{
// osgParticle now supports making use of customized drawables. The draw() method will be executed
// and display lists will be called for each particle. It is always a huge consumption of memory, and
// hardly to use shaders to render them, so please be careful using this feature.
ps->getDefaultParticleTemplate().setShape(osgParticle::Particle::USER);
ps->getDefaultParticleTemplate().setDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f)));
useShaders = false;
}
else
{
// The shader only supports rendering points at present.
ps->getDefaultParticleTemplate().setShape(osgParticle::Particle::POINT);
}
// Set the visibility distance of particles, due to their Z-value in the eye coordinates.
// Particles that are out of the distance (or behind the eye) will not be rendered.
ps->setVisibilityDistance(visibilityDistance);
if (useShaders)
{
// Set using local GLSL shaders to render particles.
// At present, this is slightly efficient than ordinary methods. The bottlenack here seems to be the cull
// traversal time. Operators go through the particle list again and again...
ps->setDefaultAttributesUsingShaders(textureFile, true, 0);
}
else
{
// The default methods uses glBegin()/glEnd() pairs. Fortunately the GLBeginEndAdapter does improve the
// process, which mimics the immediate mode with glDrawArrays().
ps->setDefaultAttributes(textureFile, true, false, 0);
// Without the help of shaders, we have to sort particles to make the visibility distance work. Sorting is
// also useful in rendering transparent particles in back-to-front order.
if (visibilityDistance>0.0)
ps->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
}
// At last, to make the point sprite work, we have to set the points size and the sprite attribute.
osg::StateSet* stateset = ps->getOrCreateStateSet();
stateset->setAttribute(new osg::Point(pointSize));
stateset->setTextureAttributeAndModes(0, new osg::PointSprite, osg::StateAttribute::ON);
/***
Construct other particle system elements, including the emitter and program
***/
osg::ref_ptr<osgParticle::ModularEmitter> emitter = new osgParticle::ModularEmitter;
emitter->setParticleSystem(ps.get());
osg::ref_ptr<osgParticle::ModularProgram> program = new osgParticle::ModularProgram;
program->setParticleSystem(ps.get());
createFountainEffect(emitter.get(), program.get());
/***
Add the entire particle system to the scene graph
***/
osg::ref_ptr<osg::MatrixTransform> parent = new osg::MatrixTransform;
parent->addChild(emitter.get());
parent->addChild(program.get());
// The updater can receive particle systems as child drawables now. The addParticleSystem() method
// is still usable, with which we should define another geode to contain a particle system.
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater = new osgParticle::ParticleSystemUpdater;
//updater->addDrawable( ps.get() );
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(parent.get());
root->addChild(updater.get());
// FIXME 2010.9.19: the updater can't be a drawable; otehrwise the ParticleEffect will not work properly. why?
updater->addParticleSystem(ps.get());
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(ps.get());
root->addChild(geode.get());
std::string cowFile(OSG_DATA_FOLDER + "cow.osg");
auto cow = osgDB::readNodeFile(cowFile);
root->addChild(cow);
viewer.setSceneData(root);
viewer.realize();
auto cams = std::vector<osg::Camera*>();
viewer.getCameras(cams, false);
for (int i = 0; i < cams.size(); i++) {
if(cams.at(i)->getGraphicsContext() ) cams.at(i)->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(useVertexAttributeAliasing);
if (cams.at(i)->getGraphicsContext()) cams.at(i)->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(useModelViewAndProjectionUniforms);
}
viewer.run();
}
------------------------
http://www.hrwallingford.com/facilities/ship-simulation-centre (http://www.hrwallingford.com/facilities/ship-simulation-centre)
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71599#71599
More information about the osg-users
mailing list