X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fparticles.cxx;h=a7fee2ded106e3dbb4c69bd8570bd6f930ddd6f6;hb=32a6bd78d8bf143f40922f1a0bc7a88ea7706a7d;hp=ca4cdb6e3071a93fd3081f15a3e577bb1d05f555;hpb=223aa0ccd57a9dd706b8debf1c3ca17e96cc14a5;p=simgear.git diff --git a/simgear/scene/model/particles.cxx b/simgear/scene/model/particles.cxx index ca4cdb6e..a7fee2de 100644 --- a/simgear/scene/model/particles.cxx +++ b/simgear/scene/model/particles.cxx @@ -1,6 +1,6 @@ // particles.cxx - classes to manage particles -// started in 2008 by Tiago Gusmão, using animation.hxx as reference -// Copyright (C) 2008 Tiago Gusmão +// started in 2008 by Tiago Gusm�o, using animation.hxx as reference +// Copyright (C) 2008 Tiago Gusm�o // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -32,10 +34,13 @@ #include #include #include +#include #include #include +#include #include +#include #include "particles.hxx" @@ -43,28 +48,42 @@ namespace simgear { void GlobalParticleCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) { + enabled = !enabledNode || enabledNode->getBoolValue(); + if (!enabled) + return; SGQuatd q = SGQuatd::fromLonLatDeg(modelRoot->getFloatValue("/position/longitude-deg",0), modelRoot->getFloatValue("/position/latitude-deg",0)); - osg::Matrix om(q.osg()); + osg::Matrix om(toOsg(q)); osg::Vec3 v(0,0,9.81); gravity = om.preMult(v); - - osg::Vec3 w(-modelRoot->getFloatValue("/environment/wind-from-north-fps",0) * SG_FEET_TO_METER, - -modelRoot->getFloatValue("/environment/wind-from-east-fps",0) * SG_FEET_TO_METER, 0); + // NOTE: THIS WIND COMPUTATION DOESN'T SEEM TO AFFECT PARTICLES + const osg::Vec3& zUpWind = Particles::getWindVector(); + osg::Vec3 w(zUpWind.y(), zUpWind.x(), -zUpWind.z()); wind = om.preMult(w); - //SG_LOG(SG_GENERAL, SG_ALERT, "wind vector:"< Particles::commonRoot; osg::ref_ptr Particles::psu = new osgParticle::ParticleSystemUpdater; -osg::ref_ptr Particles::commonGeode = new osg::Geode;; +osg::ref_ptr Particles::commonGeode = new osg::Geode; +osg::Vec3 Particles::_wind; +bool Particles::_frozen = false; + +Particles::Particles() : + useGravity(false), + useWind(false) +{ +} template class PointerGuard{ @@ -81,9 +100,38 @@ private: Object* _ptr; }; +osg::Group* Particles::getCommonRoot() +{ + if(!commonRoot.valid()) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Particle common root called!\n"); + commonRoot = new osg::Group; + commonRoot.get()->setName("common particle system root"); + commonGeode.get()->setName("common particle system geode"); + commonRoot.get()->addChild(commonGeode.get()); + commonRoot.get()->addChild(psu.get()); + commonRoot->setNodeMask( ~simgear::MODELLIGHT_BIT ); + } + return commonRoot.get(); +} + +void transformParticles(osgParticle::ParticleSystem* particleSys, + const osg::Matrix& mat) +{ + const int numParticles = particleSys->numParticles(); + if (particleSys->areAllParticlesDead()) + return; + for (int i = 0; i < numParticles; ++i) { + osgParticle::Particle* P = particleSys->getParticle(i); + if (!P->isAlive()) + continue; + P->transformPositionVelocity(mat); + } +} + osg::Group * Particles::appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, - const osgDB::ReaderWriter::Options* + const osgDB::Options* options) { SG_LOG(SG_GENERAL, SG_DEBUG, "Setting up a particle system!\n"); @@ -140,9 +188,12 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode, osg::Geode* g = new osg::Geode; align->addChild(g); g->addDrawable(particleSys); - emitter->setReferenceFrame(osgParticle::Emitter::ABSOLUTE_RF); } else { - getCommonGeode()->addDrawable(particleSys); + callback()->particleFrame = new osg::MatrixTransform(); + osg::Geode* g = new osg::Geode; + g->addDrawable(particleSys); + callback()->particleFrame->addChild(g); + getCommonRoot()->addChild(callback()->particleFrame.get()); } std::string textureFile; if (configNode->hasValue("texture")) { @@ -366,14 +417,14 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode, osg::Vec4(r2,g2,b2,a2))); float startsize=1, endsize=0.1f; - const SGPropertyNode* startsizenode = particlenode->getChild("start/size"); + const SGPropertyNode* startsizenode = particlenode->getNode("start/size"); if (startsizenode) { if (startsizenode->hasValue("value")) startsize = startsizenode->getFloatValue("value",0); else callback()->setupStartSizeData(startsizenode, modelRoot); } - const SGPropertyNode* endsizenode = particlenode->getChild("end/size"); + const SGPropertyNode* endsizenode = particlenode->getNode("end/size"); if (endsizenode) { if (endsizenode->hasValue("value")) endsize = endsizenode->getFloatValue("value",0); @@ -415,10 +466,7 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode, program->setFluidToWater(); if (programnode->getBoolValue("gravity", true)) { - if (attach == "world") - callback()->setupProgramGravity(true); - else - program->setToGravity(); + program->setToGravity(); } else program->setAcceleration(osg::Vec3(0,0,0)); @@ -447,7 +495,9 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode, void Particles::operator()(osg::Node* node, osg::NodeVisitor* nv) { //SG_LOG(SG_GENERAL, SG_ALERT, "callback!\n"); + this->particleSys->setFrozen(_frozen); + using namespace osg; if (shooterValue) shooter->setInitialSpeedRange(shooterValue->getValue(), (shooterValue->getValue() @@ -458,7 +508,7 @@ void Particles::operator()(osg::Node* node, osg::NodeVisitor* nv) else if (counterCond) counter->setRateRange(counterStaticValue, counterStaticValue + counterStaticExtraRange); - if (counterCond && !counterCond->test()) + if (!GlobalParticleCallback::getEnabled() || (counterCond && !counterCond->test())) counter->setRateRange(0, 0); bool colorchange=false; for (int i = 0; i < 8; ++i) { @@ -468,7 +518,7 @@ void Particles::operator()(osg::Node* node, osg::NodeVisitor* nv) } } if (colorchange) - particleSys->getDefaultParticleTemplate().setColorRange(osgParticle::rangev4( osg::Vec4(staticColorComponents[0], staticColorComponents[1], staticColorComponents[2], staticColorComponents[3]), osg::Vec4(staticColorComponents[4], staticColorComponents[5], staticColorComponents[6], staticColorComponents[7]))); + particleSys->getDefaultParticleTemplate().setColorRange(osgParticle::rangev4( Vec4(staticColorComponents[0], staticColorComponents[1], staticColorComponents[2], staticColorComponents[3]), Vec4(staticColorComponents[4], staticColorComponents[5], staticColorComponents[6], staticColorComponents[7]))); if (startSizeValue) startSize = startSizeValue->getValue(); if (endSizeValue) @@ -477,11 +527,28 @@ void Particles::operator()(osg::Node* node, osg::NodeVisitor* nv) particleSys->getDefaultParticleTemplate().setSizeRange(osgParticle::rangef(startSize, endSize)); if (lifeValue) particleSys->getDefaultParticleTemplate().setLifeTime(lifeValue->getValue()); - if (program) { - if (useGravity) - program->setAcceleration(GlobalParticleCallback::getGravityVector()); - if (useWind) - program->setWind(GlobalParticleCallback::getWindVector()); + + if (particleFrame.valid()) { + MatrixList mlist = node->getWorldMatrices(); + if (!mlist.empty()) { + const Matrix& particleMat = particleFrame->getMatrix(); + Vec3d emitOrigin(mlist[0](3, 0), mlist[0](3, 1), mlist[0](3, 2)); + Vec3d displace + = emitOrigin - Vec3d(particleMat(3, 0), particleMat(3, 1), + particleMat(3, 2)); + if (displace * displace > 10000.0 * 10000.0) { + // Make new frame for particle system, coincident with + // the emitter frame, but oriented with local Z. + SGGeod geod = SGGeod::fromCart(toSG(emitOrigin)); + Matrix newParticleMat = makeZUpFrame(geod); + Matrix changeParticleFrame + = particleMat * Matrix::inverse(newParticleMat); + particleFrame->setMatrix(newParticleMat); + transformParticles(particleSys.get(), changeParticleFrame); + } + } } + if (program.valid() && useWind) + program->setWind(_wind); } } // namespace simgear