I've been attempting to use osg particle systems, and I believe I've
encountered either a bug or some undocumented behavior with fluid friction.

Using, for instance, a particle system configured to look smoke-plume-like,
and using a ModularProgram with a FluidFrictionOperator, I am finding that
sometimes the plume appears normally, and sometimes the smoke particles fly
off into space at high velocity in a spiral pattern. I tried a variety of
things to track down the problem; here's what I did, with notes:

- Removed the friction operator:
  The smoke displayed correctly, but of course frictionless.

- Replaced the ModularProgram with a FluidProgram:
  The smoke displayed correctly, with friction.

- Replaced the FluidFrictionOperator::operate code with the calculation from
FluidProgram:
  The smoke displayed correctly, with friction. The FluidProgram's
calculation appears totally different from
  the FluidFrictionOperator's calculation, and uses different variable names
(coeffA/coeffB vs. viscosityCoefficient/densityCoefficient)
  for what looks like the same thing. It's hard to see why.

- Replaced the FluidFrictionOperator::operate code with a quadratic drag
calculation from a physics book:
  The smoke displayed correctly, with friction.

So I am wondering if anyone can enlighten me as to what is going on here.
Why are the FluidProgram and FluidFrictionOperator calculations so
different, what's with the cryptic variable names in FluidFrictionOperator,
and why would one calculation work but not the other?

I'm including the friction calculation I settled on, in case anyone is
curious or would like to point out the many mistakes I'm sure I made.

Thanks for any help.
Max Bandazian

   osg::Vec3 computeQuadraticDrag(osgParticle::Particle* particle, double
dt,
      float viscosityCoefficient, float densityCoefficient, osg::Vec3 wind)
   {
      static const float four_over_three = 4.0/3.0;

      float radius = particle->getRadius();
      float area = osg::PI*radius*radius;
      float volume = area*radius*four_over_three;

      osg::Vec3 vRelativeToFluid(particle->getVelocity() - wind);
      float speedRelativeToFluid = vRelativeToFluid.length();

      osg::Vec3 vDirection(particle->getVelocity());
      vDirection.normalize();

      float dragCoefficient = 6 * osg::PI * viscosityCoefficient * radius;
// Stokes

      osg::Vec3 dragForce = vDirection * -0.5 * densityCoefficient *
         speedRelativeToFluid * speedRelativeToFluid * area;

      return dragForce;
   }

   osg::Vec3 computeWindForce(osgParticle::Particle* particle, double dt,
      float viscosityCoefficient, float densityCoefficient, osg::Vec3 wind)
   {
      static const float four_over_three = 4.0/3.0;

      float radius = particle->getRadius();
      float area = osg::PI*radius*radius;
      float volume = area*radius*four_over_three;

      // Find wind vector minus projection of particle velocity
      osg::Vec3 windNorm(wind);
      windNorm.normalize();
      float windDot = windNorm * particle->getVelocity();
      osg::Vec3 relativeWind = wind * (1 - windDot);

      osg::Vec3 windForce = (relativeWind - particle->getVelocity())
         * densityCoefficient * volume / dt;

      return windForce;
   }

   void MyFluidFrictionOperator::operate(osgParticle::Particle* particle,
double dt)
   {
      osg::Vec3 dragForce = computeQuadraticDrag(particle, dt,
viscosityCoefficient,
         densityCoefficient, _wind);
      osg::Vec3 windForce = computeWindForce(particle, dt,
viscosityCoefficient,
         densityCoefficient, _wind);

      osg::Vec3 acceleration = (dragForce + windForce) *
particle->getMassInv();
      osg::Vec3 velocity = acceleration * dt;

      particle->addVelocity(velocity);
   }
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to