00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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);
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);
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
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
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
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);
00290 }
00291
00292
00297 void show() {}
00298
00299
00301
00302 virtual void setupFunctor(uint32 ) {}
00303
00304 protected:
00305
00307 T _F;
00308
00309
00310
00311 virtual void newElement(const CPSEmitterInfo &) {}
00312 virtual void deleteElement(uint32 ) {}
00313 virtual void resize(uint32 ) {}
00314
00315
00316 };
00317
00319
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
00376 virtual bool supportGlobalVectorValue() const { return true; }
00378 virtual void enableGlobalVectorValue(const std::string &name);
00379
00380 virtual std::string getGlobalVectorValueName() const;
00382 protected:
00383 NLMISC::CVector _Dir;
00384 CParticleSystem::CGlobalVectorValueHandle _GlobalValueHandle;
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
00512 }
00513
00514
00515 float getK(void) const { return _K; }
00516
00517
00518 void setK(float coeff) { _K = coeff; }
00519 protected:
00520
00521 float _K;
00522 };
00523
00524
00530 class CPSFluidFriction : public CIsotropicForceT<CPSFluidFrictionFunctor>, public CPSForceIntensity
00531 {
00532 public:
00533
00534 CPSFluidFriction(float frictionCoeff = 1.f)
00535 {
00536 setIntensity(frictionCoeff);
00537 if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("FluidFriction");
00538 }
00539
00540
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
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;
00622 static NLMISC::CVector PrecomputedPos[];
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
00645
00646
00647
00648
00649
00650
00651
00652
00653
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
00672
00673 class CPSTurbul : public CIsotropicForceT<CPSTurbulForceFunc>, public CPSForceIntensity
00674 {
00675 public:
00676
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
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
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
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
00780 CPSAttrib<NLMISC::CVector> _Normal;
00781
00782 TPSAttribFloat _Radius;
00783
00784
00785 float _RadialViscosity;
00786
00787
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 }
00820
00821
00822 #endif // NL_PS_FORCE_H
00823
00824