From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/ps__force_8cpp-source.html | 1448 +++++++++++++++++++++++++++ 1 file changed, 1448 insertions(+) create mode 100644 docs/doxygen/nel/ps__force_8cpp-source.html (limited to 'docs/doxygen/nel/ps__force_8cpp-source.html') diff --git a/docs/doxygen/nel/ps__force_8cpp-source.html b/docs/doxygen/nel/ps__force_8cpp-source.html new file mode 100644 index 00000000..d7bbb256 --- /dev/null +++ b/docs/doxygen/nel/ps__force_8cpp-source.html @@ -0,0 +1,1448 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# 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.cpp

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