# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

ps_force.h

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