int main(int argc, char **argv)
{
    preloadSharedObject("OSGImageFileIO");
    // OSG init
    osgInit(argc,argv);

    {
        // Set up Window
        WindowEventProducerRecPtr TutorialWindow = createNativeWindow();
        TutorialWindow->initWindow();

        // Create the SimpleSceneManager helper
        SimpleSceneManager sceneManager;
        TutorialWindow->setDisplayCallback(boost::bind(display, &sceneManager));
        TutorialWindow->setReshapeCallback(boost::bind(reshape, _1, &sceneManager));

        // Tell the Manager what to manage
        sceneManager.setWindow(TutorialWindow);

        //Attach to events
        TutorialWindow->connectMousePressed(boost::bind(mousePressed, _1, &sceneManager));
        TutorialWindow->connectMouseReleased(boost::bind(mouseReleased, _1, &sceneManager));
        TutorialWindow->connectMouseMoved(boost::bind(mouseMoved, _1, &sceneManager));
        TutorialWindow->connectMouseDragged(boost::bind(mouseDragged, _1, &sceneManager));
        TutorialWindow->connectMouseWheelMoved(boost::bind(mouseWheelMoved, _1, &sceneManager));

        // Creating the Particle System Material
        // Here, the image is loaded.  The entire image sequence is conatined in one image,
        // which reduces texture memory overhead and runs faster.
        TextureObjChunkRefPtr QuadTextureChunk = TextureObjChunk::create();
        ImageRefPtr LoadedImage = ImageFileHandler::the()->read("Data/Explosion.png");
        QuadTextureChunk->setImage(LoadedImage);

        TextureEnvChunkRefPtr QuadTextureEnvChunk = TextureEnvChunk::create();
        QuadTextureEnvChunk->setEnvMode(GL_MODULATE);

        BlendChunkRefPtr PSBlendChunk = BlendChunk::create();
        PSBlendChunk->setSrcFactor(GL_SRC_ALPHA);
        PSBlendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);

        MaterialChunkRefPtr PSMaterialChunk = MaterialChunk::create();
        PSMaterialChunk->setLit(false);

        ChunkMaterialRefPtr PSMaterial = ChunkMaterial::create();
        PSMaterial->addChunk(QuadTextureChunk);
        PSMaterial->addChunk(QuadTextureEnvChunk);
        PSMaterial->addChunk(PSMaterialChunk);
        PSMaterial->addChunk(PSBlendChunk);

        //Particle System
        ParticleSystemRecPtr ExplosionParticleSystem = ParticleSystem::create();
        ExplosionParticleSystem->attachUpdateProducer(TutorialWindow);

        //Age Particle Function.  Controls which image is shown when, based on the age of a particle.
        AgeParticleFunctionRecPtr AgeFunc = AgeParticleFunction::create();
        AgeFunc->setSequenceTime(0.07f); // image changes every 0.1 seconds.
        AgeFunc->setSequenceOrder(AgeParticleFunction::CUSTOM); // using the custom sequence below.
        /*
           Here, a custom sequence for the image ordering is assembled.  The image sequence will be shown in
           the order specified here.  Once the end of the sequence is reached, the sequence repeats.
           */
        UInt32 NumImages(25);
        for(UInt32 i(0) ; i<NumImages ; ++i)
        {
            AgeFunc->editMFCustomSequence()->push_back(i);
        }

        //Particle System Drawer -
        QuadSequenceParticleSystemDrawerRecPtr ExplosionParticleSystemDrawer = QuadSequenceParticleSystemDrawer::create();
        // image dimensions (in pixels) are required if there is a border on the images.
        ExplosionParticleSystemDrawer->setImageDimensions(Vec2us(320,320));
        // The "dimensions" of the sequence contained in the image.  For this image,
        // there are 3 images in the "x" direction, and two in the "y" direction, for a
        // total of 6.
        ExplosionParticleSystemDrawer->setSequenceDimensions(Vec2b(5,5));
        // width of the border on each side of the image, in pixels.
        ExplosionParticleSystemDrawer->setBorderOffsets(Vec2b(0,0));
        // this is the age function we just created above.
        ExplosionParticleSystemDrawer->setSequenceFunction(AgeFunc);

        RateParticleGeneratorRecPtr ExplosionParticleGenerator = RateParticleGenerator::create();
        //Attach the function objects to the Generator
        ExplosionParticleGenerator->setPositionDistribution(createPositionDistribution());
        ExplosionParticleGenerator->setLifespanDistribution(createLifespanDistribution());
        ExplosionParticleGenerator->setVelocityDistribution(createVelocityDistribution());
        ExplosionParticleGenerator->setAccelerationDistribution(createAccelerationDistribution());
        ExplosionParticleGenerator->setSizeDistribution(createSizeDistribution());
        ExplosionParticleGenerator->setGenerationRate(100.0f);

        //Particle System Node
        ParticleSystemCoreRefPtr ExplosionParticleCore = ParticleSystemCore::create();
        ExplosionParticleCore->setSystem(ExplosionParticleSystem);
        ExplosionParticleCore->setDrawer(ExplosionParticleSystemDrawer);
        ExplosionParticleCore->setMaterial(PSMaterial);
        ExplosionParticleCore->setSortingMode(ParticleSystemCore::BACK_TO_FRONT);

        NodeRefPtr ExplosionParticleNode = Node::create();
        ExplosionParticleNode->setCore(ExplosionParticleCore);

        ExplosionParticleSystem->addParticle(Pnt3f(10.0,0.0,0.0),
                                             Vec3f(0.0,1.0,0.0),
                                             Color4f(1.0,1.0,1.0,1.0),
                                             Vec3f(1.0,1.0,1.0),
                                             0.01,
                                             Vec3f(0.0,0.0,0.0),
                                             Vec3f(0.0,0.0,0.0));

        ExplosionParticleSystem->addParticle(Pnt3f(-10.0,0.0,0.0),
                                             Vec3f(0.0,1.0,0.0),
                                             Color4f(1.0,1.0,1.0,1.0),
                                             Vec3f(1.0,1.0,1.0),
                                             0.01,
                                             Vec3f(0.0,0.0,0.0),
                                             Vec3f(0.0,0.0,0.0));

        ExplosionParticleSystem->pushToGenerators(ExplosionParticleGenerator);

        AgeSizeParticleAffectorRecPtr ExampleAgeSizeParticleAffector = AgeSizeParticleAffector::create();

        //Age and size
        ExampleAgeSizeParticleAffector->editMFAges()->push_back(0.0);
        ExampleAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(0.2,0.2,0.2));
        ExampleAgeSizeParticleAffector->editMFAges()->push_back(1.0);
        ExampleAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(4.0,4.0,4.0));
        ExampleAgeSizeParticleAffector->editMFAges()->push_back(1.8);
        ExampleAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.2,2.2,0.1));

        //Age Fade Affector
        AgeFadeParticleAffectorRecPtr ExampleAgeFadeParticleAffector = AgeFadeParticleAffector::create();

        //Age and size
        ExampleAgeFadeParticleAffector->setStartAlpha(0.0f);
        ExampleAgeFadeParticleAffector->setFadeInTime(0.5f);
        ExampleAgeFadeParticleAffector->setFadeToAlpha(1.0f);
        ExampleAgeFadeParticleAffector->setFadeOutTime(0.5f);
        ExampleAgeFadeParticleAffector->setEndAlpha(0.0f);
        ExplosionParticleSystem->pushToAffectors(ExampleAgeFadeParticleAffector);

        //Smoke Particle System
        VortexParticleAffectorRecPtr SmokeVortexAffector = VortexParticleAffector::create();
        SmokeVortexAffector->setMagnitude(0.2);
        SmokeVortexAffector->setVortexAxis(Vec3f(0.0,1.0,0.0)); // field rotates around y axis
        NodeRefPtr VortexBeacon = makeCoredNode<Group>();
        SmokeVortexAffector->setBeacon(VortexBeacon); // set to 'emulate' from (0,0,0)
        SmokeVortexAffector->setMaxDistance(-1.0); // particles affected regardless of distance
        SmokeVortexAffector->setAttenuation(0.25); // strength of uniform field dimishes by dist^attenuation

        AgeFadeParticleAffectorRecPtr SmokeAgeFadeParticleAffector = AgeFadeParticleAffector::create();

        //Age and size
        SmokeAgeFadeParticleAffector->setStartAlpha(0.0f);
        SmokeAgeFadeParticleAffector->setFadeInTime(0.2f);
        SmokeAgeFadeParticleAffector->setFadeToAlpha(1.0f);
        SmokeAgeFadeParticleAffector->setFadeOutTime(3.5f);
        SmokeAgeFadeParticleAffector->setEndAlpha(0.0f);

        RateParticleGeneratorRecPtr SmokeParticleGenerator = RateParticleGenerator::create();
        SmokeParticleGenerator->setSizeDistribution(createSmokeSizeDistribution());
        SmokeParticleGenerator->setPositionDistribution(createSmokePositionDistribution());
        SmokeParticleGenerator->setLifespanDistribution(createSmokeLifespanDistribution());
        SmokeParticleGenerator->setVelocityDistribution(createSmokeVelocityDistribution());
        SmokeParticleGenerator->setColorDistribution(createSmokeColorDistribution());
        SmokeParticleGenerator->setGenerationRate(80.0f);

        ParticleSystemRecPtr SmokeParticleSystem = ParticleSystem::create();
        SmokeParticleSystem->pushToGenerators(SmokeParticleGenerator);
        SmokeParticleSystem->attachUpdateProducer(TutorialWindow);
        SmokeParticleSystem->pushToAffectors(SmokeAgeFadeParticleAffector);
        SmokeParticleSystem->pushToAffectors(SmokeVortexAffector);

        TextureObjChunkRefPtr SmokeTextureObjChunk = TextureObjChunk::create();
        ImageRefPtr SmokeImage = ImageFileHandler::the()->read("Data/Smoke.png");
        SmokeTextureObjChunk->setImage(SmokeImage);

        ChunkMaterialRefPtr SmokeMaterial = ChunkMaterial::create();
        SmokeMaterial->addChunk(SmokeTextureObjChunk);
        SmokeMaterial->addChunk(QuadTextureEnvChunk);
        SmokeMaterial->addChunk(PSMaterialChunk);
        SmokeMaterial->addChunk(PSBlendChunk);
        SmokeMaterial->setSortKey(-1.0f);

        QuadParticleSystemDrawerRecPtr SmokeParticleSystemDrawer = QuadParticleSystemDrawer::create();

        ParticleSystemCoreRefPtr SmokeParticleCore = ParticleSystemCore::create();
        SmokeParticleCore->setSystem(SmokeParticleSystem);
        SmokeParticleCore->setDrawer(SmokeParticleSystemDrawer);
        SmokeParticleCore->setMaterial(SmokeMaterial);
        SmokeParticleCore->setSortingMode(ParticleSystemCore::BACK_TO_FRONT);

        NodeRefPtr SmokeParticleNode = Node::create();
        SmokeParticleNode->setCore(SmokeParticleCore);

        // Make Main Scene Node and add the Torus
        NodeRefPtr scene = makeCoredNode<Group>();
        scene->addChild(ExplosionParticleNode);
        scene->addChild(SmokeParticleNode);
        scene->addChild(VortexBeacon);

        TutorialWindow->connectKeyTyped(boost::bind(keyTyped, _1,
                                        &sceneManager,
                                        AgeFunc.get()));

        sceneManager.setRoot(scene);

        // Show the whole Scene
        sceneManager.showAll();

        //Open Window
        Vec2f WinSize(TutorialWindow->getDesktopSize() * 0.85f);
        Pnt2f WinPos((TutorialWindow->getDesktopSize() - WinSize) *0.5);
        TutorialWindow->openWindow(WinPos,
                                   WinSize,
                                   "06Explosion");

        //Enter main Loop
        TutorialWindow->mainLoop();
    }

    osgExit();

    return 0;
}
int main(int argc, char **argv)
{
    preloadSharedObject("OSGImageFileIO");

    // OSG init
    osgInit(argc,argv);

    {
        // Set up Window
        WindowEventProducerRecPtr TutorialWindow = createNativeWindow();
        TutorialWindow->initWindow();

        // Create the SimpleSceneManager helper
        SimpleSceneManager sceneManager;
        TutorialWindow->setDisplayCallback(boost::bind(display, &sceneManager));
        TutorialWindow->setReshapeCallback(boost::bind(reshape, _1, &sceneManager));

        // Tell the Manager what to manage
        sceneManager.setWindow(TutorialWindow);

        //Attach to events
        TutorialWindow->connectMouseReleased(boost::bind(mouseReleased, _1, &sceneManager));
        TutorialWindow->connectMouseDragged(boost::bind(mouseDragged, _1, &sceneManager));
        TutorialWindow->connectMouseWheelMoved(boost::bind(mouseWheelMoved, _1, &sceneManager));
        TutorialWindow->connectKeyTyped(boost::bind(keyTyped, _1, &sceneManager));

        //Particle System Material
        //point material
        PointChunkRefPtr PSPointChunk = PointChunk::create();
        PSPointChunk->setSize(5.0f);
        PSPointChunk->setSmooth(true);
        BlendChunkRefPtr PSBlendChunk = BlendChunk::create();
        PSBlendChunk->setSrcFactor(GL_SRC_ALPHA);
        PSBlendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);

        MaterialChunkRefPtr PSMaterialChunkChunk = MaterialChunk::create();
        PSMaterialChunkChunk->setAmbient(Color4f(0.3f,0.3f,0.3f,1.0f));
        PSMaterialChunkChunk->setDiffuse(Color4f(0.7f,0.7f,0.7f,1.0f));
        PSMaterialChunkChunk->setSpecular(Color4f(0.9f,0.9f,0.9f,1.0f));
        PSMaterialChunkChunk->setColorMaterial(GL_AMBIENT_AND_DIFFUSE);

        ChunkMaterialRefPtr PSPointMaterial = ChunkMaterial::create();
        PSPointMaterial->addChunk(PSPointChunk);
        PSPointMaterial->addChunk(PSMaterialChunkChunk);
        PSPointMaterial->addChunk(PSBlendChunk);

        //smoke material
        TextureObjChunkRefPtr QuadTextureObjChunk = TextureObjChunk::create();
        ImageRefPtr LoadedImage = ImageFileHandler::the()->read("Data/Smoke.png");    
        QuadTextureObjChunk->setImage(LoadedImage);

        TextureEnvChunkRefPtr QuadTextureEnvChunk = TextureEnvChunk::create();
        QuadTextureEnvChunk->setEnvMode(GL_MODULATE);

        MaterialChunkRefPtr PSMaterialChunk = MaterialChunk::create();
        PSMaterialChunk->setAmbient(Color4f(0.3f,0.3f,0.3f,1.0f));
        PSMaterialChunk->setDiffuse(Color4f(0.7f,0.7f,0.7f,1.0f));
        PSMaterialChunk->setSpecular(Color4f(0.9f,0.9f,0.9f,1.0f));
        PSMaterialChunk->setColorMaterial(GL_AMBIENT_AND_DIFFUSE);

        ChunkMaterialRefPtr PSSmokeMaterial = ChunkMaterial::create();
        PSSmokeMaterial->addChunk(QuadTextureObjChunk);
        PSSmokeMaterial->addChunk(PSMaterialChunk);
        PSSmokeMaterial->addChunk(PSBlendChunk);
        PSSmokeMaterial->addChunk(QuadTextureEnvChunk);


        //Particle System
        //Rocket
        ParticleSystemRecPtr RocketParticleSystem = ParticleSystem::create();
        RocketParticleSystem->attachUpdateProducer(TutorialWindow);

        //smoke
        ParticleSystemRecPtr SmokeParticleSystem = ParticleSystem::create();
        SmokeParticleSystem->attachUpdateProducer(TutorialWindow);
        //Shrapnel
        ParticleSystemRecPtr ShrapnelParticleSystem = ParticleSystem::create();
        ShrapnelParticleSystem->attachUpdateProducer(TutorialWindow);
        //Fireball
        ParticleSystemRecPtr FireballParticleSystem = ParticleSystem::create();
        FireballParticleSystem->attachUpdateProducer(TutorialWindow);



        //Particle System Drawer
        //Rocket does not have a drawer because it is being attached to a special node core
        //Smoke
        QuadParticleSystemDrawerRecPtr SmokeParticleSystemDrawer = QuadParticleSystemDrawer::create();
        //SmokeParticleSystemDrawer->setQuadSizeScaling(Vec2f(0.5f,0.5f));
        //Shrapnel
        PointParticleSystemDrawerRecPtr ExampleShrapnelParticleSystemDrawer = PointParticleSystemDrawer::create();
        ExampleShrapnelParticleSystemDrawer->setForcePerParticleSizing(true);
        //Fireball
        PointParticleSystemDrawerRecPtr ExampleFireballParticleSystemDrawer = PointParticleSystemDrawer::create();
        ExampleFireballParticleSystemDrawer->setForcePerParticleSizing(true);

        //Particle System Node
        //collision node
        //NodeRefPtr EnvironmentNode = makeSphere(2,4.0f);

        Matrix EnvironmentTransformation;
        EnvironmentTransformation.setTranslate(0.0f,0.0f,10.0f);

        TransformRefPtr EnvironmentTransformCore = Transform::create();
        EnvironmentTransformCore->setMatrix(EnvironmentTransformation);

        NodeRefPtr EnvironmentNode = Node::create();
        EnvironmentNode->setCore(EnvironmentTransformCore);
        NodeRefPtr EnvironmentGeoNode = SceneFileHandler::the()->read("Data/house.obj");
        if(EnvironmentGeoNode == NULL)
        {
            EnvironmentGeoNode = makeTorus(.5, 2, 16, 16);
        }
        EnvironmentNode->addChild(EnvironmentGeoNode);

        NodeRefPtr RocketParticlePrototypeNode = SceneFileHandler::the()->read("Data/rocket.obj");
        if(RocketParticlePrototypeNode == NULL)
        {
            RocketParticlePrototypeNode = makeTorus(.2, 0.8, 16, 16);
        }

        NodeParticleSystemCoreRefPtr RocketParticleNodeCore = NodeParticleSystemCore::create();
        RocketParticleNodeCore->setSystem(RocketParticleSystem);
        RocketParticleNodeCore->setPrototypeNode(RocketParticlePrototypeNode);
        RocketParticleNodeCore->setNormalSource(NodeParticleSystemCore::NORMAL_VELOCITY);
        RocketParticleNodeCore->setUpSource(NodeParticleSystemCore::UP_PARTICLE_NORMAL);
        RocketParticleNodeCore->setUp(Vec3f(0.0f,1.0f,0.0f));

        //Geometry Collision Affector
        GeometryCollisionParticleSystemAffectorRefPtr ExampleGeometryCollisionParticleSystemAffector = GeometryCollisionParticleSystemAffector::create();
        ExampleGeometryCollisionParticleSystemAffector->setCollisionNode(EnvironmentNode);

        ExampleGeometryCollisionParticleSystemAffector->connectParticleCollision(boost::bind(particleCollision, _1));

        NodeRefPtr RocketParticleNode = Node::create();
        RocketParticleNode->setCore(RocketParticleNodeCore);

        //Attach the Affector to the Rocket Particle System
        //RocketParticleSystem->pushToAffectors();
        RocketParticleSystem->pushToSystemAffectors(ExampleGeometryCollisionParticleSystemAffector);


        //Smoke
        RateParticleGeneratorRecPtr SmokeGenerator = RateParticleGenerator::create();
        //Attach the function objects to the Generator
        Distribution3DRefPtr SmokePositionDistribution = createSmokePositionDistribution();
        SmokeGenerator->setPositionDistribution(SmokePositionDistribution);
        SmokeGenerator->setLifespanDistribution(createSmokeLifespanDistribution());
        SmokeGenerator->setGenerationRate(50.0);
        SmokeGenerator->setVelocityDistribution(createSmokeVelocityDistribution());
        //Attach the function objects the Affectors
        AgeFadeParticleAffectorRecPtr SmokeAgeFadeParticleAffector = AgeFadeParticleAffector::create();
        SmokeAgeFadeParticleAffector->setFadeInTime(2.0f);
        SmokeAgeFadeParticleAffector->setFadeOutTime(5.0f);
        SmokeAgeFadeParticleAffector->setStartAlpha(0.0f);
        SmokeAgeFadeParticleAffector->setFadeToAlpha(0.2f);
        SmokeAgeFadeParticleAffector->setEndAlpha(0.0f);    

        AgeSizeParticleAffectorRecPtr SmokeAgeSizeParticleAffector = AgeSizeParticleAffector::create();
        //ages
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.1);
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.2);
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.3);
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.5);
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.7);
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.8);
        SmokeAgeSizeParticleAffector->editMFAges()->push_back(1.0);

        //sizes
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(0.5,0.5,0.5));
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(1.0,1.0,1.0));
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.0,2.0,2.0));
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(3.0,3.0,3.0));
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(4.0,4.0,4.0));
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(5.0,5.0,5.0));
        SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(6.5,6.5,6.5));

        ParticleSystemCoreRefPtr SmokeParticleNodeCore = ParticleSystemCore::create();
        SmokeParticleNodeCore->setSystem(SmokeParticleSystem);
        SmokeParticleNodeCore->setDrawer(SmokeParticleSystemDrawer);
        SmokeParticleNodeCore->setMaterial(PSSmokeMaterial);

        NodeRefPtr SmokeParticleNode = Node::create();
        SmokeParticleNode->setCore(SmokeParticleNodeCore);
        //end/////////////////////

        //Shrapnel
        BurstParticleGeneratorRecPtr ShrapnelBurstGenerator = BurstParticleGenerator::create();
        NodeRefPtr ShrapnelParticlePrototypeNode = SceneFileHandler::the()->read("Data/Shrapnel.obj");

        NodeParticleSystemCoreRefPtr ShrapnelParticleNodeCore = NodeParticleSystemCore::create();
        ShrapnelParticleNodeCore->setSystem(ShrapnelParticleSystem);
        ShrapnelParticleNodeCore->setPrototypeNode(ShrapnelParticlePrototypeNode);

        //Attach the function objects to the Generator
        Distribution3DRefPtr ShrapnelPositionDistribution = createShrapnelPositionDistribution();
        ShrapnelBurstGenerator->setPositionDistribution(ShrapnelPositionDistribution);
        ShrapnelBurstGenerator->setLifespanDistribution(createLifespanDistribution());
        ShrapnelBurstGenerator->setBurstAmount(50.0);
        ShrapnelBurstGenerator->setVelocityDistribution(createShrapnelVelocityDistribution());
        ShrapnelBurstGenerator->setAccelerationDistribution(createShrapnelAccelerationDistribution());

        NodeRefPtr ShrapnelParticleNode = Node::create();
        ShrapnelParticleNode->setCore(ShrapnelParticleNodeCore);
        //end/////////////////////

        //fireball
        BurstParticleGeneratorRecPtr FireballGenerator = BurstParticleGenerator::create();
        NodeRefPtr FireballParticlePrototypeNode = SceneFileHandler::the()->read("Data/bubble.obj");

        NodeParticleSystemCoreRefPtr FireballParticleNodeCore = NodeParticleSystemCore::create();
        FireballParticleNodeCore->setSystem(FireballParticleSystem);
        FireballParticleNodeCore->setPrototypeNode(FireballParticlePrototypeNode);
        //Attach the function objects to the Generator
        Distribution3DRefPtr FireballPositionDistribution = createFireballPositionDistribution();
        FireballGenerator->setPositionDistribution(FireballPositionDistribution);
        FireballGenerator->setLifespanDistribution(createFireballLifespanDistribution());
        FireballGenerator->setBurstAmount(100.0);
        FireballGenerator->setVelocityDistribution(createFireballVelocityDistribution());
        FireballGenerator->setAccelerationDistribution(createFireballAccelerationDistribution());
        //Attach the function objects the Affectors
        AgeSizeParticleAffectorRecPtr FireballAgeSizeParticleAffector = AgeSizeParticleAffector::create();
        //ages
        FireballAgeSizeParticleAffector->editMFAges()->push_back(0.1);
        FireballAgeSizeParticleAffector->editMFAges()->push_back(0.2);
        FireballAgeSizeParticleAffector->editMFAges()->push_back(0.3);
        FireballAgeSizeParticleAffector->editMFAges()->push_back(0.5);
        FireballAgeSizeParticleAffector->editMFAges()->push_back(0.7);
        FireballAgeSizeParticleAffector->editMFAges()->push_back(0.8);
        FireballAgeSizeParticleAffector->editMFAges()->push_back(1.0);

        //sizes
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.0,2.0,2.0));
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.3,2.3,2.3));
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.5,2.5,2.5));
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(3.0,3.0,3.0));
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(4.0,4.0,4.0));
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(5.0,5.0,5.0));
        FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(6.5,6.5,6.5));

        NodeRefPtr FireballParticleNode = Node::create();
        FireballParticleNode->setCore(FireballParticleNodeCore);
        //end/////////////////////

        //Attach the Affector to the Smoke Particle System
        SmokeParticleSystem->pushToAffectors(SmokeAgeFadeParticleAffector);
        SmokeParticleSystem->pushToAffectors(SmokeAgeSizeParticleAffector);

        //Attach the Affector to the fireball Particle System
        FireballParticleSystem->pushToAffectors(FireballAgeSizeParticleAffector);

        // Make Main Scene Node 
        NodeRefPtr scene = Node::create();
        scene->setCore(Group::create());
        scene->addChild(RocketParticleNode);
        scene->addChild(SmokeParticleNode);
        scene->addChild(ShrapnelParticleNode);
        scene->addChild(FireballParticleNode);
        scene->addChild(EnvironmentNode);

        RocketParticleSystem->connectParticleKilled(boost::bind(particleKilled, _1,
                                                                ShrapnelParticleSystem.get(),
                                                                ShrapnelBurstGenerator.get(),
                                                                SmokeParticleSystem.get(),
                                                                SmokeGenerator.get(),
                                                                FireballParticleSystem.get(),
                                                                FireballGenerator.get()));

        TutorialWindow->connectMousePressed(boost::bind(mousePressed, _1,
                                                        &sceneManager,
                                                        RocketParticleSystem.get()));

        sceneManager.setRoot(scene);

        //Create the Documentation
        SimpleScreenDoc TheSimpleScreenDoc(&sceneManager, TutorialWindow);

        sceneManager.getNavigator()->set(Pnt3f(0.0,0.0,-10.0), Pnt3f(0.0,0.0,0.0), Vec3f(0.0,1.0,0.0));
        sceneManager.getNavigator()->setMotionFactor(1.0f);
        sceneManager.getCamera()->setNear(0.1f);
        sceneManager.getCamera()->setFar(1000.0f);


        //Open Window
        Vec2f WinSize(TutorialWindow->getDesktopSize() * 0.85f);
        Pnt2f WinPos((TutorialWindow->getDesktopSize() - WinSize) *0.5);
        TutorialWindow->openWindow(WinPos,
                                   WinSize,
                                   "20RocketLauncher");

        //Enter main Loop
        TutorialWindow->mainLoop();

    }
    osgExit();

    return 0;
}
int main(int argc, char **argv)
{
    // OSG init
    osgInit(argc,argv);

    // Set up Window
    TutorialWindow = createNativeWindow();
    TutorialWindow->initWindow();

    TutorialWindow->setDisplayCallback(display);
    TutorialWindow->setReshapeCallback(reshape);

    TutorialKeyListener TheKeyListener;
    TutorialWindow->addKeyListener(&TheKeyListener);
    TutorialMouseListener TheTutorialMouseListener;
    TutorialMouseMotionListener TheTutorialMouseMotionListener;
    TutorialWindow->addMouseListener(&TheTutorialMouseListener);
    TutorialWindow->addMouseMotionListener(&TheTutorialMouseMotionListener);

    // Create the SimpleSceneManager helper
    mgr = new SimpleSceneManager;

    // Tell the Manager what to manage
    mgr->setWindow(TutorialWindow);

    //Particle System Material
    //point material
    PointChunkRefPtr PSPointChunk = PointChunk::create();
    PSPointChunk->setSize(5.0f);
    PSPointChunk->setSmooth(true);
    BlendChunkRefPtr PSBlendChunk = BlendChunk::create();
    PSBlendChunk->setSrcFactor(GL_SRC_ALPHA);
    PSBlendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);

    MaterialChunkRefPtr PSMaterialChunkChunk = MaterialChunk::create();
    PSMaterialChunkChunk->setAmbient(Color4f(0.3f,0.3f,0.3f,1.0f));
    PSMaterialChunkChunk->setDiffuse(Color4f(0.7f,0.7f,0.7f,1.0f));
    PSMaterialChunkChunk->setSpecular(Color4f(0.9f,0.9f,0.9f,1.0f));
    PSMaterialChunkChunk->setColorMaterial(GL_AMBIENT_AND_DIFFUSE);

    ChunkMaterialRefPtr PSPointMaterial = ChunkMaterial::create();
    PSPointMaterial->addChunk(PSPointChunk);
    PSPointMaterial->addChunk(PSMaterialChunkChunk);
    PSPointMaterial->addChunk(PSBlendChunk);

    //smoke material
    TextureObjChunkRefPtr QuadTextureObjChunk = TextureObjChunk::create();
    ImageRefPtr LoadedImage = ImageFileHandler::the()->read("Data/Checker.jpg");    
    QuadTextureObjChunk->setImage(LoadedImage);

    TextureEnvChunkRefPtr QuadTextureEnvChunk = TextureEnvChunk::create();
    QuadTextureEnvChunk->setEnvMode(GL_MODULATE);

    MaterialChunkRefPtr PSMaterialChunk = MaterialChunk::create();
    PSMaterialChunk->setAmbient(Color4f(0.3f,0.3f,0.3f,1.0f));
    PSMaterialChunk->setDiffuse(Color4f(0.7f,0.7f,0.7f,1.0f));
    PSMaterialChunk->setSpecular(Color4f(0.9f,0.9f,0.9f,1.0f));
    PSMaterialChunk->setColorMaterial(GL_AMBIENT_AND_DIFFUSE);

    ChunkMaterialRefPtr PSSmokeMaterial = ChunkMaterial::create();
    PSSmokeMaterial->addChunk(QuadTextureObjChunk);
    PSSmokeMaterial->addChunk(PSMaterialChunk);
    PSSmokeMaterial->addChunk(PSMaterialChunk);
    PSSmokeMaterial->addChunk(QuadTextureEnvChunk);


    //Particle System
    //Rocket
    RocketParticleSystem = OSG::ParticleSystem::create();
    RocketParticleSystem->attachUpdateListener(TutorialWindow);

    TutorialRocketParticleSystemListener TheRocketListener;
    RocketParticleSystem->addParticleSystemListener(&TheRocketListener);

    //smoke
    SmokeParticleSystem = OSG::ParticleSystem::create();
    SmokeParticleSystem->attachUpdateListener(TutorialWindow);
    //Shrapnel
    ShrapnelParticleSystem = OSG::ParticleSystem::create();
    ShrapnelParticleSystem->attachUpdateListener(TutorialWindow);
    //Fireball
    FireballParticleSystem = OSG::ParticleSystem::create();
    FireballParticleSystem->attachUpdateListener(TutorialWindow);



    //Particle System Drawer
    //Rocket does not have a drawer because it is being attached to a special node core
    //Smoke
    SmokeParticleSystemDrawer = OSG::QuadParticleSystemDrawer::create();
    //SmokeParticleSystemDrawer->setQuadSizeScaling(Vec2f(0.5f,0.5f));
    //Shrapnel
    ExampleShrapnelParticleSystemDrawer = OSG::PointParticleSystemDrawer::create();
    ExampleShrapnelParticleSystemDrawer->setForcePerParticleSizing(true);
    //Fireball
    ExampleFireballParticleSystemDrawer = OSG::PointParticleSystemDrawer::create();
    ExampleFireballParticleSystemDrawer->setForcePerParticleSizing(true);



    //Particle System Node
    //collision node
    //NodeRefPtr EnvironmentNode = makeSphere(2,4.0f);

    Matrix EnvironmentTransformation;
    EnvironmentTransformation.setScale(0.1f);

    TransformRefPtr EnvironmentTransformCore = Transform::create();
    EnvironmentTransformCore->setMatrix(EnvironmentTransformation);

    NodeRefPtr EnvironmentNode = Node::create();
    EnvironmentNode->setCore(EnvironmentTransformCore);
    //EnvironmentNode->addChild(SceneFileHandler::the()->read("Data/Chloroplast.osb"));
    EnvironmentNode->addChild(SceneFileHandler::the()->read("Data/house.obj"));

    //NodeRefPtr ParticlePrototypeNode = makeTorus(1.0,4.0,16,16);
    NodeRefPtr RocketParticlePrototypeNode = SceneFileHandler::the()->read("Data/rocket.obj");
    if(RocketParticlePrototypeNode == NULL)
    {
        RocketParticlePrototypeNode = makeTorus(.5, 2, 16, 16);
    }

    NodeParticleSystemCoreRefPtr RocketParticleNodeCore = OSG::NodeParticleSystemCore::create();
    RocketParticleNodeCore->setSystem(RocketParticleSystem);
    RocketParticleNodeCore->setPrototypeNode(RocketParticlePrototypeNode);
    RocketParticleNodeCore->setNormalSource(NodeParticleSystemCore::NORMAL_VELOCITY);
    RocketParticleNodeCore->setUpSource(NodeParticleSystemCore::UP_PARTICLE_NORMAL);
    RocketParticleNodeCore->setUp(Vec3f(0.0f,1.0f,0.0f));

    //Geometry Collision Affector
    GeometryCollisionParticleSystemAffectorRefPtr ExampleGeometryCollisionParticleSystemAffector = GeometryCollisionParticleSystemAffector::create();
    ExampleGeometryCollisionParticleSystemAffector->setCollisionNode(EnvironmentNode);

    TutorialParticleCollisionListener TheCollisionListener;
    ExampleGeometryCollisionParticleSystemAffector->addParticleGeometryCollisionListener(&TheCollisionListener);


    NodeRefPtr RocketParticleNode = OSG::Node::create();
    RocketParticleNode->setCore(RocketParticleNodeCore);

    //Attach the Affector to the Rocket Particle System
    //RocketParticleSystem->pushToAffectors();
    RocketParticleSystem->pushToSystemAffectors(ExampleGeometryCollisionParticleSystemAffector);


    //Smoke
    SmokeGenerator = OSG::RateParticleGenerator::create();
    //Attach the function objects to the Generator
    SmokePositionDistribution = createSmokePositionDistribution();
    SmokeGenerator->setPositionDistribution(SmokePositionDistribution);
    SmokeGenerator->setLifespanDistribution(createSmokeLifespanDistribution());
    SmokeGenerator->setGenerationRate(50.0);
    SmokeGenerator->setVelocityDistribution(createSmokeVelocityDistribution());
    //Attach the function objects the Affectors
    SmokeAgeFadeParticleAffector = OSG::AgeFadeParticleAffector::create();
    SmokeAgeFadeParticleAffector->setFadeInTime(2.0f);
    SmokeAgeFadeParticleAffector->setFadeOutTime(5.0f);
    SmokeAgeFadeParticleAffector->setStartAlpha(0.0f);
    SmokeAgeFadeParticleAffector->setFadeToAlpha(0.2f);
    SmokeAgeFadeParticleAffector->setEndAlpha(0.0f);	

    SmokeAgeSizeParticleAffector = OSG::AgeSizeParticleAffector::create();
    //ages
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.1);
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.2);
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.3);
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.5);
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.7);
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(0.8);
    SmokeAgeSizeParticleAffector->editMFAges()->push_back(1.0);

    //sizes
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(0.5,0.5,0.5));
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(1.0,1.0,1.0));
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.0,2.0,2.0));
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(3.0,3.0,3.0));
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(4.0,4.0,4.0));
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(5.0,5.0,5.0));
    SmokeAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(6.5,6.5,6.5));

    ParticleSystemCoreRefPtr SmokeParticleNodeCore = OSG::ParticleSystemCore::create();
    SmokeParticleNodeCore->setSystem(SmokeParticleSystem);
    SmokeParticleNodeCore->setDrawer(SmokeParticleSystemDrawer);
    SmokeParticleNodeCore->setMaterial(PSSmokeMaterial);

    NodeRefPtr SmokeParticleNode = OSG::Node::create();
    SmokeParticleNode->setCore(SmokeParticleNodeCore);
    //end/////////////////////

    //Shrapnel
    ShrapnelBurstGenerator = OSG::BurstParticleGenerator::create();
    NodeRefPtr ShrapnelParticlePrototypeNode = SceneFileHandler::the()->read("Data/Shrapnel.obj");

    NodeParticleSystemCoreRefPtr ShrapnelParticleNodeCore = OSG::NodeParticleSystemCore::create();
    ShrapnelParticleNodeCore->setSystem(ShrapnelParticleSystem);
    ShrapnelParticleNodeCore->setPrototypeNode(ShrapnelParticlePrototypeNode);

    //Attach the function objects to the Generator
    ShrapnelPositionDistribution = createShrapnelPositionDistribution();
    ShrapnelBurstGenerator->setPositionDistribution(ShrapnelPositionDistribution);
    ShrapnelBurstGenerator->setLifespanDistribution(createLifespanDistribution());
    ShrapnelBurstGenerator->setBurstAmount(50.0);
    ShrapnelBurstGenerator->setVelocityDistribution(createShrapnelVelocityDistribution());
    ShrapnelBurstGenerator->setAccelerationDistribution(createShrapnelAccelerationDistribution());

    NodeRefPtr ShrapnelParticleNode = OSG::Node::create();
    ShrapnelParticleNode->setCore(ShrapnelParticleNodeCore);
    //end/////////////////////

    //fireball
    FireballGenerator = OSG::BurstParticleGenerator::create();
    NodeRefPtr FireballParticlePrototypeNode = SceneFileHandler::the()->read("Data/bubble.obj");

    NodeParticleSystemCoreRefPtr FireballParticleNodeCore = OSG::NodeParticleSystemCore::create();
    FireballParticleNodeCore->setSystem(FireballParticleSystem);
    FireballParticleNodeCore->setPrototypeNode(FireballParticlePrototypeNode);
    //Attach the function objects to the Generator
    FireballPositionDistribution = createFireballPositionDistribution();
    FireballGenerator->setPositionDistribution(FireballPositionDistribution);
    FireballGenerator->setLifespanDistribution(createFireballLifespanDistribution());
    FireballGenerator->setBurstAmount(100.0);
    FireballGenerator->setVelocityDistribution(createFireballVelocityDistribution());
    FireballGenerator->setAccelerationDistribution(createFireballAccelerationDistribution());
    //Attach the function objects the Affectors
    FireballAgeSizeParticleAffector = OSG::AgeSizeParticleAffector::create();
    //ages
    FireballAgeSizeParticleAffector->editMFAges()->push_back(0.1);
    FireballAgeSizeParticleAffector->editMFAges()->push_back(0.2);
    FireballAgeSizeParticleAffector->editMFAges()->push_back(0.3);
    FireballAgeSizeParticleAffector->editMFAges()->push_back(0.5);
    FireballAgeSizeParticleAffector->editMFAges()->push_back(0.7);
    FireballAgeSizeParticleAffector->editMFAges()->push_back(0.8);
    FireballAgeSizeParticleAffector->editMFAges()->push_back(1.0);

    //sizes
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.0,2.0,2.0));
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.3,2.3,2.3));
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(2.5,2.5,2.5));
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(3.0,3.0,3.0));
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(4.0,4.0,4.0));
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(5.0,5.0,5.0));
    FireballAgeSizeParticleAffector->editMFSizes()->push_back(Vec3f(6.5,6.5,6.5));

    NodeRefPtr FireballParticleNode = OSG::Node::create();
    FireballParticleNode->setCore(FireballParticleNodeCore);
    //end/////////////////////


    // Make Main Scene Node 
    NodeRefPtr scene = OSG::Node::create();
    scene->setCore(OSG::Group::create());
    scene->addChild(RocketParticleNode);
    scene->addChild(SmokeParticleNode);
    scene->addChild(ShrapnelParticleNode);
    scene->addChild(FireballParticleNode);
    scene->addChild(EnvironmentNode);

    mgr->setRoot(scene);

    mgr->getNavigator()->set(Pnt3f(0.0,0.0,0.0), Pnt3f(0.0,0.0,-1.0), Vec3f(0.0,1.0,0.0));
    mgr->getNavigator()->setMotionFactor(1.0f);
    mgr->getCamera()->setNear(0.1f);
    mgr->getCamera()->setFar(1000.0f);


    //Open Window
    Vec2f WinSize(TutorialWindow->getDesktopSize() * 0.85f);
    Pnt2f WinPos((TutorialWindow->getDesktopSize() - WinSize) *0.5);
    TutorialWindow->openWindow(WinPos,
                               WinSize,
                               "10RocketLauncher");

    //Enter main Loop
    TutorialWindow->mainLoop();

    osgExit();

    return 0;
}