//see
//http://faculty.nps.edu/jasullivan/osgTutorials/osgParticleHelper.htm
//http://faculty.nps.edu/jasullivan/osgTutorials/Download/psHelper.cpp
//Author: [email protected]

#ifndef PARTICLEHELPER
#define PARTICLEHELPER

class psGeodeTransform : public osg::MatrixTransform
{
public:
   class psGeodeTransformCallback : public osg::NodeCallback
   {
      virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
      {
         if ( psGeodeTransform* ps = dynamic_cast<psGeodeTransform*>( node ) )
         {
            osg::NodePath& fullNodePath = nv->getNodePath();
            fullNodePath.pop_back();

            osg::Matrix localCoordMat = osg::computeLocalToWorld(
fullNodePath );
            osg::Matrix inverseOfAccum = osg::Matrix::inverse( localCoordMat );

            ps->setMatrix( inverseOfAccum );
         }
                 traverse(node, nv);

      }
   };

   psGeodeTransform() {setUpdateCallback( new psGeodeTransformCallback() );}

};

class findGeodeVisitor : public osg::NodeVisitor
{
public:
   findGeodeVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
   {
      foundGeode = NULL;
   }
   virtual void apply(osg::Node &searchNode)
   {
      if (osg::Geode* g = dynamic_cast<osg::Geode*> (&searchNode) )
         foundGeode = g;
      else
         traverse(searchNode);
   }
   osg::ref_ptr<osg::Geode> getGeode() {return foundGeode.get();}
protected:
   osg::ref_ptr<osg::Geode> foundGeode;
};

class particleSystemHelper : public osg::Group
{
public:
   particleSystemHelper(osg::Group* psGroup) : osg::Group(*psGroup)
   {
      osg::ref_ptr<findGeodeVisitor> fg = new findGeodeVisitor();
      accept(*fg.get());
      osg::ref_ptr<osg::Geode> psGeode = fg->getGeode().get();
      psGeodeXForm = new psGeodeTransform();
      psGeodeXForm->addChild (psGeode.get());
      replaceChild(psGeode.get(),psGeodeXForm.get());
   }
   void addEffect(osg::Group* psGroup)
   {
      this->addChild(psGroup);
      osg::ref_ptr<findGeodeVisitor> fg = new findGeodeVisitor();
      psGroup->accept(*fg.get());
      osg::ref_ptr<osg::Geode> psGeode = fg->getGeode().get();
      psGeodeXForm->addChild(psGeode.get());
      psGroup->removeChild( psGroup->getChildIndex(psGeode.get()) );
   }
protected:
   osg::ref_ptr<psGeodeTransform> psGeodeXForm;
};


#endif


//конструктор
BaseParticleObject::BaseParticleObject(std::string Name,
osg::ref_ptr<osg::Group> _root)
{
        //Запоминаем ссылку на root
        root = _root;

        //задаем имя
        setName (Name);

        //Particle
        ptemplate = new osgParticle::Particle();
        ptemplate->setLifeTime(3);        // 3 seconds of life
        ptemplate->setSizeRange(osgParticle::rangef(0.75f, 3.0f));
    ptemplate->setAlphaRange(osgParticle::rangef(0.0f, 1.5f));
    ptemplate->setColorRange(osgParticle::rangev4(
        osg::Vec4(1, 0.5f, 0.3f, 1.5f),
        osg::Vec4(0, 0.0f, 0.0f, 0.0f)));
        // these are physical properties of the particle
    ptemplate->setRadius(0.05f);    // 5 cm wide particles
    ptemplate->setMass(0.05f);    // 50 g heavy

        //ParticleSystem
        ps = new osgParticle::ParticleSystem;
        //ps->setFreezeOnCull(false);
        ps->setDefaultAttributes("", false, false);
        // assign the particle template to the system.
    ps->setDefaultParticleTemplate(*ptemplate);

        //emitter
    emitter = new osgParticle::ModularEmitter;
        
        //По замечаниям Ассель...
        //Углы вылете частиц
        //RadialShooter
        shooter = new osgParticle::RadialShooter();
        emitter->setShooter (shooter.get());
        float k =64.0f;
        float k2 =4.0f;
        shooter->setPhiRange (-0.05f*k,0.05f*k);
        shooter->setThetaRange (-0.05f*k2, 0.05f*k2);
        
        //SectorPlacer
        placer = new osgParticle::SectorPlacer();
        placer->setRadiusRange (0.1f,0.2f);
        emitter->setPlacer(placer.get());
        
    emitter->setParticleSystem(ps.get());
    rrc = static_cast<osgParticle::RandomRateCounter *>(emitter->getCounter());
    rrc->setRateRange(20, 30);    // generate 20 to 30 particles per second
    rrc->setClamp (true);

        osg::ref_ptr <osg::Geode> geode = new osg::Geode;
    geode->addDrawable(ps.get());
        
        //В этой матрице эмиттер (должен быть строго в Root)
        otherMatrix  = new osg::MatrixTransform();
        otherMatrix->setName (Name + "_emitter");
        otherMatrix->addChild (geode);
        
        psu = new osgParticle::ParticleSystemUpdater;
    psu->addParticleSystem(ps.get());

        root->addChild (otherMatrix);
        addChild(psu.get());
        addChild(emitter.get());

        //созданные обертки (для возможности работать с текстом командами
типа RSetPosition..)
        root->addChild(this);
}



2010/9/20 Tueller, Shayne R Civ USAF AFMC 519 SMXS/MXDEC
<[email protected]>:
> All,
>
>
>
> I have a need to attach osgParticle effects on a moving object (i.e smoke
> and fire trail from a moving missile). I've looked at the
> osgparticleeffects.cpp example in where they attach these effects based off
> a hit node from the pick event to see how I might do this. Unfortunately I
> need to invoke the effects from the moving object's UpdateCallback event
> rather than from a pick event. I have tried several things to get this to
> work without success.
>
>
>
> As anyone else been able to something similar to what I'm trying to
> accomplish? I would appreciate any suggestions anyone might have on how to
> get this to work...
>
>
>
> Thanks,
>
> -Shayne
>
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>



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

Reply via email to