//see
//http://faculty.nps.edu/jasullivan/osgTutorials/osgParticleHelper.htm
//http://faculty.nps.edu/jasullivan/osgTutorials/Download/psHelper.cpp
//Author: jasulli...@nps.edu
#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( 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 (&searchNode) )
foundGeode = g;
else
traverse(searchNode);
}
osg::ref_ptr getGeode() {return foundGeode.get();}
protected:
osg::ref_ptr foundGeode;
};
class particleSystemHelper : public osg::Group
{
public:
particleSystemHelper(osg::Group* psGroup) : osg::Group(*psGroup)
{
osg::ref_ptr fg = new findGeodeVisitor();
accept(*fg.get());
osg::ref_ptr 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 fg = new findGeodeVisitor();
psGroup->accept(*fg.get());
osg::ref_ptr psGeode = fg->getGeode().get();
psGeodeXForm->addChild(psGeode.get());
psGroup->removeChild( psGroup->getChildIndex(psGeode.get()) );
}
protected:
osg::ref_ptr psGeodeXForm;
};
#endif
//конструктор
BaseParticleObject::BaseParticleObject(std::string Name,
osg::ref_ptr _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(emitter->getCounter());
rrc->setRateRange(20, 30);// generate 20 to 30 particles per second
rrc->setClamp (true);
osg::ref_ptr 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
:
> 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 mov