]> git.mxchange.org Git - simgear.git/commitdiff
Keep non-local particles in a Z-up frame that is periodically moved.
authortimoore <timoore>
Thu, 11 Sep 2008 10:19:05 +0000 (10:19 +0000)
committertimoore <timoore>
Thu, 11 Sep 2008 10:19:05 +0000 (10:19 +0000)
This eliminates jitter and other rendering problems.
For the moment this is dependent on an osg fix.

Also, don't read wind properties from FlightGear; provide a mechanism
for fg to set the wind.

simgear/scene/model/SGReaderWriterXML.cxx
simgear/scene/model/particles.cxx
simgear/scene/model/particles.hxx

index 9d6a42c56b26101cdfdbc9806a67954b49b291fe..2d48e7e20e07a582e418c78736a9381dbff06e7b 100644 (file)
@@ -20,6 +20,7 @@
 #  include <simgear_config.h>
 #endif
 
+#include <osg/MatrixTransform>
 #include <osgDB/WriteFile>
 #include <osgDB/Registry>
 #include <osg/Switch>
index 9fdc4bf51a1f3d5c8ab8746d2fb26a827004a67c..0194e960c4ff9a91a712e659efdf04f1758aa840 100644 (file)
@@ -21,6 +21,8 @@
 #  include <simgear_config.h>
 #endif
 
+#include <simgear/math/SGMath.hxx>
+#include <simgear/math/SGGeod.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/props/props_io.hxx>
 #include <osgParticle/SectorPlacer>
 #include <osgParticle/ConstantRateCounter>
 #include <osgParticle/ParticleSystemUpdater>
+#include <osgParticle/ParticleSystem>
 #include <osgParticle/FluidProgram>
 
 #include <osg/Geode>
+#include <osg/Group>
 #include <osg/MatrixTransform>
+#include <osg/Node>
 
 #include "particles.hxx"
 
@@ -49,9 +54,8 @@ void GlobalParticleCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
     osg::Matrix om(q.osg());
     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);
+    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:"<<w[0]<<","<<w[1]<<","<<w[2]<<"\n");
@@ -65,6 +69,13 @@ osg::Vec3 GlobalParticleCallback::wind;
 osg::ref_ptr<osg::Group> Particles::commonRoot;
 osg::ref_ptr<osgParticle::ParticleSystemUpdater> Particles::psu = new osgParticle::ParticleSystemUpdater;
 osg::ref_ptr<osg::Geode> Particles::commonGeode = new osg::Geode;;
+osg::Vec3 Particles::_wind;
+
+Particles::Particles() : 
+    useGravity(false),
+    useWind(false)
+{
+}
 
 template <typename Object>
 class PointerGuard{
@@ -81,6 +92,36 @@ 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());
+    }
+    return commonRoot.get();
+}
+
+// Enable this once particle fix is in OSG.
+// #define OSG_PARTICLE_FIX 1
+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*
@@ -140,9 +181,19 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode,
         osg::Geode* g = new osg::Geode;
         align->addChild(g);
         g->addDrawable(particleSys);
+#ifndef OSG_PARTICLE_FIX
         emitter->setReferenceFrame(osgParticle::Emitter::ABSOLUTE_RF);
+#endif
     } else {
+#ifdef OSG_PARTICLE_FIX
+        callback()->particleFrame = new osg::MatrixTransform();
+        osg::Geode* g = new osg::Geode;
+        g->addDrawable(particleSys);
+        callback()->particleFrame->addChild(g);
+        getCommonRoot()->addChild(callback()->particleFrame.get());
+#else
         getCommonGeode()->addDrawable(particleSys);
+#endif
     }
     std::string textureFile;
     if (configNode->hasValue("texture")) {
@@ -415,10 +466,14 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode,
             program->setFluidToWater();
 
         if (programnode->getBoolValue("gravity", true)) {
+#ifdef OSG_PARTICLE_FIX
+            program->setToGravity();
+#else
             if (attach == "world")
                 callback()->setupProgramGravity(true);
             else
                 program->setToGravity();
+#endif
         } else
             program->setAcceleration(osg::Vec3(0,0,0));
 
@@ -447,7 +502,7 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode,
 void Particles::operator()(osg::Node* node, osg::NodeVisitor* nv)
 {
     //SG_LOG(SG_GENERAL, SG_ALERT, "callback!\n");
-
+    using namespace osg;
     if (shooterValue)
         shooter->setInitialSpeedRange(shooterValue->getValue(),
                                       (shooterValue->getValue()
@@ -468,7 +523,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 +532,36 @@ void Particles::operator()(osg::Node* node, osg::NodeVisitor* nv)
         particleSys->getDefaultParticleTemplate().setSizeRange(osgParticle::rangef(startSize, endSize));
     if (lifeValue)
         particleSys->getDefaultParticleTemplate().setLifeTime(lifeValue->getValue());
+#ifdef OSG_PARTICLE_FIX
+    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(SGVec3d(emitOrigin));
+                Matrix newParticleMat = geod.makeZUpFrame();
+                Matrix changeParticleFrame
+                    = particleMat * Matrix::inverse(newParticleMat);
+                particleFrame->setMatrix(newParticleMat);
+                transformParticles(particleSys.get(), changeParticleFrame);
+            }
+        }
+    }
+    if (program.valid() && useWind)
+        program->setWind(_wind);
+#else
     if (program.valid()) {
         if (useGravity)
             program->setAcceleration(GlobalParticleCallback::getGravityVector());
         if (useWind)
             program->setWind(GlobalParticleCallback::getWindVector());
     }
+#endif
 }
 } // namespace simgear
index 359f6acd4d3c26f7a8a2a4e09495a936c8a981b3..4c9d5053f63bd55038ad14f57ffe0056612aea47 100644 (file)
 #define _SG_PARTICLES_HXX 1
 
 #include <osg/ref_ptr>
-#include <osg/Group>
-#include <osg/Node>
-#include <osg/NodeVisitor>
-#include <osg/Texture2D>
 #include <osgParticle/SmokeTrailEffect>
 #include <osgParticle/Particle>
 #include <osgParticle/ModularEmitter>
-#include <osgParticle/ParticleSystemUpdater>
-#include <osgParticle/ParticleSystem>
-#include <osg/MatrixTransform>
 #include <osgDB/ReaderWriter>
 #include <osgDB/FileNameUtils>
 #include <osgDB/FileUtils>
 #include <osg/Notify>
 #include <osg/Vec3>
 
+namespace osg
+{
+class Group;
+class MatrixTransform;
+class Node;
+class NodeVisitor;
+}
+
+namespace osgParticle
+{
+class ParticleSystem;
+class ParticleSystemUpdater;
+}
 
 #include <simgear/scene/util/SGNodeMasks.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/props/condition.hxx>
 #include <simgear/structure/SGExpression.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/math/SGQuat.hxx>
 #include <simgear/math/SGMatrix.hxx>
 
@@ -90,18 +97,7 @@ private:
 class Particles : public osg::NodeCallback 
 {
 public:
-    Particles() : 
-        shooterValue(NULL),
-        counterValue(NULL),
-        startSizeValue(NULL),
-        endSizeValue(NULL),
-        lifeValue(NULL),
-        counterCond(NULL),
-        useGravity(false),
-        useWind(false)
-    {
-        memset(colorComponents, 0, sizeof(colorComponents));
-    }
+    Particles();
 
     static osg::Group * appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const osgDB::ReaderWriter::Options* options);
 
@@ -229,19 +225,7 @@ public:
         staticColorComponents[7] = a2;
     }
 
-    static osg::Group * 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());
-        }
-        return commonRoot.get();
-    }
+    static osg::Group * getCommonRoot();
 
     static osg::Geode * getCommonGeode()
     {
@@ -253,16 +237,23 @@ public:
         return psu.get();
     }
 
+    /**
+     *  Set and get the wind vector for particles in the
+     * atmosphere. This vector is in the Z-up Y-north frame, and the
+     * magnitude is the velocity in meters per second.
+     */
+    static void setWindVector(const osg::Vec3& wind) { _wind = wind; }
+    static const osg::Vec3& getWindVector() { return _wind; }
 protected:
     float shooterExtraRange;
     float counterExtraRange;
-    SGExpressiond* shooterValue;
-    SGExpressiond* counterValue;
-    SGExpressiond* colorComponents[8];
-    SGExpressiond* startSizeValue;
-    SGExpressiond* endSizeValue;
-    SGExpressiond* lifeValue;
-    SGCondition* counterCond;
+    SGSharedPtr<SGExpressiond> shooterValue;
+    SGSharedPtr<SGExpressiond> counterValue;
+    SGSharedPtr<SGExpressiond> colorComponents[8];
+    SGSharedPtr<SGExpressiond> startSizeValue;
+    SGSharedPtr<SGExpressiond> endSizeValue;
+    SGSharedPtr<SGExpressiond> lifeValue;
+    SGSharedPtr<SGCondition> counterCond;
     float staticColorComponents[8];
     float startSize;
     float endSize;
@@ -272,11 +263,14 @@ protected:
     osg::ref_ptr<osgParticle::RandomRateCounter> counter;
     osg::ref_ptr<osgParticle::ParticleSystem> particleSys;
     osg::ref_ptr<osgParticle::FluidProgram> program;
+    osg::ref_ptr<osg::MatrixTransform> particleFrame;
+    
     bool useGravity;
     bool useWind;
     static osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu;
     static osg::ref_ptr<osg::Group> commonRoot;
     static osg::ref_ptr<osg::Geode> commonGeode;
+    static osg::Vec3 _wind;
 };
 }
 #endif