ps_force.h

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #ifndef NL_PS_FORCE_H
00025 #define NL_PS_FORCE_H
00026 
00027 #include "nel/misc/types_nl.h"
00028 #include "nel/3d/ps_located.h"
00029 #include "nel/3d/ps_util.h"
00030 #include "nel/3d/ps_attrib_maker.h"
00031 #include "nel/3d/ps_edit.h"
00032 #include "nel/3d/ps_direction.h"
00033 #include "nel/3d/particle_system.h"
00034 
00035 
00036 namespace NL3D {
00037 
00038 class CPSEmitterInfo;
00039 
00049 class CPSForce : public CPSTargetLocatedBindable
00050 {
00051 public:
00052 
00054     CPSForce();
00055 
00057     uint32              getType(void) const { return PSForce; }
00058 
00059 
00061 
00062     virtual uint32      getPriority(void) const { return 4000; }
00063 
00065     virtual bool        doesProduceBBox(void) const { return false; }
00066 
00070     virtual void        step(TPSProcessPass pass);
00071 
00072 
00074     virtual void        computeForces(CPSLocated &target) = 0;
00075 
00077     virtual void        show() = 0;
00078 
00080     virtual void         serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00081 
00083     virtual bool         isIntegrable(void) const { return false; }
00084 
00086     virtual void         attachTarget(CPSLocated *ptr);
00087 
00089     void                  releaseTargetRsc(CPSLocated *target);
00090 
00091 
00097      virtual void integrate(float date, CPSLocated *src, uint32 startIndex, uint32 numObjects, NLMISC::CVector *destPos = NULL, NLMISC::CVector *destSpeed = NULL,
00098                             bool accumulate = false,
00099                             uint posStride = sizeof(NLMISC::CVector), uint speedStride = sizeof(NLMISC::CVector)
00100                             ) const
00101      {
00102          nlassert(0); // not an integrable force
00103      }
00104 
00105 
00110     virtual void integrateSingle(float startDate, float deltaT, uint numStep,
00111                                  const CPSLocated *src, uint32 indexInLocated,
00112                                  NLMISC::CVector *destPos,
00113                                  bool accumulate = false,
00114                                  uint posStride = sizeof(NLMISC::CVector)) const
00115     {
00116          nlassert(0); // not an integrable force
00117     }
00118 
00119 
00120 
00121 
00122 
00123 
00124 protected:
00125     friend class CPSLocated;
00126     friend class CPSForceIntensity;
00127 
00129     void                registerToTargets(void);
00130 
00132     void                 cancelIntegrable(void);
00133 
00135     void                 renewIntegrable(void);
00136 
00140     virtual void         basisChanged(TPSMatrixMode systemBasis);
00141 
00142     virtual void newElement(const CPSEmitterInfo &info) = 0;
00143 
00148     virtual void deleteElement(uint32 index) = 0;
00149 
00153     virtual void resize(uint32 size) = 0;
00154 };
00155 
00156 
00158 class CPSForceIntensity
00159 {
00160 public:
00161 
00162     // ctor
00163     CPSForceIntensity() : _IntensityScheme(NULL)
00164     {
00165     }
00166 
00167     virtual ~CPSForceIntensity();
00168 
00169 
00171     float getIntensity(void) const  { return _K; }
00172 
00174     virtual void setIntensity(float value);
00175 
00177     virtual void setIntensityScheme(CPSAttribMaker<float> *scheme);
00178 
00179     // deriver have here the opportunity to setup the functor object. The default does nothing
00180     virtual void setupFunctor(uint32 indexInLocated) { }
00181 
00183     CPSAttribMaker<float> *getIntensityScheme(void) { return _IntensityScheme; }
00184     const CPSAttribMaker<float> *getIntensityScheme(void) const { return _IntensityScheme; }
00185     void serialForceIntensity(NLMISC::IStream &f) throw(NLMISC::EStream);
00186 
00187 protected:
00188 
00190     virtual CPSLocated *getForceIntensityOwner(void) = 0;
00191 
00192 
00193     // the intensity ...
00194     float _K;
00195     CPSAttribMaker<float> *_IntensityScheme;
00196 
00197     void newForceIntensityElement(const CPSEmitterInfo &info)
00198     {
00199         if (_IntensityScheme && _IntensityScheme->hasMemory()) _IntensityScheme->newElement(info);
00200     }
00201     void deleteForceIntensityElement(uint32 index)
00202     {
00203         if (_IntensityScheme && _IntensityScheme->hasMemory()) _IntensityScheme->deleteElement(index);
00204     }
00205     void resizeForceIntensity(uint32 size)
00206     {
00207         if (_IntensityScheme && _IntensityScheme->hasMemory()) _IntensityScheme->resize(size, getForceIntensityOwner()->getSize());
00208     }
00209 };
00210 
00211 
00216 class CPSForceIntensityHelper : public CPSForce, public CPSForceIntensity
00217 {
00218 public:
00219     void serial(NLMISC::IStream &f) throw(NLMISC::EStream) ;
00220 
00221 protected:
00222     virtual CPSLocated *getForceIntensityOwner(void) { return _Owner; }
00223     virtual void newElement(const CPSEmitterInfo &info) { newForceIntensityElement(info); }
00224     virtual void deleteElement(uint32 index) { deleteForceIntensityElement(index); }
00225     virtual void resize(uint32 size) { resizeForceIntensity(size); }
00226 
00227 };
00228 
00229 
00230 
00231 
00276 template <class T> class CIsotropicForceT : public CPSForce
00277 {
00278 public:
00279 
00281     virtual void computeForces(CPSLocated &target);
00282 
00283 
00285     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00286     {
00287         f.serialVersion(1);
00288         CPSForce::serial(f);
00289         f.serial(_F); // serial the functor object 5does nothing most of the time ...)
00290     }
00291 
00292 
00297      void show()  {}
00298 
00299 
00301 
00302      virtual void setupFunctor(uint32 /* index */) {}
00303 
00304 protected:
00305 
00307     T _F;
00308 
00309 
00310 
00311     virtual void newElement(const CPSEmitterInfo &/* info */) {}
00312     virtual void deleteElement(uint32 /* index */) {}
00313     virtual void resize(uint32 /* size */) {}
00314 
00315 
00316 };
00317 
00319 // implementation of method of the template class  CHomogenousForceT //
00321 
00322 
00323 template <class T> void CIsotropicForceT<T>::computeForces(CPSLocated &target)
00324 {
00325     nlassert(CParticleSystem::InsideSimLoop);
00326     for (uint32 k = 0; k < _Owner->getSize(); ++k)
00327     {
00328         setupFunctor(k);
00329         TPSAttribVector::iterator speedIt = target.getSpeed().begin(), endSpeedIt = target.getSpeed().end();
00330         TPSAttribVector::const_iterator posIt = target.getPos().begin();
00331         TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
00332 
00333         for (; speedIt != endSpeedIt; ++speedIt, ++posIt, ++invMassIt)
00334         {
00335             _F(*posIt, *speedIt, *invMassIt);
00336         }
00337     }
00338 }
00339 
00340 
00345 class CPSDirectionnalForce : public CPSForceIntensityHelper, public CPSDirection
00346 {
00347     public:
00349     virtual void computeForces(CPSLocated &target);
00350 
00352     virtual void show();
00353 
00354 
00355 
00356     CPSDirectionnalForce(float i = 1.f)
00357     {
00358         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("DirectionnalForce");
00359         setIntensity(i);
00360         _Dir = NLMISC::CVector(0, 0, -1);
00361     }
00362 
00364     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00365 
00366 
00367     NLMISC_DECLARE_CLASS(CPSDirectionnalForce);
00368 
00370 
00371 
00372         virtual void setDir(const NLMISC::CVector &dir) { _Dir = dir; }
00374         virtual NLMISC::CVector getDir(void) const  { return _Dir; }
00375         // Tells that a global vector value of the system can be used as a direction
00376         virtual bool supportGlobalVectorValue() const { return true; }
00378         virtual void                enableGlobalVectorValue(const std::string &name);
00379         // See if the direction is bound to a global variable. Return an empty string if not
00380         virtual std::string         getGlobalVectorValueName() const;
00382 protected:
00383     NLMISC::CVector                             _Dir;
00384     CParticleSystem::CGlobalVectorValueHandle   _GlobalValueHandle; // a global vector value may override the value of _Dir (example of use : global direction for wind)
00385 };
00386 
00387 
00389 class CPSGravity : public CPSForceIntensityHelper
00390 {
00391 public:
00393     virtual void computeForces(CPSLocated &target);
00394 
00396     virtual void show();
00397 
00398 
00399 
00400     CPSGravity(float g = 9.8f)
00401     {
00402         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("Gravity");
00403         setIntensity(g);
00404     }
00405 
00407     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00408 
00409     NLMISC_DECLARE_CLASS(CPSGravity);
00410 
00411 
00412     virtual bool         isIntegrable(void) const;
00413 
00415     virtual void integrate(float date, CPSLocated *src, uint32 startIndex, uint32 numObjects, NLMISC::CVector *destPos = NULL, NLMISC::CVector *destSpeed = NULL,
00416                             bool accumulate = false,
00417                             uint posStride = sizeof(NLMISC::CVector), uint speedStride = sizeof(NLMISC::CVector)
00418                             ) const;
00419 
00420     virtual void integrateSingle(float startDate, float deltaT, uint numStep,
00421                                  const CPSLocated *src, uint32 indexInLocated,
00422                                  NLMISC::CVector *destPos,
00423                                  bool accumulate = false,
00424                                  uint posStride = sizeof(NLMISC::CVector)) const;
00425 
00426 protected:
00428     virtual void setIntensity(float value);
00430     virtual void setIntensityScheme(CPSAttribMaker<float> *scheme);
00431 };
00432 
00433 
00435 class CPSCentralGravity : public CPSForceIntensityHelper
00436 {
00437 public:
00439     virtual void computeForces(CPSLocated &target);
00440 
00442     virtual void show();
00443 
00444 
00445 
00446     CPSCentralGravity(float i = 1.f)
00447     {
00448         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("CentralGravity");
00449         setIntensity(i);
00450     }
00451 
00453     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00454 
00455 
00456     NLMISC_DECLARE_CLASS(CPSCentralGravity);
00457 };
00458 
00459 
00461 class CPSSpring : public CPSForceIntensityHelper
00462 {
00463 public:
00464 
00466     CPSSpring(float k = 1.0f)
00467     {
00468         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("Spring");
00469         setIntensity(k);
00470     }
00471 
00472 
00474     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00475 
00476 
00478     virtual void computeForces(CPSLocated &target);
00479 
00481     virtual void show();
00482 
00483 
00484     NLMISC_DECLARE_CLASS(CPSSpring);
00485 
00486 };
00487 
00488 
00489 
00491 class CPSFluidFrictionFunctor
00492 {
00493 public:
00494     CPSFluidFrictionFunctor() : _K(1.f)
00495     {
00496     }
00497 
00498     virtual ~CPSFluidFrictionFunctor() {}
00499 
00500     #ifdef NL_OS_WINDOWS
00501         __forceinline
00502     #endif
00503      void operator() (const NLMISC::CVector &pos, NLMISC::CVector &speed, float invMass)
00504      {
00505         speed -= (CParticleSystem::EllapsedTime * _K * invMass * speed);
00506      }
00507 
00508      virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00509      {
00510          f.serialVersion(1);
00511          // we don't save intensity info : it is saved by the owning object (and set before each use of this functor)
00512      }
00513 
00514      // get the friction coefficient
00515      float getK(void) const { return _K; }
00516 
00517      // set the friction coefficient
00518      void setK(float coeff) { _K = coeff; }
00519 protected:
00520     // the friction coeff
00521     float _K;
00522 };
00523 
00524 
00530 class CPSFluidFriction : public CIsotropicForceT<CPSFluidFrictionFunctor>, public CPSForceIntensity
00531 {
00532 public:
00533     // create the force with a friction coefficient
00534     CPSFluidFriction(float frictionCoeff = 1.f)
00535     {
00536         setIntensity(frictionCoeff);
00537         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("FluidFriction");
00538     }
00539 
00540     // inherited from CIsotropicForceT
00541     virtual void setupFunctor(uint32 index)
00542     {
00543         _F.setK(_IntensityScheme ? _IntensityScheme->get(_Owner, index) : _K);
00544     }
00545 
00546     NLMISC_DECLARE_CLASS(CPSFluidFriction)
00547 
00548 
00549     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00550     {
00551         f.serialVersion(1);
00552         CIsotropicForceT<CPSFluidFrictionFunctor>::serial(f);
00553         serialForceIntensity(f);
00554         if (f.isReading())
00555         {
00556             registerToTargets();
00557         }
00558     }
00559 
00560 
00561 protected:
00562     virtual CPSLocated *getForceIntensityOwner(void) { return _Owner; }
00563     virtual void newElement(const CPSEmitterInfo &info) { newForceIntensityElement(info); }
00564     virtual void deleteElement(uint32 index) { deleteForceIntensityElement(index); }
00565     virtual void resize(uint32 size) { resizeForceIntensity(size); }
00566 };
00567 
00568 
00573 class CPSBrownianForce : public CPSForceIntensityHelper
00574 {
00575 public:
00576     // create the force with a friction coefficient
00577     CPSBrownianForce(float intensity = 1.f);
00578 
00579     NLMISC_DECLARE_CLASS(CPSBrownianForce)
00580 
00581     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00582 
00584     virtual bool         isIntegrable(void) const;
00585 
00586     virtual void integrate(float date, CPSLocated *src, uint32 startIndex, uint32 numObjects, NLMISC::CVector *destPos = NULL, NLMISC::CVector *destSpeed = NULL,
00587                             bool accumulate = false,
00588                             uint posStride = sizeof(NLMISC::CVector), uint speedStride = sizeof(NLMISC::CVector)
00589                             ) const;
00590 
00591     virtual void integrateSingle(float startDate, float deltaT, uint numStep,
00592                                  const CPSLocated *src, uint32 indexInLocated,
00593                                  NLMISC::CVector *destPos,
00594                                  bool accumulate = false,
00595                                  uint posStride = sizeof(NLMISC::CVector)) const;
00596 
00598     static void initPrecalc();
00599 
00600     void setIntensity(float value);
00601     void setIntensityScheme(CPSAttribMaker<float> *scheme);
00602 
00604     virtual void computeForces(CPSLocated &target);
00605 
00606     void show()  {}
00607 
00608 
00612     void    setParametricFactor(float factor) {  _ParametricFactor = factor; }
00613     float   getParametricFactor() const { return _ParametricFactor; }
00614 
00615 protected:
00616     virtual CPSLocated *getForceIntensityOwner(void) { return _Owner; }
00617     virtual void newElement(const CPSEmitterInfo &info) { newForceIntensityElement(info); }
00618     virtual void deleteElement(uint32 index) { deleteForceIntensityElement(index); }
00619     virtual void resize(uint32 size) { resizeForceIntensity(size); }
00620 
00621     float  _ParametricFactor; // tells how fast this force act on a particle when parametric motion is used
00622     static NLMISC::CVector PrecomputedPos[]; // after the sequence we must be back to the start position
00623     static NLMISC::CVector PrecomputedSpeed[];
00624 
00626     static NLMISC::CVector PrecomputedImpulsions[];
00627 
00628 };
00629 
00630 
00632 
00633 struct CPSTurbulForceFunc
00634 {
00635     virtual ~CPSTurbulForceFunc() {}
00636 
00637     #ifdef NL_OS_WINDOWS
00638         __forceinline
00639     #endif
00640     void operator() (const NLMISC::CVector &pos, NLMISC::CVector &speed, float invMass)
00641     {
00642         nlassert(0);
00643 
00644         // TODO : complete that
00645 
00646     /*  static const NLMISC::CVector v1(1.235f, - 45.32f, 157.5f);
00647         static const NLMISC::CVector v2(-0.35f, 7.77f, 220.77f);
00648 
00649 
00650         speed += ellapsedTime * _Intensity
00651                * NLMISC::CVector(2.f * (-0.5f + CPSUtil::buildPerlinNoise(_Scale * pos, _NumOctaves))
00652                          , 2.f * (-0.5f +  CPSUtil::buildPerlinNoise(_Scale * (pos +  v1) , _NumOctaves))
00653                          , 2.f * (-0.5f +  CPSUtil::buildPerlinNoise(_Scale * (pos +  v2) , _NumOctaves))
00654                          );
00655                          */
00656     }
00657 
00658     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00659      {
00660         f.serialVersion(1);
00661         f.serial(_Scale, _NumOctaves);
00662      }
00663 
00664     float _Scale;
00665     float _Intensity;
00666     uint32 _NumOctaves;
00667 };
00668 
00669 
00670 
00671 // the turbulence force
00672 
00673 class CPSTurbul : public CIsotropicForceT<CPSTurbulForceFunc>, public CPSForceIntensity
00674 {
00675 public:
00676     // create the force with a friction coefficient
00677     CPSTurbul(float scale = 1.f , uint numOctaves = 4)
00678     {
00679         nlassert(numOctaves > 0);
00680         setScale(scale);
00681         setNumOctaves(numOctaves);
00682         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("Turbulence");
00683     }
00684 
00685 
00686     float getScale(void) const { return _F._Scale; }
00687     void setScale(float scale) { _F._Scale = scale; }
00688 
00689 
00690     uint getNumOctaves(void) const { return _F._NumOctaves; }
00691     void setNumOctaves(uint numOctaves) { _F._NumOctaves = numOctaves; }
00692 
00693 
00694     NLMISC_DECLARE_CLASS(CPSTurbul)
00695 
00696     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00697     {
00698         f.serialVersion(1);
00699         CIsotropicForceT<CPSTurbulForceFunc>::serial(f);
00700         serialForceIntensity(f);
00701         if (f.isReading())
00702         {
00703             registerToTargets();
00704         }
00705     }
00706 
00707     // inherited from CIsotropicForceT
00708     virtual void setupFunctor(uint32 index)
00709     {
00710         _F._Intensity = (_IntensityScheme ? _IntensityScheme->get(_Owner, index) : _K);
00711     }
00712 
00713 protected:
00714     virtual CPSLocated *getForceIntensityOwner(void) { return _Owner; }
00715     virtual void newElement(const CPSEmitterInfo &info) { newForceIntensityElement(info); }
00716     virtual void deleteElement(uint32 index) { deleteForceIntensityElement(index); }
00717     virtual void resize(uint32 size) { resizeForceIntensity(size); }
00718 };
00719 
00720 
00721 
00722 
00728 class CPSCylindricVortex : public CPSForceIntensityHelper, public IPSMover
00729 {
00730 public:
00732     virtual void computeForces(CPSLocated &target);
00733 
00735     virtual void show();
00736 
00737 
00738     CPSCylindricVortex(float intensity = 1.f) : _RadialViscosity(.1f), _TangentialViscosity(.1f)
00739     {
00740         setIntensity(intensity);
00741         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("Cylindric Vortex");
00742     }
00743 
00744     // inherited from IPSMover
00745     virtual bool supportUniformScaling(void) const { return true; }
00746     virtual bool supportNonUniformScaling(void) const { return false; }
00747     virtual void setScale(uint32 k, float scale) { _Radius[k] = scale; }
00748     virtual NLMISC::CVector getScale(uint32 k) const { return NLMISC::CVector(_Radius[k], _Radius[k], _Radius[k]); }
00749     virtual bool onlyStoreNormal(void) const { return true; }
00750     virtual NLMISC::CVector getNormal(uint32 index) { return _Normal[index]; }
00751     virtual void setNormal(uint32 index, NLMISC::CVector n) { _Normal[index] = n; }
00752 
00753     virtual void setMatrix(uint32 index, const NLMISC::CMatrix &m);
00754     virtual NLMISC::CMatrix getMatrix(uint32 index) const;
00755 
00756 
00757     void setRadialViscosity(float v) { _RadialViscosity = v; }
00758     float getRadialViscosity(void) const { return _RadialViscosity; }
00759 
00760     void setTangentialViscosity(float v) { _TangentialViscosity = v; }
00761     float getTangentialViscosity(void) const { return _TangentialViscosity; }
00762 
00763     NLMISC_DECLARE_CLASS(CPSCylindricVortex);
00764 
00765 
00766 
00767     // serialization
00768     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00769 
00770 
00771 
00772 
00773 
00774 protected:
00775 
00777     virtual CPSLocated *getForceIntensityOwner(void) { return _Owner; }
00778 
00779     // the normal of the vortex
00780     CPSAttrib<NLMISC::CVector> _Normal;
00781     // radius of the vortex
00782     TPSAttribFloat _Radius;
00783 
00784     // radial viscosity : when it is near of 1, if tends to set the radial componenent of speed to 0
00785     float _RadialViscosity;
00786 
00787     // tangential viscosity : when set to 1, the tangential speed immediatly reach what it would be in a real vortex (w = 1 / r2)
00788     float _TangentialViscosity;
00789 
00790     virtual void newElement(const CPSEmitterInfo &info);
00791     virtual void deleteElement(uint32 index);
00792     virtual void resize(uint32 size);
00793 
00794 };
00795 
00796 
00797 
00798 
00802 class CPSMagneticForce : public CPSDirectionnalForce
00803 {
00804     public:
00805     CPSMagneticForce(float i = 1.f)  : CPSDirectionnalForce(i)
00806     {
00807         if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("MagneticForce");
00808     }
00809     virtual void computeForces(CPSLocated &target);
00811     virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00812     NLMISC_DECLARE_CLASS(CPSMagneticForce);
00813 };
00814 
00815 
00816 
00817 
00818 
00819 } // NL3D
00820 
00821 
00822 #endif // NL_PS_FORCE_H
00823 
00824 /* End of ps_force.h */

Generated on Thu Jan 7 08:26:19 2010 for NeL by  doxygen 1.6.1