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





_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to