ps_force.cpp

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 #include "std3d.h"
00025 
00026 #include "nel/3d/ps_force.h"
00027 #include "nel/3d/driver.h"
00028 #include "nel/3d/index_buffer.h"
00029 #include "nel/3d/material.h"
00030 #include "nel/3d/vertex_buffer.h"
00031 #include "nel/3d/computed_string.h"
00032 #include "nel/3d/font_manager.h"
00033 #include "nel/3d/particle_system.h"
00034 #include "nel/misc/common.h"
00035 #include "nel/3d/ps_util.h"
00036 #include "nel/3d/ps_misc.h"
00037 
00038 namespace NL3D {
00039 
00040 
00041 /*
00042  * Constructor
00043  */
00044 CPSForce::CPSForce()
00045 {
00046     NL_PS_FUNC(CPSForce_CPSForce)
00047 }
00048 
00049 
00050 
00051 void CPSForce::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00052 {
00053     NL_PS_FUNC(CPSForce_serial)
00054     f.serialVersion(1);
00055     CPSTargetLocatedBindable::serial(f);
00056     CPSLocatedBindable::serial(f);
00057 }
00058 
00059 
00060 void CPSForce::registerToTargets(void)
00061 {
00062     NL_PS_FUNC(CPSForce_registerToTargets)
00063     for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
00064     {
00065         if (this->isIntegrable())
00066         {
00067             (*it)->registerIntegrableForce(this);
00068         }
00069         else
00070         {
00071             (*it)->addNonIntegrableForceRef();
00072         }
00073     }
00074 }
00075 
00076 
00077 void CPSForce::step(TPSProcessPass pass)
00078 {
00079     NL_PS_FUNC(CPSForce_step)
00080     switch(pass)
00081     {
00082         case PSToolRender:
00083             show();
00084             break;
00085         default: break;
00086     }
00087 }
00088 
00089 
00090 
00091 void    CPSForce::attachTarget(CPSLocated *ptr)
00092 {
00093     NL_PS_FUNC(CPSForce_attachTarget)
00094     nlassert(_Owner);
00095     CPSTargetLocatedBindable::attachTarget(ptr);
00096     // check whether we are integrable, and if so, add us to the list
00097     if (this->isIntegrable())
00098     {
00099         ptr->registerIntegrableForce(this);
00100     }
00101     else
00102     {
00103         ptr->addNonIntegrableForceRef();
00104     }
00105 }
00106 
00107 void    CPSForce::releaseTargetRsc(CPSLocated *target)
00108 {
00109     NL_PS_FUNC(CPSForce_releaseTargetRsc)
00110     if (this->isIntegrable())
00111     {
00112         target->unregisterIntegrableForce(this);
00113     }
00114     else
00115     {
00116         target->releaseNonIntegrableForceRef();
00117     }
00118 }
00119 
00120 
00121 
00122 void    CPSForce::basisChanged(TPSMatrixMode matrixMode)
00123 {
00124     NL_PS_FUNC(CPSForce_basisChanged)
00125     if (!this->isIntegrable()) return;
00126     for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
00127     {
00128         (*it)->integrableForceBasisChanged(matrixMode);
00129     }
00130 }
00131 
00132 
00133 void    CPSForce::cancelIntegrable(void)
00134 {
00135     NL_PS_FUNC(CPSForce_cancelIntegrable)
00136     nlassert(_Owner);
00137     for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
00138     {
00139         if ((*it)->getMatrixMode() == _Owner->getMatrixMode())
00140         {
00141             (*it)->unregisterIntegrableForce(this);
00142             (*it)->addNonIntegrableForceRef();
00143         }
00144     }
00145 }
00146 
00147 
00148 void    CPSForce::renewIntegrable(void)
00149 {
00150     NL_PS_FUNC(CPSForce_renewIntegrable)
00151     nlassert(_Owner);
00152     for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
00153     {
00154         if ((*it)->getMatrixMode() == _Owner->getMatrixMode())
00155         {
00156             (*it)->registerIntegrableForce(this);
00157             (*it)->releaseNonIntegrableForceRef();
00158         }
00159     }
00160 }
00161 
00162 
00163 
00165 //  CPSForceIntensity implementation //
00167 
00168 void CPSForceIntensity::setIntensity(float value)
00169 {
00170     NL_PS_FUNC(CPSForceIntensity_setIntensity)
00171     if (_IntensityScheme)
00172     {
00173         delete _IntensityScheme;
00174         _IntensityScheme = NULL;
00175     }
00176     _K = value;
00177 
00178 }
00179 
00180 CPSForceIntensity::~CPSForceIntensity()
00181 {
00182     NL_PS_FUNC(CPSForceIntensity_CPSForceIntensityDtor)
00183     delete _IntensityScheme;
00184 }
00185 
00186 void CPSForceIntensity::setIntensityScheme(CPSAttribMaker<float> *scheme)
00187 {
00188     NL_PS_FUNC(CPSForceIntensity_setIntensityScheme)
00189     nlassert(scheme);
00190     delete _IntensityScheme;
00191     _IntensityScheme = scheme;
00192     if (getForceIntensityOwner() && scheme->hasMemory()) scheme->resize(getForceIntensityOwner()->getMaxSize(), getForceIntensityOwner()->getSize());
00193 }
00194 
00195 void CPSForceIntensity::serialForceIntensity(NLMISC::IStream &f) throw(NLMISC::EStream)
00196 {
00197     NL_PS_FUNC(CPSForceIntensity_IStream )
00198     f.serialVersion(1);
00199     if (!f.isReading())
00200     {
00201         if (_IntensityScheme)
00202         {
00203             bool bFalse = false;
00204             f.serial(bFalse);
00205             f.serialPolyPtr(_IntensityScheme);
00206         }
00207         else
00208         {
00209             bool bTrue = true;
00210             f.serial(bTrue);
00211             f.serial(_K);
00212         }
00213     }
00214     else
00215     {
00216         bool constantIntensity;
00217         f.serial(constantIntensity);
00218         if (constantIntensity)
00219         {
00220             f.serial(_K);
00221         }
00222         else
00223         {
00224             f.serialPolyPtr(_IntensityScheme);
00225         }
00226     }
00227 }
00228 
00229 
00231 // CPSForceIntensityHelper            //
00233 
00234 
00235 void CPSForceIntensityHelper::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00236 {
00237     NL_PS_FUNC(CPSForceIntensityHelper_serial)
00238     f.serialVersion(1);
00239     CPSForce::serial(f);
00240     serialForceIntensity(f);
00241     if (f.isReading())
00242     {
00243         registerToTargets();
00244     }
00245 }
00246 
00247 
00248 
00250 // CPSDirectionalForce implementation //
00252 
00253 void CPSDirectionnalForce::computeForces(CPSLocated &target)
00254 {
00255     NL_PS_FUNC(CPSDirectionnalForce_computeForces)
00256     nlassert(CParticleSystem::InsideSimLoop);
00257     // perform the operation on each target
00258     CVector toAdd;
00259     for (uint32 k = 0; k < _Owner->getSize(); ++k)
00260     {
00261         CVector toAddLocal;
00262         CVector dir;
00263 
00264         if (_GlobalValueHandle.isValid()) // is direction a global variable ?
00265         {
00266             dir = _GlobalValueHandle.get(); // takes direction from global variable instead
00267         }
00268         else
00269         {
00270             dir = _Dir;
00271         }
00272         toAddLocal = CParticleSystem::EllapsedTime * (_IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K ) * dir;
00273         toAdd = CPSLocated::getConversionMatrix(&target, this->_Owner).mulVector(toAddLocal); // express this in the target basis
00274         TPSAttribVector::iterator it = target.getSpeed().begin(), itend = target.getSpeed().end();
00275         // 1st case : non-constant mass
00276         if (target.getMassScheme())
00277         {
00278             TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
00279             for (;it != itend; ++it, ++invMassIt)
00280             {
00281                 (*it) += *invMassIt * toAdd;
00282 
00283             }
00284         }
00285         else
00286         {
00287             // the mass is constant
00288             toAdd /= target.getInitialMass();
00289             for (; it != itend; ++it)
00290             {
00291                 (*it) += toAdd;
00292             }
00293         }
00294     }
00295 }
00296 
00297 
00298 void CPSDirectionnalForce::show()
00299 {
00300     NL_PS_FUNC(CPSDirectionnalForce_show)
00301     CPSLocated *loc;
00302     uint32 index;
00303     CPSLocatedBindable *lb;
00304     _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
00305 
00306     setupDriverModelMatrix();
00307 
00308     CVector dir;
00309     if (_GlobalValueHandle.isValid()) // is direction a global variable ?
00310     {
00311         dir = _GlobalValueHandle.get(); // takes direction from global variable instead
00312     }
00313     else
00314     {
00315         dir = _Dir;
00316     }
00317 
00318     // for each element, see if it is the selected element, and if yes, display in red
00319     for (uint k = 0; k < _Owner->getSize(); ++k)
00320     {
00321         const CRGBA col = (((lb == NULL || this == lb) && loc == _Owner && index == k)  ? CRGBA::Red : CRGBA(127, 127, 127));
00322         CPSUtil::displayArrow(getDriver(), _Owner->getPos()[k], dir, 1.f, col, CRGBA(80, 80, 0));
00323     }
00324 }
00325 
00326 void CPSDirectionnalForce::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00327 {
00328     NL_PS_FUNC(CPSDirectionnalForce_serial)
00329     // Version 2 : added link to a global vector value
00330     //
00331     sint ver = f.serialVersion(2);
00332     CPSForceIntensityHelper::serial(f);
00333     if (ver == 1)
00334     {
00335         f.serial(_Dir);
00336         _GlobalValueHandle.reset();
00337     }
00338     else
00339     {
00340         bool useHandle = _GlobalValueHandle.isValid();
00341         f.serial(useHandle);
00342         if (useHandle)
00343         {
00344             // a global value is used
00345             if (f.isReading())
00346             {
00347                 std::string handleName;
00348                 f.serial(handleName);
00349                 // retrieve a handle to the global value from the particle system
00350                 _GlobalValueHandle = CParticleSystem::getGlobalVectorValueHandle(handleName);
00351             }
00352             else
00353             {
00354                 std::string handleName = _GlobalValueHandle.getName();
00355                 f.serial(handleName);
00356             }
00357         }
00358         else
00359         {
00360             f.serial(_Dir);
00361         }
00362     }
00363 }
00364 
00365 void CPSDirectionnalForce::enableGlobalVectorValue(const std::string &name)
00366 {
00367     NL_PS_FUNC(CPSDirectionnalForce_enableGlobalVectorValue)
00368     if (name.empty())
00369     {
00370         _GlobalValueHandle.reset();
00371         return;
00372     }
00373     _GlobalValueHandle = CParticleSystem::getGlobalVectorValueHandle(name);
00374 }
00375 
00376 std::string CPSDirectionnalForce::getGlobalVectorValueName() const
00377 {
00378     NL_PS_FUNC(CPSDirectionnalForce_getGlobalVectorValueName)
00379     return _GlobalValueHandle.isValid() ? _GlobalValueHandle.getName() : "";
00380 }
00381 
00383 // gravity implementation //
00385 void CPSGravity::computeForces(CPSLocated &target)
00386 {
00387     NL_PS_FUNC(CPSGravity_computeForces)
00388     nlassert(CParticleSystem::InsideSimLoop);
00389     // perform the operation on each target
00390     CVector toAdd;
00391     for (uint32 k = 0; k < _Owner->getSize(); ++k)
00392     {
00393         CVector toAddLocal = CParticleSystem::EllapsedTime * CVector(0, 0, _IntensityScheme ? - _IntensityScheme->get(_Owner, k) : - _K);
00394         toAdd = CPSLocated::getConversionMatrix(&target, this->_Owner).mulVector(toAddLocal); // express this in the target basis
00395         TPSAttribVector::iterator it = target.getSpeed().begin(), itend = target.getSpeed().end();
00396 
00397         if (toAdd.x && toAdd.y)
00398         {
00399             for (; it != itend; ++it)
00400             {
00401                 (*it) += toAdd;
00402 
00403             }
00404         }
00405         else // only the z component is not null, which should be the majority of cases ...
00406         {
00407             for (; it != itend; ++it)
00408             {
00409                 it->z += toAdd.z;
00410 
00411             }
00412         }
00413     }
00414 }
00415 
00416 void CPSGravity::show()
00417 {
00418     NL_PS_FUNC(CPSGravity_show)
00419     CVector I = computeI();
00420     CVector K = CVector(0,0,1);
00421 
00422     // this is not designed for efficiency (target : edition code)
00423     CIndexBuffer     pb;
00424     CVertexBuffer vb;
00425     CMaterial material;
00426     IDriver *driver = getDriver();
00427     const float toolSize = 0.2f;
00428 
00429     vb.setVertexFormat(CVertexBuffer::PositionFlag);
00430     vb.setNumVertices(6);
00431     {
00432         CVertexBufferReadWrite vba;
00433         vb.lock (vba);
00434         vba.setVertexCoord(0, -toolSize * I);
00435         vba.setVertexCoord(1, toolSize * I);
00436         vba.setVertexCoord(2, CVector(0, 0, 0));
00437         vba.setVertexCoord(3, -6.0f * toolSize * K);
00438         vba.setVertexCoord(4, -toolSize * I  - 5.0f * toolSize * K);
00439         vba.setVertexCoord(5, toolSize * I - 5.0f * toolSize * K);
00440     }
00441     pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
00442     pb.setNumIndexes(2*4);
00443     {
00444         CIndexBufferReadWrite ibaWrite;
00445         pb.lock (ibaWrite);
00446         ibaWrite.setLine(0, 0, 1);
00447         ibaWrite.setLine(2, 2, 3);
00448         ibaWrite.setLine(4, 4, 3);
00449         ibaWrite.setLine(6, 3, 5);
00450     }
00451 
00452     material.setColor(CRGBA(127, 127, 127));
00453     material.setLighting(false);
00454     material.setBlendFunc(CMaterial::one, CMaterial::one);
00455     material.setZWrite(false);
00456     material.setBlend(true);
00457 
00458 
00459     CMatrix mat;
00460 
00461     for (TPSAttribVector::const_iterator it = _Owner->getPos().begin(); it != _Owner->getPos().end(); ++it)
00462     {
00463         mat.identity();
00464         mat.translate(*it);
00465         mat = getLocalToWorldMatrix() * mat;
00466 
00467         driver->setupModelMatrix(mat);
00468         driver->activeVertexBuffer(vb);
00469         driver->activeIndexBuffer(pb);
00470         driver->renderLines(material, 0, pb.getNumIndexes()/2);
00471 
00472 
00473 
00474         // affiche un g a cote de la force
00475 
00476         CVector pos = *it + CVector(1.5f * toolSize, 0, -1.2f * toolSize);
00477 
00478         pos = getLocalToWorldMatrix() * pos;
00479 
00480 
00481         // must have set this
00482         nlassert(getFontGenerator() && getFontGenerator());
00483 
00484         CPSUtil::print(driver, std::string("G")
00485                             , *getFontGenerator()
00486                             , *getFontManager()
00487                             , pos
00488                             , 80.0f * toolSize );
00489     }
00490 
00491 
00492 }
00493 
00494 void CPSGravity::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00495 {
00496     NL_PS_FUNC(CPSGravity_IStream )
00497     f.serialVersion(1);
00498     CPSForceIntensityHelper::serial(f);
00499 }
00500 
00501 
00502 bool    CPSGravity::isIntegrable(void) const
00503 {
00504     NL_PS_FUNC(CPSGravity_isIntegrable)
00505     return _IntensityScheme == NULL;
00506 }
00507 
00508 void CPSGravity::integrate(float date, CPSLocated *src, uint32 startIndex, uint32 numObjects, NLMISC::CVector *destPos, NLMISC::CVector *destSpeed,
00509                             bool accumulate,
00510                             uint posStride, uint speedStride
00511                             ) const
00512 {
00513     NL_PS_FUNC(CPSGravity_integrate)
00514     #define NEXT_SPEED destSpeed = (NLMISC::CVector *) ((uint8 *) destSpeed + speedStride);
00515     #define NEXT_POS   destPos   = (NLMISC::CVector *) ((uint8 *) destPos   + posStride);
00516 
00517     float deltaT;
00518 
00519     if (!destPos && !destSpeed) return;
00520 
00521     CPSLocated::TPSAttribParametricInfo::const_iterator it = src->_PInfo.begin() + startIndex,
00522                                                         endIt = src->_PInfo.begin() + startIndex + numObjects;
00523     if (!accumulate) // compute coords from initial condition, and applying this force
00524     {
00525         if (destPos && !destSpeed) // fills dest pos only
00526         {
00527             while (it != endIt)
00528             {
00529                 deltaT = date - it->Date;
00530                 destPos->x = it->Pos.x + deltaT * it->Speed.x;
00531                 destPos->y = it->Pos.y + deltaT * it->Speed.y;
00532                 destPos->z = it->Pos.z + deltaT * it->Speed.z - 0.5f * deltaT * deltaT * _K;
00533                 ++it;
00534                 NEXT_POS;
00535             }
00536         }
00537         else if (!destPos && destSpeed) // fills dest speed only
00538         {
00539             while (it != endIt)
00540             {
00541                 deltaT = date - it->Date;
00542                 destSpeed->x = it->Speed.x;
00543                 destSpeed->y = it->Speed.y;
00544                 destSpeed->z = it->Speed.z - deltaT * _K;
00545                 ++it;
00546                 NEXT_SPEED;
00547             }
00548         }
00549         else // fills both speed and pos
00550         {
00551             while (it != endIt)
00552             {
00553                 deltaT = date - it->Date;
00554                 destPos->x = it->Pos.x + deltaT * it->Speed.x;
00555                 destPos->y = it->Pos.y + deltaT * it->Speed.y;
00556                 destPos->z = it->Pos.z + deltaT * it->Speed.z - 0.5f * deltaT * deltaT * _K;
00557 
00558                 destSpeed->x = it->Speed.x;
00559                 destSpeed->y = it->Speed.y;
00560                 destSpeed->z = it->Speed.z - deltaT * _K;
00561 
00562                 ++it;
00563                 NEXT_POS;
00564                 NEXT_SPEED;
00565             }
00566         }
00567     }
00568     else // accumulate datas
00569     {
00570         if (destPos && !destSpeed) // fills dest pos only
00571         {
00572             while (it != endIt)
00573             {
00574                 deltaT = date - it->Date;
00575                 destPos->z -= 0.5f * deltaT * deltaT * _K;
00576                 ++it;
00577                 NEXT_POS;
00578             }
00579         }
00580         else if (!destPos && destSpeed) // fills dest speed only
00581         {
00582             while (it != endIt)
00583             {
00584                 deltaT = date - it->Date;
00585                 destSpeed->z -= deltaT * _K;
00586                 ++it;
00587                 NEXT_SPEED;
00588             }
00589         }
00590         else // fills both speed and pos
00591         {
00592             while (it != endIt)
00593             {
00594                 deltaT = date - it->Date;
00595                 destPos->z -= 0.5f * deltaT * deltaT * _K;
00596                 destSpeed->z -= deltaT * _K;
00597                 ++it;
00598                 NEXT_POS;
00599                 NEXT_SPEED;
00600             }
00601         }
00602     }
00603 
00604 }
00605 
00606 
00607 
00608 void CPSGravity::integrateSingle(float startDate, float deltaT, uint numStep,
00609                                  const CPSLocated *src, uint32 indexInLocated,
00610                                  NLMISC::CVector *destPos,
00611                                  bool accumulate /*= false*/,
00612                                  uint stride/* = sizeof(NLMISC::CVector)*/) const
00613 {
00614     NL_PS_FUNC(CPSGravity_CVector )
00615     nlassert(src->isParametricMotionEnabled());
00616     //nlassert(deltaT > 0);
00617     nlassert(numStep > 0);
00618     #ifdef NL_DEBUG
00619         NLMISC::CVector *endPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride * numStep);
00620     #endif
00621     const CPSLocated::CParametricInfo &pi = src->_PInfo[indexInLocated];
00622     const NLMISC::CVector &startPos   = pi.Pos;
00623     if (numStep != 0)
00624     {
00625         if (!accumulate)
00626         {
00627             destPos = FillBufUsingSubdiv(startPos, pi.Date, startDate, deltaT, numStep, destPos, stride);
00628             if (numStep != 0)
00629             {
00630                 float currDate = startDate - pi.Date;
00631                 nlassert(currDate >= 0);
00632                 const NLMISC::CVector &startSpeed = pi.Speed;
00633                 do
00634                 {
00635                     #ifdef NL_DEBUG
00636                         nlassert(destPos < endPos);
00637                     #endif
00638                     float halfTimeSquare  = 0.5f * currDate * currDate;
00639                     destPos->x = startPos.x + currDate * startSpeed.x;
00640                     destPos->y = startPos.y + currDate * startSpeed.y;
00641                     destPos->z = startPos.z + currDate * startSpeed.z - _K * halfTimeSquare;
00642                     currDate += deltaT;
00643                     destPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride);
00644                 }
00645                 while (--numStep);
00646             }
00647         }
00648         else
00649         {
00650             uint numToSkip = ScaleFloatGE(startDate, deltaT, pi.Date, numStep);
00651             if (numToSkip < numStep)
00652             {
00653                 numStep -= numToSkip;
00654                 float currDate = startDate + deltaT * numToSkip - pi.Date;
00655                 do
00656                 {
00657                     #ifdef NL_DEBUG
00658                         nlassert(destPos < endPos);
00659                     #endif
00660                     float halfTimeSquare  = 0.5f * currDate * currDate;
00661                     destPos->z -=  _K * halfTimeSquare;
00662                     currDate += deltaT;
00663                     destPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride);
00664                 }
00665                 while (--numStep);
00666             }
00667         }
00668     }
00669 }
00670 
00671 
00672 void CPSGravity::setIntensity(float value)
00673 {
00674     NL_PS_FUNC(CPSGravity_setIntensity)
00675     if (_IntensityScheme)
00676     {
00677         CPSForceIntensityHelper::setIntensity(value);
00678         renewIntegrable(); // integrable again
00679     }
00680     else
00681     {
00682         CPSForceIntensityHelper::setIntensity(value);
00683     }
00684 }
00685 
00686 void CPSGravity::setIntensityScheme(CPSAttribMaker<float> *scheme)
00687 {
00688     NL_PS_FUNC(CPSGravity_setIntensityScheme)
00689     if (!_IntensityScheme)
00690     {
00691         cancelIntegrable(); // not integrable anymore
00692     }
00693     CPSForceIntensityHelper::setIntensityScheme(scheme);
00694 }
00695 
00696 
00698 // CPSCentralGravity  implementation   //
00700 
00701 void CPSCentralGravity::computeForces(CPSLocated &target)
00702 {
00703     NL_PS_FUNC(CPSCentralGravity_computeForces)
00704     nlassert(CParticleSystem::InsideSimLoop);
00705     // for each central gravity, and each target, we check if they are in the same basis
00706     // if not, we need to transform the central gravity attachment pos into the target basis
00707     uint32 size = _Owner->getSize();
00708     // a vector that goes from the gravity to the object
00709     CVector centerToObj;
00710     float dist;
00711 
00712     for (uint32 k = 0; k < size; ++k)
00713     {
00714         const float ellapsedTimexK = CParticleSystem::EllapsedTime  * (_IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K);
00715         const CMatrix &m = CPSLocated::getConversionMatrix(&target, this->_Owner);
00716         const CVector center = m * (_Owner->getPos()[k]);
00717         TPSAttribVector::iterator it2 = target.getSpeed().begin(), it2End = target.getSpeed().end();
00718         TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
00719         TPSAttribVector::const_iterator posIt = target.getPos().begin();
00720         for (; it2 != it2End; ++it2, ++invMassIt, ++posIt)
00721         {
00722             // our equation does 1 / r attenuation, which is not realistic, but fast ...
00723             centerToObj = center - *posIt;
00724 
00725             dist = centerToObj * centerToObj;
00726             if (dist > 10E-6f)
00727             {
00728                 (*it2) += (*invMassIt) * ellapsedTimexK * (1.f / dist) *  centerToObj;
00729             }
00730         }
00731     }
00732 }
00733 
00734 void CPSCentralGravity::show()
00735 {
00736     NL_PS_FUNC(CPSCentralGravity_show)
00737     CVector I = CVector::I;
00738     CVector J = CVector::J;
00739 
00740     const CVector tab[] = { -I - J, I - J
00741                             ,-I + J, I + J
00742                             , I - J, I + J
00743                             , -I - J, -I + J
00744                             , I + J, -I - J
00745                             , I - J, J - I
00746                             };
00747     const uint tabSize = sizeof(tab) / (2 * sizeof(CVector));
00748 
00749     const float sSize = 0.08f;
00750     displayIcon2d(tab, tabSize, sSize);
00751 }
00752 
00753 void CPSCentralGravity::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00754 {
00755     NL_PS_FUNC(CPSCentralGravity_IStream )
00756     f.serialVersion(1);
00757     CPSForceIntensityHelper::serial(f);
00758 }
00759 
00760 
00762 // CPSSpring  implementation   //
00764 
00765 
00766 
00767 void CPSSpring::computeForces(CPSLocated &target)
00768 {
00769     NL_PS_FUNC(CPSSpring_computeForces)
00770     nlassert(CParticleSystem::InsideSimLoop);
00771     // for each spring, and each target, we check if they are in the same basis
00772     // if not, we need to transform the spring attachment pos into the target basis
00773     uint32 size = _Owner->getSize();
00774     for (uint32 k = 0; k < size; ++k)
00775     {
00776         const float ellapsedTimexK = CParticleSystem::EllapsedTime  * (_IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K);
00777         const CMatrix &m = CPSLocated::getConversionMatrix(&target, this->_Owner);
00778         const CVector center = m * (_Owner->getPos()[k]);
00779         TPSAttribVector::iterator it = target.getSpeed().begin(), itEnd = target.getSpeed().end();
00780         TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
00781         TPSAttribVector::const_iterator posIt = target.getPos().begin();
00782         for (; it != itEnd; ++it, ++invMassIt, ++posIt)
00783         {
00784             // apply the spring equation
00785             (*it) += (*invMassIt) * ellapsedTimexK * (center - *posIt);
00786         }
00787     }
00788 }
00789 
00790 
00791 void CPSSpring::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00792 {
00793     NL_PS_FUNC(CPSSpring_serial)
00794     f.serialVersion(1);
00795     CPSForceIntensityHelper::serial(f);
00796 }
00797 
00798 
00799 
00800 void CPSSpring::show()
00801 {
00802     NL_PS_FUNC(CPSSpring_show)
00803     CVector I = CVector::I;
00804     CVector J = CVector::J;
00805     static const CVector tab[] =
00806     {
00807        -I + 2 * J,
00808        I + 2 * J,
00809        I + 2 * J, -I + J,
00810        -I + J, I + J,
00811        I + J, -I,
00812        -I, I,
00813        I, -I - J,
00814        -I - J, I - J,
00815        I - J,
00816        - I - 2 * J,
00817        - I - 2 * J,
00818        I - 2 * J
00819     };
00820     const uint tabSize = sizeof(tab) / (2 * sizeof(CVector));
00821     const float sSize = 0.08f;
00822     displayIcon2d(tab, tabSize, sSize);
00823 }
00824 
00825 
00827 //  CPSCylindricVortex implementation  //
00829 void CPSCylindricVortex::computeForces(CPSLocated &target)
00830 {
00831     NL_PS_FUNC(CPSCylindricVortex_computeForces)
00832     nlassert(CParticleSystem::InsideSimLoop);
00833     uint32 size = _Owner->getSize();
00834     for (uint32 k = 0; k < size; ++k) // for each vortex
00835     {
00836         const float invR = 1.f  / _Radius[k];
00837         const float radius2 = _Radius[k] * _Radius[k];
00838         // intensity for this vortex
00839         nlassert(_Owner);
00840         float intensity =  (_IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K);
00841         // express the vortex position and plane normal in the located basis
00842         const CMatrix &m = CPSLocated::getConversionMatrix(&target, this->_Owner);
00843         const CVector center = m * (_Owner->getPos()[k]);
00844         const CVector n = m.mulVector(_Normal[k]);
00845         TPSAttribVector::iterator speedIt = target.getSpeed().begin(), speedItEnd = target.getSpeed().end();
00846         TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
00847         TPSAttribVector::const_iterator posIt = target.getPos().begin();
00848         // projection of the current located pos on the vortex axis
00849         CVector p;
00850         // a vector that go from the vortex center to the point we're dealing with
00851         CVector v2p;
00852         // the square of the dist of the projected pos
00853         float d2 , d;
00854         CVector realTangentialSpeed;
00855         CVector tangentialSpeed;
00856         CVector radialSpeed;
00857         for (; speedIt != speedItEnd; ++speedIt, ++invMassIt, ++posIt)
00858         {
00859             v2p = *posIt - center;
00860             p = v2p - (v2p * n) * n;
00861             d2 = p * p;
00862             if (d2 < radius2) // not out of range ?
00863             {
00864                 if (d2 > 10E-6)
00865                 {
00866                     d = sqrtf(d2);
00867                     p *= 1.f / d;
00868                     // compute the speed vect that we should have (normalized)
00869                     realTangentialSpeed = n ^ p;
00870                     tangentialSpeed = (*speedIt * realTangentialSpeed) * realTangentialSpeed;
00871                     radialSpeed =  (p * *speedIt) * p;
00872                     // update radial speed;
00873                     *speedIt -= _RadialViscosity * CParticleSystem::EllapsedTime * radialSpeed;
00874                     // update tangential speed
00875                     *speedIt -= _TangentialViscosity * intensity * CParticleSystem::EllapsedTime * (tangentialSpeed - (1.f - d * invR) * realTangentialSpeed);
00876                 }
00877             }
00878         }
00879     }
00880 }
00881 
00882 
00883 void CPSCylindricVortex::show()
00884 {
00885     NL_PS_FUNC(CPSCylindricVortex_show)
00886     CPSLocated *loc;
00887     uint32 index;
00888     CPSLocatedBindable *lb;
00889     _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
00890 
00891 
00892     // must have set this
00893     nlassert(getFontGenerator() && getFontGenerator());
00894     setupDriverModelMatrix();
00895 
00896     for (uint k = 0; k < _Owner->getSize(); ++k)
00897     {
00898         const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
00899         CMatrix m;
00900         CPSUtil::buildSchmidtBasis(_Normal[k], m);
00901         CPSUtil::displayDisc(*getDriver(), _Radius[k], _Owner->getPos()[k], m, 32, col);
00902         CPSUtil::displayArrow(getDriver(), _Owner->getPos()[k], _Normal[k], 1.f, col, CRGBA(200, 0, 200));
00903         // display a V letter at the center
00904         CPSUtil::print(getDriver(), std::string("v"), *getFontGenerator(), *getFontManager(), _Owner->getPos()[k], 80.f);
00905     }
00906 
00907 }
00908 
00909 void CPSCylindricVortex::setMatrix(uint32 index, const CMatrix &m)
00910 {
00911     NL_PS_FUNC(CPSCylindricVortex_setMatrix)
00912     nlassert(index < _Normal.getSize());
00913     _Normal[index] = m.getK();
00914     _Owner->getPos()[index] = m.getPos();
00915 }
00916 
00917 CMatrix CPSCylindricVortex::getMatrix(uint32 index) const
00918 {
00919     NL_PS_FUNC(CPSCylindricVortex_getMatrix)
00920     CMatrix m;
00921     CPSUtil::buildSchmidtBasis(_Normal[index], m);
00922     m.setPos(_Owner->getPos()[index] );
00923     return m;
00924 }
00925 
00926 
00927 void CPSCylindricVortex::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00928 {
00929     NL_PS_FUNC(CPSCylindricVortex_IStream )
00930     f.serialVersion(1);
00931     CPSForceIntensityHelper::serial(f);
00932     f.serial(_Normal);
00933     f.serial(_Radius);
00934     f.serial(_RadialViscosity);
00935     f.serial(_TangentialViscosity);
00936 }
00937 
00938 void CPSCylindricVortex::newElement(const CPSEmitterInfo &info)
00939 {
00940     NL_PS_FUNC(CPSCylindricVortex_newElement)
00941     CPSForceIntensityHelper::newElement(info);
00942     _Normal.insert(CVector::K);
00943     _Radius.insert(1.f);
00944 }
00945 void CPSCylindricVortex::deleteElement(uint32 index)
00946 {
00947     NL_PS_FUNC(CPSCylindricVortex_deleteElement)
00948     CPSForceIntensityHelper::deleteElement(index);
00949     _Normal.remove(index);
00950     _Radius.remove(index);
00951 }
00952 void CPSCylindricVortex::resize(uint32 size)
00953 {
00954     NL_PS_FUNC(CPSCylindricVortex_resize)
00955     nlassert(size < (1 << 16));
00956     CPSForceIntensityHelper::resize(size);
00957     _Normal.resize(size);
00958     _Radius.resize(size);
00959 }
00960 
00961 
00966 void CPSMagneticForce::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00967 {
00968     NL_PS_FUNC(CPSMagneticForce_serial)
00969     f.serialVersion(1);
00970     CPSDirectionnalForce::serial(f);
00971 }
00972 
00973 void CPSMagneticForce::computeForces(CPSLocated &target)
00974 {
00975     NL_PS_FUNC(CPSMagneticForce_computeForces)
00976     nlassert(CParticleSystem::InsideSimLoop);
00977     // perform the operation on each target
00978     for (uint32 k = 0; k < _Owner->getSize(); ++k)
00979     {
00980         float intensity = CParticleSystem::EllapsedTime * (_IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K);
00981         NLMISC::CVector toAdd = CPSLocated::getConversionMatrix(&target, this->_Owner).mulVector(_Dir); // express this in the target basis
00982         TPSAttribVector::iterator it = target.getSpeed().begin(), itend = target.getSpeed().end();
00983         // 1st case : non-constant mass
00984         if (target.getMassScheme())
00985         {
00986             TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
00987             for (; it != itend; ++it, ++invMassIt)
00988             {
00989                 (*it) += intensity * *invMassIt * (*it ^ toAdd);
00990             }
00991         }
00992         else
00993         {
00994             float i = intensity / target.getInitialMass();
00995             for (; it != itend; ++it)
00996             {
00997                 (*it) += i * (*it ^ toAdd);
00998             }
00999         }
01000     }
01001 }
01002 
01003 
01008 const uint BFNumPredefinedPos    = 8192;    // should be a power of 2
01009 const uint BFPredefinedNumInterp = 256;     
01013 const uint BFNumPrecomputedImpulsions = 1024; 
01014 
01015 NLMISC::CVector CPSBrownianForce::PrecomputedPos[BFNumPredefinedPos]; // after the sequence we must be back to the start position
01016 NLMISC::CVector CPSBrownianForce::PrecomputedSpeed[BFNumPredefinedPos];
01017 NLMISC::CVector CPSBrownianForce::PrecomputedImpulsions[BFNumPrecomputedImpulsions];
01018 
01020 CPSBrownianForce::CPSBrownianForce(float intensity /* = 1.f*/) : _ParametricFactor(1.f)
01021 {
01022     NL_PS_FUNC(CPSBrownianForce_CPSBrownianForce)
01023     setIntensity(intensity);
01024     if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("BrownianForce");
01025 
01026 }
01027 
01029 bool    CPSBrownianForce::isIntegrable(void) const
01030 {
01031     NL_PS_FUNC(CPSBrownianForce_isIntegrable)
01032     return _IntensityScheme == NULL;
01033 }
01034 
01035 
01037 void CPSBrownianForce::integrate(float date, CPSLocated *src,
01038                                  uint32 startIndex,
01039                                  uint32 numObjects,
01040                                  NLMISC::CVector *destPos,
01041                                  NLMISC::CVector *destSpeed,
01042                                  bool accumulate,
01043                                  uint posStride, uint speedStride
01044                                 ) const
01045 {
01046     NL_PS_FUNC(CPSBrownianForce_integrate)
01048     float deltaT;
01049     if (!destPos && !destSpeed) return;
01050     CPSLocated::TPSAttribParametricInfo::const_iterator it = src->_PInfo.begin() + startIndex,
01051                                                         endIt = src->_PInfo.begin() + startIndex + numObjects;
01052     float lookUpFactor = _ParametricFactor * BFNumPredefinedPos;
01053     float speedFactor  = _ParametricFactor * _K;
01054     if (!accumulate) // compute coords from initial condition, and applying this force
01055     {
01056         if (destPos && !destSpeed) // fills dest pos only
01057         {
01058             while (it != endIt)
01059             {
01060                 float deltaT = date - it->Date;
01061                 uint index = (uint) (lookUpFactor * deltaT) & (BFNumPredefinedPos - 1);
01062                 destPos->set(it->Pos.x + deltaT * it->Speed.x + _K * PrecomputedPos[index].x,
01063                              it->Pos.y + deltaT * it->Speed.y + _K * PrecomputedPos[index].y,
01064                              it->Pos.z + deltaT * it->Speed.z + _K * PrecomputedPos[index].z );
01065                 ++it;
01066                 NEXT_POS;
01067             }
01068         }
01069         else if (!destPos && destSpeed) // fills dest speed only
01070         {
01071             while (it != endIt)
01072             {
01073                 deltaT = date - it->Date;
01074                 uint index = (uint) (lookUpFactor * deltaT) & (BFNumPredefinedPos - 1);
01075                 destSpeed->x = it->Speed.x  + speedFactor * PrecomputedSpeed[index].x;
01076                 destSpeed->y = it->Speed.y  + speedFactor * PrecomputedSpeed[index].y;
01077                 destSpeed->z = it->Speed.z  + speedFactor * PrecomputedSpeed[index].z;
01078                 ++it;
01079                 NEXT_SPEED;
01080             }
01081         }
01082         else // fills both speed and pos
01083         {
01084             while (it != endIt)
01085             {
01086                 deltaT = date - it->Date;
01087                 uint index = (uint) (lookUpFactor * deltaT) & (BFNumPredefinedPos - 1);
01088                 destPos->x = it->Pos.x + deltaT * it->Speed.x + _K * PrecomputedPos[index].x;
01089                 destPos->y = it->Pos.y + deltaT * it->Speed.y + _K * PrecomputedPos[index].y;
01090                 destPos->z = it->Pos.z + deltaT * it->Speed.z + _K * PrecomputedPos[index].z;
01091 
01092                 destSpeed->x = it->Speed.x + speedFactor * PrecomputedSpeed[index].x;
01093                 destSpeed->y = it->Speed.y + speedFactor * PrecomputedSpeed[index].y;
01094                 destSpeed->z = it->Speed.z + speedFactor * PrecomputedSpeed[index].z;
01095 
01096                 ++it;
01097                 NEXT_POS;
01098                 NEXT_SPEED;
01099             }
01100         }
01101     }
01102     else // accumulate datas
01103     {
01104         if (destPos && !destSpeed) // fills dest pos only
01105         {
01106             while (it != endIt)
01107             {
01108                 deltaT = date - it->Date;
01109                 uint index = (uint) (lookUpFactor * deltaT) & (BFNumPredefinedPos - 1);
01110                 destPos->set(destPos->x + _K * PrecomputedPos[index].x,
01111                              destPos->y + _K * PrecomputedPos[index].y,
01112                              destPos->z + _K * PrecomputedPos[index].z);
01113                 ++it;
01114                 NEXT_POS;
01115             }
01116         }
01117         else if (!destPos && destSpeed) // fills dest speed only
01118         {
01119             while (it != endIt)
01120             {
01121                 deltaT = date - it->Date;
01122                 uint index = (uint) (lookUpFactor * deltaT) & (BFNumPredefinedPos - 1);
01123                 destSpeed->set(destSpeed->x + speedFactor * PrecomputedSpeed[index].x,
01124                                destSpeed->y + speedFactor * PrecomputedSpeed[index].y,
01125                                destSpeed->z + speedFactor * PrecomputedSpeed[index].z);
01126                 ++it;
01127                 NEXT_SPEED;
01128             }
01129         }
01130         else // fills both speed and pos
01131         {
01132             while (it != endIt)
01133             {
01134                 deltaT = date - it->Date;
01135                 uint index = (uint) (lookUpFactor * deltaT) & (BFNumPredefinedPos - 1);
01136                 destPos->set(destPos->x + _K * PrecomputedPos[index].x,
01137                              destPos->y + _K * PrecomputedPos[index].y,
01138                              destPos->z + _K * PrecomputedPos[index].z);
01139                 destSpeed->set(destSpeed->x + speedFactor * PrecomputedSpeed[index].x,
01140                                destSpeed->y + speedFactor * PrecomputedSpeed[index].y,
01141                                destSpeed->z + speedFactor * PrecomputedSpeed[index].z);
01142                 ++it;
01143                 NEXT_POS;
01144                 NEXT_SPEED;
01145             }
01146         }
01147     }
01148 }
01149 
01150 
01152 void CPSBrownianForce::integrateSingle(float startDate, float deltaT, uint numStep,
01153                                  const CPSLocated *src, uint32 indexInLocated,
01154                                  NLMISC::CVector *destPos,
01155                                  bool accumulate,
01156                                  uint stride) const
01157 {
01158     NL_PS_FUNC(CPSBrownianForce_integrateSingle)
01159     nlassert(src->isParametricMotionEnabled());
01160     //nlassert(deltaT > 0);
01161     nlassert(numStep > 0);
01162     #ifdef NL_DEBUG
01163         NLMISC::CVector *endPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride * numStep);
01164     #endif
01165     const CPSLocated::CParametricInfo &pi = src->_PInfo[indexInLocated];
01166     const NLMISC::CVector &startPos   = pi.Pos;
01167     if (numStep != 0)
01168     {
01169         float lookUpFactor = _ParametricFactor * BFPredefinedNumInterp;
01170         if (!accumulate)
01171         {
01173             destPos = FillBufUsingSubdiv(startPos, pi.Date, startDate, deltaT, numStep, destPos, stride);
01174             if (numStep != 0)
01175             {
01176                 float currDate = startDate - pi.Date;
01177                 nlassert(currDate >= 0);
01178                 const NLMISC::CVector &startSpeed = pi.Speed;
01179                 do
01180                 {
01181                     #ifdef NL_DEBUG
01182                         nlassert(destPos < endPos);
01183                     #endif
01184                     uint index = (uint) (lookUpFactor * currDate) & (BFNumPredefinedPos - 1);
01185                     destPos->x = startPos.x + currDate * startSpeed.x + _K * PrecomputedPos[index].x;
01186                     destPos->y = startPos.y + currDate * startSpeed.y + _K * PrecomputedPos[index].y;
01187                     destPos->z = startPos.z + currDate * startSpeed.z + _K * PrecomputedPos[index].z;
01188                     currDate += deltaT;
01189                     destPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride);
01190                 }
01191                 while (--numStep);
01192             }
01193         }
01194         else
01195         {
01196             uint numToSkip = ScaleFloatGE(startDate, deltaT, pi.Date, numStep);
01197             if (numToSkip < numStep)
01198             {
01199                 numStep -= numToSkip;
01200                 float currDate = startDate + deltaT * numToSkip - pi.Date;
01201                 do
01202                 {
01203                     #ifdef NL_DEBUG
01204                         nlassert(destPos < endPos);
01205                     #endif
01206                     uint index = (uint) (lookUpFactor * currDate) & (BFNumPredefinedPos - 1);
01207                     destPos->x += _K * PrecomputedPos[index].x;
01208                     destPos->y += _K * PrecomputedPos[index].y;
01209                     destPos->z += _K * PrecomputedPos[index].z;
01210                     currDate += deltaT;
01211                     destPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride);
01212                 }
01213                 while (--numStep);
01214             }
01215         }
01216     }
01217 }
01218 
01219 
01221 void CPSBrownianForce::initPrecalc()
01222 {
01223     NL_PS_FUNC(CPSBrownianForce_initPrecalc)
01225     nlassert(BFNumPredefinedPos % BFPredefinedNumInterp == 0);
01226 
01227     NLMISC::CVector p0(0, 0, 0), p1;
01228     const uint numStep = BFNumPredefinedPos / BFPredefinedNumInterp;
01229     NLMISC::CVector *dest = PrecomputedPos;
01230     uint k, l;
01231     for (k = 0; k < numStep; ++k)
01232     {
01233         if (k != numStep - 1)
01234         {
01235             p1.set(2.f * (NLMISC::frand(1.f) - 0.5f),
01236                    2.f * (NLMISC::frand(1.f) - 0.5f),
01237                    2.f * (NLMISC::frand(1.f) - 0.5f));
01238         }
01239         else
01240         {
01241             p1.set(0, 0, 0);
01242         }
01243         float lambda     = 0.f;
01244         float lambdaStep = 1.f / BFPredefinedNumInterp;
01245         for (l = 0; l < BFPredefinedNumInterp; ++l)
01246         {
01247             *dest++ = lambda * p1 + (1.f - lambda) * p0;
01248             lambda += lambdaStep;
01249         }
01250         p0 = p1;
01251     }
01252 
01253     // now, filter the table several time to get something more smooth
01254     for (k = 0; k < (BFPredefinedNumInterp << 2) ; ++k)
01255     {
01256         for (l = 1; l < (BFNumPredefinedPos - 1); ++l)
01257         {
01258             PrecomputedPos[l] = 0.5f * (PrecomputedPos[l - 1] + PrecomputedPos[l + 1]);
01259         }
01260     }
01261 
01262 
01263     // compute the table of speeds, by using on a step of 1.s
01264     for (l = 1; l < (BFNumPredefinedPos - 1); ++l)
01265     {
01266         PrecomputedSpeed[l] = 0.5f * (PrecomputedPos[l + 1] - PrecomputedPos[l - 1]);
01267     }
01268     PrecomputedSpeed[BFNumPredefinedPos - 1] = NLMISC::CVector::Null;
01269 
01270     // compute the table of impulsion
01271     for (k = 0; k < BFNumPrecomputedImpulsions; ++k)
01272     {
01273         static double divRand = (2.f / RAND_MAX);
01274         PrecomputedImpulsions[k].set( (float) (rand() * divRand - 1),
01275                                       (float) (rand() * divRand - 1),
01276                                       (float) (rand() * divRand - 1)
01277                                     );
01278     }
01279 }
01280 
01282 void CPSBrownianForce::setIntensity(float value)
01283 {
01284     NL_PS_FUNC(CPSBrownianForce_setIntensity)
01285     if (_IntensityScheme)
01286     {
01287         CPSForceIntensity::setIntensity(value);
01288         renewIntegrable(); // integrable again
01289     }
01290     else
01291     {
01292         CPSForceIntensity::setIntensity(value);
01293     }
01294 }
01295 
01296 
01298 void CPSBrownianForce::setIntensityScheme(CPSAttribMaker<float> *scheme)
01299 {
01300     NL_PS_FUNC(CPSBrownianForce_setIntensityScheme)
01301     if (!_IntensityScheme)
01302     {
01303         cancelIntegrable(); // not integrable anymore
01304     }
01305     CPSForceIntensity::setIntensityScheme(scheme);
01306 }
01307 
01309 void CPSBrownianForce::computeForces(CPSLocated &target)
01310 {
01311     NL_PS_FUNC(CPSBrownianForce_computeForces)
01312     nlassert(CParticleSystem::InsideSimLoop);
01313     // perform the operation on each target
01314     for (uint32 k = 0; k < _Owner->getSize(); ++k)
01315     {
01316         float intensity = _IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K;
01317         uint32 size = target.getSize();
01318         if (!size) continue;
01319         TPSAttribVector::iterator it2 = target.getSpeed().begin(), it2End;
01321         uint startPos = (uint) ::rand() % BFNumPrecomputedImpulsions;
01322         NLMISC::CVector *imp = PrecomputedImpulsions + startPos;
01323 
01324         if (target.getMassScheme())
01325         {
01326             float intensityXtime = intensity * CParticleSystem::EllapsedTime;
01327             TPSAttribFloat::const_iterator invMassIt = target.getInvMass().begin();
01328             do
01329             {
01330                 uint toProcess = std::min((uint) (BFNumPrecomputedImpulsions - startPos), (uint) size);
01331                 it2End = it2 + toProcess;
01332                 do
01333                 {
01334                     float factor = intensityXtime * *invMassIt;
01335                     it2->set(it2->x + factor * imp->x,
01336                             it2->y + factor * imp->y,
01337                             it2->z + factor * imp->x);
01338                     ++invMassIt;
01339                     ++imp;
01340                     ++it2;
01341                 }
01342                 while (it2 != it2End);
01343                 startPos = 0;
01344                 imp = PrecomputedImpulsions;
01345                 size -= toProcess;
01346             }
01347             while (size != 0);
01348         }
01349         else
01350         {
01351             do
01352             {
01353                 uint toProcess = std::min((uint) (BFNumPrecomputedImpulsions - startPos) , (uint) size);
01354                 it2End = it2 + toProcess;
01355                 float factor = intensity * CParticleSystem::EllapsedTime / target.getInitialMass();
01356                 do
01357                 {
01358                     it2->set(it2->x + factor * imp->x,
01359                             it2->y + factor * imp->y,
01360                             it2->z + factor * imp->x);
01361                     ++imp;
01362                     ++it2;
01363                 }
01364                 while (it2 != it2End);
01365                 startPos = 0;
01366                 imp = PrecomputedImpulsions;
01367                 size -= toProcess;
01368             }
01369             while (size != 0);
01370         }
01371     }
01372 }
01373 
01375 void CPSBrownianForce::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
01376 {
01377     NL_PS_FUNC(CPSBrownianForce_serial)
01378     sint ver = f.serialVersion(3);
01379     if (ver <= 2)
01380     {
01381         uint8 dummy;
01382         f.serial(dummy); // old data in version 2 not used anymore
01383         CPSForce::serial(f);
01384         f.serial(dummy); // old data in version 2 not used anymore
01385         serialForceIntensity(f);
01386         if (f.isReading())
01387         {
01388             registerToTargets();
01389         }
01390     }
01391 
01392     if (ver >= 2)
01393     {
01394         CPSForceIntensityHelper::serial(f);
01395         f.serial(_ParametricFactor);
01396     }
01397 }
01398 
01399 
01400 } // NL3D

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