00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
00252
00253 void CPSDirectionnalForce::computeForces(CPSLocated &target)
00254 {
00255 NL_PS_FUNC(CPSDirectionnalForce_computeForces)
00256 nlassert(CParticleSystem::InsideSimLoop);
00257
00258 CVector toAdd;
00259 for (uint32 k = 0; k < _Owner->getSize(); ++k)
00260 {
00261 CVector toAddLocal;
00262 CVector dir;
00263
00264 if (_GlobalValueHandle.isValid())
00265 {
00266 dir = _GlobalValueHandle.get();
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);
00274 TPSAttribVector::iterator it = target.getSpeed().begin(), itend = target.getSpeed().end();
00275
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
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())
00310 {
00311 dir = _GlobalValueHandle.get();
00312 }
00313 else
00314 {
00315 dir = _Dir;
00316 }
00317
00318
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
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
00345 if (f.isReading())
00346 {
00347 std::string handleName;
00348 f.serial(handleName);
00349
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
00385 void CPSGravity::computeForces(CPSLocated &target)
00386 {
00387 NL_PS_FUNC(CPSGravity_computeForces)
00388 nlassert(CParticleSystem::InsideSimLoop);
00389
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);
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
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
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
00475
00476 CVector pos = *it + CVector(1.5f * toolSize, 0, -1.2f * toolSize);
00477
00478 pos = getLocalToWorldMatrix() * pos;
00479
00480
00481
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)
00524 {
00525 if (destPos && !destSpeed)
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)
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
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
00569 {
00570 if (destPos && !destSpeed)
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)
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
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 ,
00612 uint stride) const
00613 {
00614 NL_PS_FUNC(CPSGravity_CVector )
00615 nlassert(src->isParametricMotionEnabled());
00616
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();
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();
00692 }
00693 CPSForceIntensityHelper::setIntensityScheme(scheme);
00694 }
00695
00696
00698
00700
00701 void CPSCentralGravity::computeForces(CPSLocated &target)
00702 {
00703 NL_PS_FUNC(CPSCentralGravity_computeForces)
00704 nlassert(CParticleSystem::InsideSimLoop);
00705
00706
00707 uint32 size = _Owner->getSize();
00708
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
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
00764
00765
00766
00767 void CPSSpring::computeForces(CPSLocated &target)
00768 {
00769 NL_PS_FUNC(CPSSpring_computeForces)
00770 nlassert(CParticleSystem::InsideSimLoop);
00771
00772
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
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
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)
00835 {
00836 const float invR = 1.f / _Radius[k];
00837 const float radius2 = _Radius[k] * _Radius[k];
00838
00839 nlassert(_Owner);
00840 float intensity = (_IntensityScheme ? _IntensityScheme->get(_Owner, k) : _K);
00841
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
00849 CVector p;
00850
00851 CVector v2p;
00852
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)
00863 {
00864 if (d2 > 10E-6)
00865 {
00866 d = sqrtf(d2);
00867 p *= 1.f / d;
00868
00869 realTangentialSpeed = n ^ p;
00870 tangentialSpeed = (*speedIt * realTangentialSpeed) * realTangentialSpeed;
00871 radialSpeed = (p * *speedIt) * p;
00872
00873 *speedIt -= _RadialViscosity * CParticleSystem::EllapsedTime * radialSpeed;
00874
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
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
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
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);
00982 TPSAttribVector::iterator it = target.getSpeed().begin(), itend = target.getSpeed().end();
00983
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;
01009 const uint BFPredefinedNumInterp = 256;
01013 const uint BFNumPrecomputedImpulsions = 1024;
01014
01015 NLMISC::CVector CPSBrownianForce::PrecomputedPos[BFNumPredefinedPos];
01016 NLMISC::CVector CPSBrownianForce::PrecomputedSpeed[BFNumPredefinedPos];
01017 NLMISC::CVector CPSBrownianForce::PrecomputedImpulsions[BFNumPrecomputedImpulsions];
01018
01020 CPSBrownianForce::CPSBrownianForce(float intensity ) : _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)
01055 {
01056 if (destPos && !destSpeed)
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)
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
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
01103 {
01104 if (destPos && !destSpeed)
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)
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
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
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
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
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
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();
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();
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
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);
01383 CPSForce::serial(f);
01384 f.serial(dummy);
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 }