00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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);
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);
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
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
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
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);
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
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
00381 virtual bool supportGlobalVectorValue() const { return true; }
00383 virtual void enableGlobalVectorValue(const std::string &name);
00384
00385 virtual std::string getGlobalVectorValueName() const;
00387 protected:
00388 NLMISC::CVector _Dir;
00389 CParticleSystem::CGlobalVectorValueHandle _GlobalValueHandle;
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
00515 }
00516
00517
00518 float getK(void) const { return _K; }
00519
00520
00521 void setK(float coeff) { _K = coeff; }
00522 protected:
00523
00524 float _K;
00525 };
00526
00527
00533 class CPSFluidFriction : public CIsotropicForceT<CPSFluidFrictionFunctor>, public CPSForceIntensity
00534 {
00535 public:
00536
00537 CPSFluidFriction(float frictionCoeff = 1.f)
00538 {
00539 setIntensity(frictionCoeff);
00540 _Name = std::string("FluidFriction");
00541 }
00542
00543
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
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;
00625 static NLMISC::CVector PrecomputedPos[];
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
00646
00647
00648
00649
00650
00651
00652
00653
00654
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
00673
00674 class CPSTurbul : public CIsotropicForceT<CPSTurbulForceFunc>, public CPSForceIntensity
00675 {
00676 public:
00677
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
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
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
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
00781 CPSAttrib<NLMISC::CVector> _Normal;
00782
00783 TPSAttribFloat _Radius;
00784
00785
00786 float _RadialViscosity;
00787
00788
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 }
00821
00822
00823 #endif // NL_PS_FORCE_H
00824
00825