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/a06287.html | 1474 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1474 insertions(+) create mode 100644 docs/doxygen/nel/a06287.html (limited to 'docs/doxygen/nel/a06287.html') diff --git a/docs/doxygen/nel/a06287.html b/docs/doxygen/nel/a06287.html new file mode 100644 index 00000000..aa25e520 --- /dev/null +++ b/docs/doxygen/nel/a06287.html @@ -0,0 +1,1474 @@ + + +NeL: ps_zone.cpp Source File + + + +
+

ps_zone.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_zone.h"
+00029 #include "3d/vertex_buffer.h"
+00030 #include "3d/primitive_block.h"
+00031 #include "3d/material.h"
+00032 #include "3d/ps_util.h"
+00033 #include "3d/dru.h"
+00034 #include "3d/particle_system.h"
+00035 #include "nel/misc/plane.h"
+00036 
+00037 // tmp
+00038 
+00039 #include "3d/particle_system_model.h"
+00040 
+00041 #include <math.h>
+00042 #include <limits>
+00043 
+00044 namespace NL3D {
+00045 
+00046 
+00047 /*
+00048  * Constructor
+00049  */
+00050 CPSZone::CPSZone() : _BounceFactor(1.f), _CollisionBehaviour(bounce)
+00051 {
+00052 }
+00053 
+00054 void CPSZone::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+00055 { 
+00056         f.serialVersion(1);
+00057         CPSTargetLocatedBindable::serial(f); 
+00058         f.serialEnum(_CollisionBehaviour);
+00059         f.serial(_BounceFactor);
+00060         if (f.isReading())
+00061         {               
+00062                 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+00063                 {
+00064                         // though this is not a force, this prevent parametric motion
+00065                         (*it)->addNonIntegrableForceRef();
+00066                 }       
+00067         }
+00068 }
+00069 
+00073 void CPSZone::attachTarget(CPSLocated *ptr)
+00074 {
+00075                 
+00076         CPSTargetLocatedBindable::attachTarget(ptr);
+00077         ptr->queryCollisionInfo();
+00078         ptr->addNonIntegrableForceRef();
+00079 }
+00080 
+00081 
+00082 
+00083 
+00084 
+00086 void CPSZone::releaseTargetRsc(CPSLocated *target)
+00087 {
+00088         // tell the target that we were using collision infos and that we won't use them anymore
+00089         target->releaseCollisionInfo();
+00090         target->releaseNonIntegrableForceRef();
+00091 }
+00092 
+00093 
+00094 
+00095 void CPSZone::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
+00096 {
+00097         // for zone, the PSCollision pass and the PSToolRenderPass are processed
+00098         switch(pass)
+00099         {
+00100                 case PSCollision:
+00101                         performMotion(ellapsedTime);
+00102                         break;
+00103                 case PSToolRender:
+00104                         show(ellapsedTime);
+00105                         break;
+00106                 default: break;
+00107         }
+00108 }
+00109 
+00110 
+00111 // build a basis with K = the normal of the plane
+00112 CMatrix CPSZonePlane::buildBasis(uint32 index) const
+00113 {
+00114         CMatrix m;
+00115         m.setPos(_Owner->getPos()[index]);      
+00116         CPSUtil::buildSchmidtBasis(_Normal[index], m);
+00117         return m;
+00118 }
+00119 
+00120 
+00123 /*void CPSZone::bounce(uint32 locatedIndex, const CVector &bouncePoint, const CVector &surfNormal, float elasticity, TAnimationTime ellapsedTime)
+00124 {
+00125         CVector &speed = _Owner->getSpeed()[locatedIndex];
+00126         const CVector &pos   = _Owner->getPos()[locatedIndex];
+00127         CVector &bounceVect = elasticity  * (speed - 2.0f * (speed * surfNormal) * surfNormal); // speed vector after collision
+00128         // now check where the located will be after integration
+00129         CVector d = bouncePoint - pos;
+00130         TAnimationTime collideDelay = speed.norm() / d.norm();
+00131         CVector finalPos = bouncePoint + (ellapsedTime - collideDelay) * bounceVect;
+00132         // now, we must have pos + ellapsedTime * newSpeed = finalPos 
+00133         // newSpeed = alpha * (finalPos - pos)
+00134         // so alpha = 1 / ellapsedTime
+00135 
+00136         speed = (1.0f / ellapsedTime) * (finalPos - pos);       
+00137 }*/
+00138 
+00139 
+00140 void CPSZonePlane::show(TAnimationTime)
+00141 {
+00142         const float planeSize = 2.0f;
+00143         setupDriverModelMatrix();
+00144 
+00145         IDriver *driver = getDriver();
+00146         uint k  = 0;
+00147 
+00148         setupDriverModelMatrix();
+00149 
+00150         CPSLocated *loc;
+00151         uint32 index;
+00152         CPSLocatedBindable *lb;
+00153         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+00154         
+00155 
+00156 
+00157                 
+00158 
+00159         for (TPSAttribVector::const_iterator it = _Owner->getPos().begin(); it != _Owner->getPos().end(); ++it, ++k)
+00160         {       
+00161                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
+00162                 CMatrix mat = buildBasis(k);
+00163 
+00164                 CPSUtil::displayBasis(getDriver(), getLocalToWorldMatrix(), mat, 1.f, *getFontGenerator(), *getFontManager());
+00165 
+00166 
+00167                 setupDriverModelMatrix();
+00168         
+00169                 CDRU::drawLine(*it + (planeSize  + 3) * mat.getI() + planeSize * mat.getJ() 
+00170                                                 , *it - (planeSize + 3) * mat.getI() + planeSize * mat.getJ()
+00171                                                 , col
+00172                                                 , *driver);
+00173 
+00174                 CDRU::drawLine(*it + (planeSize  + 3) * mat.getI() - planeSize * mat.getJ() 
+00175                                                 , *it - (planeSize + 3) * mat.getI() - planeSize * mat.getJ()
+00176                                                 , col
+00177                                                 , *driver);
+00178 
+00179                 CDRU::drawLine(*it + planeSize  * mat.getI() + (planeSize + 3) * mat.getJ() 
+00180                                                 , *it + planeSize * mat.getI() - (planeSize + 3) * mat.getJ()
+00181                                                 , col
+00182                                                 , *driver);
+00183                 CDRU::drawLine(*it - planeSize  * mat.getI() + (planeSize + 3) * mat.getJ() 
+00184                                                 , *it - planeSize * mat.getI() - (planeSize + 3) * mat.getJ()
+00185                                                 , col
+00186                                                 , *driver);
+00187         }
+00188         
+00189 
+00190 }
+00191 
+00192 
+00193 
+00194 void CPSZonePlane::resize(uint32 size)
+00195 {
+00196         nlassert(size < (1 << 16));
+00197         _Normal.resize(size);
+00198 }
+00199 
+00200 
+00201 void CPSZonePlane::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+00202 {
+00203         nlassert(_Normal.getSize() != _Normal.getMaxSize());
+00204         _Normal.insert(CVector(0, 0, 1));
+00205 }
+00206 
+00207 
+00208 void CPSZonePlane::deleteElement(uint32 index)
+00209 {
+00210         _Normal.remove(index);
+00211 }
+00212 
+00213 
+00214 
+00215 void CPSZonePlane::performMotion(TAnimationTime ellapsedTime)
+00216 {
+00217         MINI_TIMER(PSStatsZonePlane)
+00218         // for each target, we must check wether they are going through the plane
+00219         // if so they must bounce
+00220         TPSAttribVector::const_iterator planePosIt, planePosEnd, normalIt, targetPosIt, targetPosEnd;
+00221         CVector dest;
+00222         CPSCollisionInfo ci;
+00223         CVector startEnd;
+00224         uint32 k;
+00225         const TPSAttribVector *speedAttr;
+00226         float posSide, negSide;
+00227 
+00228         // alpha is the ratio that gives the percent of endPos - startPos that hit the plane
+00229         float alpha; 
+00230 
+00231         for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+00232         {
+00233 
+00234                 speedAttr = &((*it)->getSpeed());
+00235                 // cycle through the planes
+00236 
+00237                 planePosEnd = _Owner->getPos().end();           
+00238                 for (planePosIt = _Owner->getPos().begin(), normalIt = _Normal.begin(); planePosIt != planePosEnd
+00239                                 ; ++planePosIt, ++normalIt)
+00240                 {
+00241                         
+00242                         // we must setup the plane in the good basis
+00243 
+00244                         const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
+00245                         const float epsilon = 0.5f * PSCollideEpsilon;
+00246                         
+00247 
+00248                         NLMISC::CPlane p;
+00249                         p.make(m.mulVector(*normalIt), m * (*planePosIt));              
+00250                         
+00251                         // deals with each particle
+00252                         
+00253                         targetPosEnd = (*it)->getPos().end();
+00254                         TPSAttribCollisionInfo::const_iterator ciIt = (*it)->getCollisionInfo().begin();
+00255                         for (targetPosIt = (*it)->getPos().begin(), k = 0; targetPosIt != targetPosEnd; ++targetPosIt, ++k, ++ciIt)
+00256                         {       
+00257                                 const CVector &speed = (*speedAttr)[k];
+00258                                 // check whether the located is going through the plane
+00259                                 dest = *targetPosIt + ellapsedTime *  speed * ciIt->TimeSliceRatio;
+00260 
+00261 
+00262                                 posSide = p * *targetPosIt;
+00263                                 negSide = p * dest;
+00264                                                                                                 
+00265                                 if (posSide >= - epsilon && negSide <= epsilon)
+00266                                 {
+00267                                         if (fabsf(posSide - negSide) > std::numeric_limits<float>::min())
+00268                                         {
+00269                                                 alpha = posSide / (posSide - negSide);
+00270                                         }
+00271                                         else
+00272                                         {
+00273                                                 alpha = 0.f;
+00274                                         }
+00275                                         startEnd = alpha * (dest - *targetPosIt);                                       
+00276                                         ci.dist = startEnd.norm();
+00277                                         // we translate the particle from an epsilon so that it won't get hooked to the plane
+00278                                         ci.newPos = *targetPosIt  + startEnd + PSCollideEpsilon * p.getNormal();                                
+00279                                         ci.newSpeed = _BounceFactor * (speed - 2.0f * (speed * p.getNormal()) * p.getNormal());
+00280                                         ci.collisionZone = this;                                                
+00281                                         (*it)->collisionUpdate(ci, k);                                                                          
+00282                                 }
+00283                         }
+00284                 }
+00285         }
+00286 }
+00287 
+00288 void CPSZonePlane::setMatrix(uint32 index, const CMatrix &m)
+00289 {
+00290         nlassert(index < _Normal.getSize());
+00291         _Normal[index] = m.getK();
+00292         _Owner->getPos()[index] = m.getPos();   
+00293 }
+00294 
+00295 CMatrix CPSZonePlane::getMatrix(uint32 index) const
+00296 {
+00297         return buildBasis(index);
+00298 }
+00299 
+00300 
+00301 CVector CPSZonePlane::getNormal(uint32 index)
+00302 {
+00303         return _Normal[index];
+00304 }
+00305 void CPSZonePlane::setNormal(uint32 index, CVector n)
+00306 {
+00307         _Normal[index] = n;
+00308 }
+00309 
+00310 
+00311 
+00312 
+00313 void CPSZonePlane::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+00314 {
+00315         f.serialVersion(1);             
+00316         CPSZone::serial(f);     
+00317         f.serial(_Normal);      
+00318 }
+00319 
+00320 
+00321 
+00323 // sphere implementation //
+00325 
+00326 
+00327 
+00328 
+00329 void CPSZoneSphere::performMotion(TAnimationTime ellapsedTime)
+00330 {
+00331         MINI_TIMER(PSStatsZoneSphere)           
+00332         // for each target, we must check wether they are going through the plane
+00333         // if so they must bounce
+00334 
+00335         TPSAttribRadiusPair::const_iterator radiusIt = _Radius.begin();
+00336         TPSAttribVector::const_iterator spherePosIt, spherePosEnd, targetPosIt, targetPosEnd;
+00337         CVector dest;
+00338         CPSCollisionInfo ci;
+00339         uint32 k;
+00340         const TPSAttribVector *speedAttr;
+00341 
+00342 
+00343         float rOut, rIn;
+00344 
+00345 
+00346         for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+00347         {
+00348 
+00349                 speedAttr = &((*it)->getSpeed());
+00350 
+00351 
+00352                 // cycle through the spheres
+00353                         
+00354                 spherePosEnd = _Owner->getPos().end();
+00355                 for (spherePosIt = _Owner->getPos().begin(), radiusIt = _Radius.begin(); spherePosIt != spherePosEnd
+00356                                 ; ++spherePosIt, ++radiusIt)
+00357                 {
+00358                         
+00359                         // we must setup the sphere in the good basis
+00360 
+00361                         const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
+00362 
+00363                         
+00364 
+00365                         CVector center = m * *spherePosIt;
+00366                                                 
+00367                         // deals with each particle
+00368 
+00369 
+00370                         targetPosEnd = (*it)->getPos().end();
+00371                         TPSAttribCollisionInfo::const_iterator ciIt = (*it)->getCollisionInfo().begin();
+00372                         for (targetPosIt = (*it)->getPos().begin(), k = 0; targetPosIt != targetPosEnd; ++targetPosIt, ++k, ++ciIt)
+00373                         {       
+00374                                 const CVector &speed = (*speedAttr)[k];
+00375                                 const CVector &pos = *targetPosIt;
+00376                                 // check whether the located is going through the sphere
+00377 
+00378                                 // we don't use raytracing for now because it is too slow ...
+00379                                         
+00380 
+00381                                 rOut = (pos - center) * (pos - center);
+00382 
+00383                                 // initial position outside the sphere ?
+00384                                 if (rOut > radiusIt->R2)
+00385                                 {
+00386                                         dest = pos + ellapsedTime *  speed * ciIt->TimeSliceRatio;
+00387                                         rIn = (dest - center) * (dest - center);
+00388 
+00389                                         const CVector D = dest - pos;
+00390 
+00391                                         // final position inside the sphere ?
+00392 
+00393                                         if ( rIn <= radiusIt->R2)
+00394                                         {                               
+00395                                                 // discriminant of the intersection equation
+00396                                                 const float b = 2.f * (pos * D - D * center), a = D * D
+00397                                                                         , c = (pos * pos) + (center * center) - 2.f * (pos * center) - radiusIt->R2;
+00398                                                 float d = b * b - 4 * a * c;
+00399 
+00400                                                 
+00401                                                 if (d <= 0.f) continue; // should never happen, but we never know ...
+00402                                                 
+00403 
+00404                                                 d = sqrtf(d);
+00405 
+00406                                                 // roots of the equation, we take the smallest 
+00407 
+00408 
+00409                                                 const float r1 = .5f * (-b + 2.f * d) * a
+00410                                                                         , r2 = .5f * (-b - 2.f * d) * a;
+00411 
+00412                                                 const float  r = std::min(r1, r2);
+00413 
+00414                                                 // collision point 
+00415 
+00416                                                 const CVector C = pos  + r * D;
+00417 
+00418 
+00419 
+00420 
+00421                                 
+00422                                     
+00423                                                 const float alpha = ((C - pos) * D) * a;
+00424 
+00425                                                 const CVector startEnd = alpha * (dest - pos);                                  
+00426 
+00427                                                 CVector normal = C - center;
+00428                                                 normal = normal * (1.f / radiusIt->R);
+00429 
+00430                                         
+00431                                                 ci.dist = startEnd.norm();
+00432                                                 // we translate the particle from an epsilon so that it won't get hooked to the sphere
+00433                                                 ci.newPos = pos  + startEnd + PSCollideEpsilon * normal;                                
+00434                                                 ci.newSpeed = _BounceFactor * (speed - 2.0f * (speed * normal) * normal);
+00435 
+00436                                                 ci.collisionZone = this;                                                
+00437                                                 (*it)->collisionUpdate(ci, k);
+00438                                                 
+00439                                         }                                       
+00440                                 }
+00441                         }
+00442                 }
+00443         }
+00444 }
+00445 
+00446 
+00447 
+00448 void CPSZoneSphere::show(TAnimationTime ellapsedTime)
+00449 {
+00450         
+00451         CPSLocated *loc;
+00452         uint32 index;
+00453         CPSLocatedBindable *lb;
+00454         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+00455 
+00456 
+00457         TPSAttribRadiusPair::const_iterator radiusIt = _Radius.begin();
+00458         TPSAttribVector::const_iterator posIt = _Owner->getPos().begin(), endPosIt = _Owner->getPos().end();
+00459         setupDriverModelMatrix();       
+00460         for (uint k = 0; posIt != endPosIt; ++posIt, ++radiusIt, ++k) 
+00461         {       
+00462                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));             
+00463                 CPSUtil::displaySphere(*getDriver(), radiusIt->R, *posIt, 5, col);
+00464         }
+00465 }
+00466         
+00467 void CPSZoneSphere::setMatrix(uint32 index, const CMatrix &m)
+00468 {
+00469         nlassert(index < _Radius.getSize());
+00470                 
+00471         // compute new pos
+00472         _Owner->getPos()[index] = m.getPos();
+00473         
+00474 }
+00475 
+00476 
+00477 CMatrix CPSZoneSphere::getMatrix(uint32 index) const
+00478 {
+00479         nlassert(index < _Radius.getSize());
+00480         CMatrix m;
+00481         m.identity();
+00482         m.translate(_Owner->getPos()[index]);   
+00483         return m; 
+00484 }
+00485 
+00486 void CPSZoneSphere::setScale(uint32 k, float scale)
+00487 {
+00488         _Radius[k].R = scale;
+00489         _Radius[k].R2 = scale * scale;
+00490 }
+00491 CVector CPSZoneSphere::getScale(uint32 k) const
+00492 {
+00493         return CVector(_Radius[k].R, _Radius[k].R, _Radius[k].R);
+00494 }
+00495 
+00496 
+00497 void CPSZoneSphere::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+00498 {
+00499         f.serialVersion(1);
+00500         CPSZone::serial(f);
+00501         f.serial(_Radius);      
+00502 }
+00503 
+00504 
+00505                 
+00506 
+00507 
+00508 
+00509 void CPSZoneSphere::resize(uint32 size)
+00510 {
+00511         nlassert(size < (1 << 16));
+00512         _Radius.resize(size);
+00513 }
+00514 
+00515 void CPSZoneSphere::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+00516 {
+00517         CRadiusPair rp;
+00518         rp.R = rp.R2 = 1.f;
+00519         nlassert(_Radius.getSize() != _Radius.getMaxSize());
+00520         _Radius.insert(rp);
+00521 }
+00522 
+00523 void CPSZoneSphere::deleteElement(uint32 index)
+00524 {
+00525         _Radius.remove(index);
+00526 }
+00527 
+00528 
+00530 // CPSZoneDisc implementation //
+00532 
+00533 void CPSZoneDisc::performMotion(TAnimationTime ellapsedTime)
+00534 {
+00535         MINI_TIMER(PSStatsZoneDisc)             
+00536         // for each target, we must check wether they are going through the disc
+00537         // if so they must bounce
+00538         TPSAttribVector::const_iterator discPosIt, discPosEnd, normalIt, targetPosIt, targetPosEnd;
+00539         TPSAttribRadiusPair::const_iterator radiusIt;
+00540         CVector dest;
+00541         CPSCollisionInfo ci;
+00542         CVector startEnd;
+00543         uint32 k;
+00544         const TPSAttribVector *speedAttr;
+00545         float posSide, negSide;
+00546 
+00547         // the square of radius at the hit point
+00548         float hitRadius2; 
+00549 
+00550         // alpha is the ratio that gives the percent of endPos - startPos that hit the disc
+00551         float alpha; 
+00552 
+00553         CVector center;
+00554 
+00555         for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+00556         {
+00557 
+00558                 speedAttr = &((*it)->getSpeed());
+00559                 // cycle through the disc
+00560 
+00561                 discPosEnd = _Owner->getPos().end();
+00562                 for (discPosIt = _Owner->getPos().begin(), radiusIt = _Radius.begin(), normalIt = _Normal.begin(); discPosIt != discPosEnd
+00563                                 ; ++discPosIt, ++normalIt, ++radiusIt)
+00564                 {
+00565                         
+00566                         // we must setup the disc in the good basis
+00567 
+00568                         const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
+00569 
+00570                         
+00571 
+00572                         NLMISC::CPlane p;
+00573                         center = m * (*discPosIt);
+00574                         p.make(m.mulVector(*normalIt), center);         
+00575                         
+00576                         // deals with each particle
+00577 
+00578                         const float epsilon = 0.5f * PSCollideEpsilon;
+00579 
+00580                         targetPosEnd = (*it)->getPos().end();
+00581                         TPSAttribCollisionInfo::const_iterator ciIt = (*it)->getCollisionInfo().begin();
+00582                         for (targetPosIt = (*it)->getPos().begin(), k = 0; targetPosIt != targetPosEnd; ++targetPosIt, ++k, ++ciIt)
+00583                         {       
+00584                                 const CVector &speed = (*speedAttr)[k];
+00585                                 // check whether the located is going through the disc
+00586                                 dest = *targetPosIt + ellapsedTime *  speed * ciIt->TimeSliceRatio;
+00587 
+00588 
+00589                                 posSide = p * *targetPosIt;
+00590                                 negSide = p * dest;
+00591                                                                 
+00592                                 if (posSide >= - epsilon && negSide <= epsilon)
+00593                                 {                                                                       
+00594                                                 if (fabsf(posSide - negSide) > std::numeric_limits<float>::min())
+00595                                                 {
+00596                                                         alpha = posSide / (posSide - negSide);
+00597                                                 }
+00598                                                 else
+00599                                                 {
+00600                                                         alpha = 0.f;
+00601                                                 }
+00602                                                 startEnd = alpha * (dest - *targetPosIt);                                       
+00603                                                 ci.dist = startEnd.norm();
+00604                                                 // we translate the particle from an epsilon so that it won't get hooked to the disc
+00605                                                 ci.newPos = *targetPosIt  + startEnd + PSCollideEpsilon * p.getNormal();                                
+00606 
+00607 
+00608                                                 // now, check the collision pos against radius
+00609 
+00610                                                 hitRadius2 = (ci.newPos - center) * (ci.newPos - center);
+00611 
+00612                                                 if (hitRadius2 < radiusIt->R2) // check collision against disc
+00613                                                 {
+00614                                                         ci.newSpeed = _BounceFactor * (speed - 2.0f * (speed * p.getNormal()) * p.getNormal());                                         
+00615                                                         ci.collisionZone = this;                                                
+00616                                                         (*it)->collisionUpdate(ci, k);
+00617                                                 }
+00618                                         
+00619                                 }
+00620                         }
+00621                 }
+00622         }       
+00623 }
+00624 
+00625 void CPSZoneDisc::show(TAnimationTime ellapsedTime)
+00626 {
+00627         TPSAttribRadiusPair::const_iterator radiusIt = _Radius.begin();
+00628         TPSAttribVector::const_iterator posIt = _Owner->getPos().begin(), endPosIt = _Owner->getPos().end()
+00629                                                                         , normalIt = _Normal.begin();
+00630         setupDriverModelMatrix();       
+00631         CMatrix mat;
+00632 
+00633         
+00634                 
+00635         CPSLocated *loc;
+00636         uint32 index;
+00637         CPSLocatedBindable *lb;
+00638         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+00639         
+00640 
+00641         
+00642         for (uint k = 0; posIt != endPosIt; ++posIt, ++radiusIt, ++normalIt, ++k) 
+00643         {       
+00644                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
+00645                 CPSUtil::buildSchmidtBasis(*normalIt, mat);
+00646                 CPSUtil::displayDisc(*getDriver(), radiusIt->R, *posIt, mat, 32, col);
+00647 
+00648                 mat.setPos(*posIt);
+00649                 CPSUtil::displayBasis(getDriver() ,getLocalToWorldMatrix(), mat, 1.f, *getFontGenerator(), *getFontManager());                          
+00650                 setupDriverModelMatrix();                       
+00651         }       
+00652 }
+00653         
+00654 
+00655 
+00656 
+00657 
+00658 
+00659 void CPSZoneDisc::setMatrix(uint32 index, const CMatrix &m)
+00660 {
+00661         nlassert(index < _Radius.getSize());    
+00662         // compute new pos
+00663         _Owner->getPos()[index] = m.getPos();
+00664         // compute new normal
+00665         _Normal[index] = m.getK();
+00666 }
+00667 
+00668 CMatrix CPSZoneDisc::getMatrix(uint32 index) const
+00669 {
+00670         CMatrix m, b;
+00671         m.translate(_Owner->getPos()[index]);
+00672         CPSUtil::buildSchmidtBasis(_Normal[index], b);
+00673         m = m * b;
+00674         return m;       
+00675 }
+00676 
+00677 CVector CPSZoneDisc::getNormal(uint32 index)
+00678 {
+00679         return _Normal[index];
+00680 }
+00681 void CPSZoneDisc::setNormal(uint32 index, CVector n)
+00682 {
+00683         _Normal[index] = n;
+00684 }
+00685 
+00686 void CPSZoneDisc::setScale(uint32 k, float scale)
+00687 {
+00688         _Radius[k].R = scale;
+00689         _Radius[k].R2 = scale * scale;
+00690 }
+00691 
+00692 CVector CPSZoneDisc::getScale(uint32 k) const
+00693 {
+00694         return CVector(_Radius[k].R, _Radius[k].R, _Radius[k].R);
+00695 }
+00696 
+00697 
+00698 void CPSZoneDisc::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+00699 {
+00700         f.serialVersion(1);     
+00701         CPSZone::serial(f);
+00702         f.serial(_Normal);              
+00703         f.serial(_Radius);              
+00704 }
+00705 
+00706 void CPSZoneDisc::resize(uint32 size)
+00707 {
+00708         nlassert(size < (1 << 16));
+00709         _Radius.resize(size);
+00710         _Normal.resize(size);
+00711 }
+00712 
+00713 void CPSZoneDisc::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+00714 {
+00715         CRadiusPair rp;
+00716         rp.R = rp.R2 = 1.f;
+00717         nlassert(_Radius.getSize() != _Radius.getMaxSize());
+00718         _Radius.insert(rp);
+00719         _Normal.insert(CVector::K);
+00720 }
+00721 
+00722 void CPSZoneDisc::deleteElement(uint32 index)
+00723 {
+00724         _Radius.remove(index);
+00725         _Normal.remove(index);
+00726 }
+00727 
+00728 
+00730 // CPSZoneCylinder implementation //
+00732 
+00733 
+00734 /*
+00735 void CPSZoneCylinder::performMotion(TAnimationTime ellapsedTime)
+00736 {
+00737         TPSAttribVector::const_iterator dimIt = _Dim.begin();
+00738         CPSAttrib<CPlaneBasis>::const_iterator basisIt = _Basis.begin();
+00739         TPSAttribVector::const_iterator cylinderPosIt, cylinderPosEnd, targetPosIt, targetPosEnd;
+00740         CVector dest;
+00741         CPSCollisionInfo ci;
+00742         CVector startEnd;
+00743         uint32 k;
+00744         const TPSAttribVector *speedAttr;
+00745 
+00746 
+00747 
+00748         for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+00749         {
+00750 
+00751                 speedAttr = &((*it)->getSpeed());
+00752 
+00753 
+00754                 // cycle through the cylinders
+00755 
+00756                 cylinderPosEnd = _Owner->getPos().end();
+00757                 for (cylinderPosIt = _Owner->getPos().begin(); cylinderPosIt != cylinderPosEnd
+00758                                 ; ++cylinderPosIt, ++dimIt, ++basisIt)
+00759                 {
+00760                         
+00761                         // we must setup the cylinder in the good basis
+00762 
+00763                         const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
+00764 
+00765                         
+00766 
+00767                         // compute the new center pos
+00768                         CVector center = m * *cylinderPosIt;
+00769 
+00770                         // compute a basis for the cylinder
+00771                         CVector I = m.mulVector(basisIt->X);
+00772                         CVector J = m.mulVector(basisIt->Y);
+00773                         CVector K = m.mulVector(basisIt->X ^ basisIt->Y);
+00774 
+00775                                                 
+00776                         // the pos projected (and scale) over the plane basis of the cylinder, the pos minus the center
+00777                         CVector projectedPos, tPos;
+00778 
+00779                         // the same, but with the final position
+00780                         CVector destProjectedPos, destTPos;
+00781 
+00782 
+00783                         // deals with each particle
+00784                         targetPosEnd = (*it)->getPos().end();
+00785                         for (targetPosIt = (*it)->getPos().begin(), k = 0; targetPosIt != targetPosEnd; ++targetPosIt, ++k)
+00786                         {       
+00787                                 const CVector &speed = (*speedAttr)[k];
+00788                                 const CVector &pos = *targetPosIt;
+00789 
+00790                                 
+00791                                 
+00792                                 // check wether current pos was outside the cylinder
+00793 
+00794 
+00795                                 tPos = pos - center;
+00796                                 projectedPos = (1 / dimIt->x) * (I * tPos) * I + (1 / dimIt->y)  * (J * tPos) * J;
+00797                                 
+00798                                 if (!
+00799                                          (
+00800                                                 ((tPos * K) < dimIt->z)
+00801                                                 && ((tPos * K) > -dimIt->z)
+00802                                                 && (projectedPos * projectedPos < 1.f) 
+00803                                          )
+00804                                    )
+00805                                 {
+00806                                         dest = pos + ellapsedTime *  speed;
+00807                                         destTPos = dest - center;
+00808                                         destProjectedPos = (1.f / dimIt->x) * (I * tPos) * I + (1.f / dimIt->y)  * (J * tPos) * J;
+00809 
+00810                                         // test wether the new position is inside the cylinder
+00811 
+00812                                         
+00813                                         if (!
+00814                                                  (
+00815                                                         ((destTPos * K) < dimIt->z)
+00816                                                         && ((destTPos * K) > -dimIt->z)
+00817                                                         && (destProjectedPos * destProjectedPos < 1.f) 
+00818                                                  )
+00819                                            )
+00820                                         {
+00821                                                 // now, detect the closest hit point (the smallest alpha, with alpha, the percent of the move vector
+00822                                                 // to reach the hit point)
+00823 
+00824                                                 const float epsilon = 10E-6f;
+00825 
+00826                                                 float alphaTop, alphaBottom, alphaCyl;
+00827 
+00828                                                 const float denum = (dest - pos) * K;
+00829 
+00830                                                 // top plane
+00831 
+00832                                                 if (fabs(denum) < epsilon)
+00833                                                 {
+00834                                                         alphaTop = (dimIt->z - (tPos * K)) / denum;
+00835                                                         if (alphaTop < 0.f) alphaTop = 1.f;
+00836                                                 }
+00837                                                 else
+00838                                                 {
+00839                                                         alphaTop = 1.f;
+00840                                                 }
+00841 
+00842                                                 // bottom plane
+00843 
+00844                                                 if (fabs(denum) < epsilon)
+00845                                                 {
+00846                                                         alphaBottom = (- dimIt->z - (tPos * K)) / denum;
+00847                                                         if (alphaBottom < 0.f) alphaBottom = 1.f;
+00848                                                 }
+00849                                                 else
+00850                                                 {
+00851                                                         alphaBottom = 1.f;
+00852                                                 }
+00853 
+00854                                                 // cylinder
+00855 
+00856                                                 //expressed the src and dest positions in the cylinder basis
+00857 
+00858                                                 const float ox = tPos * I, oy = tPos * J, dx = (destTPos - tPos) * I, dy = (destTPos - tPos) * J;
+00859 
+00860                                                 // coefficients of the equation : a * alpha ^ 2 + b * alpha + c = 0
+00861                                                 const float a = (dx * dx) / (dimIt->x * dimIt->x)
+00862                                                                   + (dy * dy) / (dimIt->y * dimIt->y);
+00863                                                 const float b = 2.f * (ox * dx) / (dimIt->x * dimIt->x)
+00864                                                                   + (oy * dy) / (dimIt->y * dimIt->y);
+00865                                                 const float c = ox * ox + oy * oy - 1;
+00866 
+00867                                                 // discriminant
+00868                                                 const float delta = b * b - 4.f * a * c;
+00869 
+00870                                                 if (delta < epsilon)
+00871                                                 {
+00872                                                         alphaCyl = 1.f;
+00873                                                 }
+00874                                                 else
+00875                                                 {
+00876                                                         const float deltaRoot = sqrtf(delta);
+00877                                                         const float r1 = (- b - deltaRoot) / (2.f / a);
+00878                                                         const float r2 = (- b - deltaRoot) / (2.f / a);
+00879 
+00880                                                         if (r1 < 0.f) alphaCyl = r2;
+00881                                                                 else if (r2 < 0.f) alphaCyl = r1;
+00882                                                                         else alphaCyl = r1 < r2 ? r1 : r2;
+00883                                                 }
+00884 
+00885 
+00886                                                 // now, choose the minimum positive dist
+00887                                                 
+00888                                                 if (alphaTop < alphaBottom && alphaTop < alphaCyl)
+00889                                                 {
+00890                                                         // collision with the top plane
+00891                                                         CVector startEnd = alphaTop * (dest - pos);
+00892                                                         ci.newPos = pos + startEnd + PSCollideEpsilon * K;
+00893                                                         ci.dist = startEnd.norm();
+00894                                                         ci.newSpeed = (-2.f * (speed * K)) * K + speed;
+00895                                                         ci.collisionZone = this;
+00896                                                         
+00897                                                         (*it)->collisionUpdate(ci, k);
+00898                                                 }
+00899                                                 else
+00900                                                         if (alphaBottom < alphaCyl)
+00901                                                         {       
+00902                                                                 // collision with the bottom plane
+00903                                                                 CVector startEnd = alphaBottom * (dest - pos);
+00904                                                                 ci.newPos = pos + startEnd - PSCollideEpsilon * K;
+00905                                                                 ci.dist = startEnd.norm();
+00906                                                                 ci.newSpeed = (-2.f * (speed * K)) * K + speed;
+00907                                                                 ci.collisionZone = this;
+00908                                                 
+00909                                                                 
+00910                                                                 (*it)->collisionUpdate(ci, k);
+00911                                                         }
+00912                                                         else
+00913                                                         {
+00914                                                                 // collision with the cylinder
+00915 
+00916                                                                 CVector startEnd = alphaCyl * (dest - pos);
+00917 
+00918                                                                 // normal at the hit point. It is the gradient of the implicit equation x^2 / a^2 + y^2 / b^2 - R^ 2=  0
+00919                                                                 // so we got unormalized n =  (2 x / a ^ 2, 2 y / b ^ 2, 0) in the basis of the cylinder
+00920                                                                 // As we'll normalize it, we don't need  the 2 factor
+00921                                                                 
+00922                                                                 float px = ox + alphaCyl * dx;
+00923                                                                 float py = oy + alphaCyl * dy;
+00924 
+00925                                                                 CVector normal = px / (dimIt->x * dimIt->x) * I + py / (dimIt->y * dimIt->y) * J;
+00926                                                                 normal.normalize();
+00927 
+00928                                                                 ci.newPos = pos + startEnd - PSCollideEpsilon * normal;
+00929                                                                 ci.dist = startEnd.norm();
+00930                                                                 ci.newSpeed = (-2.f * (speed * normal)) * normal + speed;
+00931                                                                 ci.collisionZone = this;
+00932 
+00933                                                                 (*it)->collisionUpdate(ci, k);
+00934                                                         }                                               
+00935 
+00936                                         }
+00937                                 }                                                                       
+00938                         }
+00939                 }
+00940         }
+00941 }
+00942 */
+00943 
+00944 
+00945 
+00946 void CPSZoneCylinder::performMotion(TAnimationTime ellapsedTime)
+00947 {
+00948         MINI_TIMER(PSStatsZoneCylinder)
+00949         TPSAttribVector::const_iterator dimIt;
+00950         CPSAttrib<CPlaneBasis>::const_iterator basisIt;
+00951         TPSAttribVector::const_iterator cylinderPosIt, cylinderPosEnd, targetPosIt, targetPosEnd;
+00952         CVector dest;
+00953         CPSCollisionInfo ci;
+00954         uint32 k;
+00955         const TPSAttribVector *speedAttr;
+00956 
+00957 
+00958 
+00959         for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+00960         {
+00961 
+00962                 speedAttr = &((*it)->getSpeed());
+00963 
+00964 
+00965                 // cycle through the cylinders
+00966 
+00967                 cylinderPosEnd = _Owner->getPos().end();
+00968                 for (cylinderPosIt = _Owner->getPos().begin(), basisIt = _Basis.begin(),  dimIt = _Dim.begin()
+00969                                 ; cylinderPosIt != cylinderPosEnd
+00970                                 ; ++cylinderPosIt, ++dimIt, ++basisIt)
+00971                 {
+00972                         
+00973                         // we must setup the cylinder in the good basis
+00974 
+00975                         const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
+00976 
+00977                         
+00978 
+00979                         // compute the new center pos
+00980                         CVector center = m * *cylinderPosIt;
+00981 
+00982                         // compute a basis for the cylinder
+00983                         CVector I = m.mulVector(basisIt->X);
+00984                         CVector J = m.mulVector(basisIt->Y);
+00985                         CVector K = m.mulVector(basisIt->X ^ basisIt->Y);
+00986 
+00987                                                 
+00988                         // the pos projected (and scale) over the plane basis of the cylinder, the pos minus the center
+00989                         CVector projectedPos, tPos;
+00990 
+00991                         // the same, but with the final position
+00992                         CVector destProjectedPos, destTPos;
+00993 
+00994 
+00995                         // deals with each particle
+00996                         targetPosEnd = (*it)->getPos().end();
+00997                         TPSAttribCollisionInfo::const_iterator ciIt = (*it)->getCollisionInfo().begin();
+00998                         for (targetPosIt = (*it)->getPos().begin(), k = 0; targetPosIt != targetPosEnd; ++targetPosIt, ++k, ++ciIt)
+00999                         {       
+01000                                 const CVector &speed = (*speedAttr)[k];
+01001                                 const CVector &pos = *targetPosIt;
+01002 
+01003                                 
+01004                                 
+01005                                 // check wether current pos was outside the cylinder
+01006 
+01007 
+01008                                 tPos = pos - center;
+01009                                 projectedPos = (1 / dimIt->x) * (I * tPos) * I + (1 / dimIt->y)  * (J * tPos) * J;
+01010                                 
+01011                                 if (!
+01012                                          (
+01013                                                 ((tPos * K) < dimIt->z)
+01014                                                 && ((tPos * K) > -dimIt->z)
+01015                                                 && (projectedPos * projectedPos < 1.f) 
+01016                                          )
+01017                                    )
+01018                                 {
+01019                                         dest = pos + ellapsedTime *  speed * ciIt->TimeSliceRatio;
+01020                                         destTPos = dest - center;
+01021                                         destProjectedPos = (1.f / dimIt->x) * (I * destTPos) * I + (1.f / dimIt->y)  * (J * destTPos) * J;
+01022 
+01023                                         // test wether the new position is inside the cylinder
+01024 
+01025                                         
+01026                                         if (
+01027                                                  (
+01028                                                         ((destTPos * K) < dimIt->z)
+01029                                                         && ((destTPos * K) > -dimIt->z)
+01030                                                         && (destProjectedPos * destProjectedPos < 1.f) 
+01031                                                  )
+01032                                            )
+01033                                         {
+01034                                                 // now, detect the closest hit point (the smallest alpha, with alpha, the percent of the move vector
+01035                                                 // to reach the hit point)
+01036 
+01037                                                 const float epsilon = 10E-3f;
+01038 
+01039                                                 float alphaTop, alphaBottom, alphaCyl;
+01040 
+01041                                                 const float denum = (dest - pos) * K;
+01042 
+01043                                                 // top plane
+01044 
+01045                                                 if (fabs(denum) < epsilon)
+01046                                                 {
+01047                                                         alphaTop = (dimIt->z - (tPos * K)) / denum;
+01048                                                         if (alphaTop < 0.f) alphaTop = 1.f;
+01049                                                 }
+01050                                                 else
+01051                                                 {
+01052                                                         alphaTop = 1.f;
+01053                                                 }
+01054 
+01055                                                 // bottom plane
+01056 
+01057                                                 if (fabs(denum) < epsilon)
+01058                                                 {
+01059                                                         alphaBottom = (- dimIt->z - (tPos * K)) / denum;
+01060                                                         if (alphaBottom < 0.f) alphaBottom = 1.f;
+01061                                                 }
+01062                                                 else
+01063                                                 {
+01064                                                         alphaBottom = 1.f;
+01065                                                 }
+01066 
+01067                                                 // cylinder
+01068 
+01069                                                 //expressed the src and dest positions in the cylinder basis
+01070 
+01071                                                 const float ox = tPos * I, oy = tPos * J, dx = (destTPos - tPos) * I, dy = (destTPos - tPos) * J;
+01072 
+01073                                                 // coefficients of the equation : a * alpha ^ 2 + b * alpha + c = 0
+01074                                                 const float a = (dx * dx) / (dimIt->x * dimIt->x)
+01075                                                                   + (dy * dy) / (dimIt->y * dimIt->y);
+01076                                                 const float b = 2.f * ((ox * dx) / (dimIt->x * dimIt->x)
+01077                                                                   + (oy * dy) / (dimIt->y * dimIt->y));
+01078                                                 const float c = (ox * ox) / (dimIt->x * dimIt->x) + (oy * oy) / (dimIt->y * dimIt->y)  - 1;
+01079 
+01080                                                 // discriminant
+01081                                                 const float delta = b * b - 4.f * a * c;
+01082 
+01083                                                 if (delta < epsilon)
+01084                                                 {
+01085                                                         alphaCyl = 1.f;
+01086                                                 }
+01087                                                 else
+01088                                                 {
+01089                                                         const float deltaRoot = sqrtf(delta);
+01090                                                         const float r1 = (- b + 2.f * deltaRoot) / (2.f * a);
+01091                                                         const float r2 = (- b - 2.f * deltaRoot) / (2.f * a);
+01092 
+01093                                                         if (r1 < 0.f) alphaCyl = r2;
+01094                                                                 else if (r2 < 0.f) alphaCyl = r1;
+01095                                                                         else alphaCyl = r1 < r2 ? r1 : r2;
+01096 
+01097                                                                         if (alphaCyl < 0.f) alphaCyl = 1.f;
+01098                                                 }
+01099 
+01100 
+01101                                                 // now, choose the minimum positive dist
+01102 
+01103                                         
+01104                                                 
+01105                                                 if (alphaTop < alphaBottom && alphaTop < alphaCyl)
+01106                                                 {
+01107                                                         // collision with the top plane
+01108                                                         CVector startEnd = alphaTop * (dest - pos);
+01109                                                         ci.newPos = pos + startEnd + PSCollideEpsilon * K;
+01110                                                         ci.dist = startEnd.norm();
+01111                                                         ci.newSpeed = (-2.f * (speed * K)) * K + speed;
+01112                                                         ci.collisionZone = this;
+01113                                                         
+01114                                                         (*it)->collisionUpdate(ci, k);
+01115                                                 }
+01116                                                 else
+01117                                                         if (alphaBottom < alphaCyl)
+01118                                                         {       
+01119                                                                 // collision with the bottom plane
+01120                                                                 CVector startEnd = alphaBottom * (dest - pos);
+01121                                                                 ci.newPos = pos + startEnd - PSCollideEpsilon * K;
+01122                                                                 ci.dist = startEnd.norm();
+01123                                                                 ci.newSpeed = (-2.f * (speed * K)) * K + speed;
+01124                                                                 ci.collisionZone = this;
+01125                                                 
+01126                                                                 
+01127                                                                 (*it)->collisionUpdate(ci, k);
+01128                                                         }
+01129                                                         else
+01130                                                         {
+01131                                                                 // collision with the cylinder
+01132 
+01133                                                                 CVector startEnd = alphaCyl * (dest - pos);
+01134 
+01135                                                                 // normal at the hit point. It is the gradient of the implicit equation x^2 / a^2 + y^2 / b^2 - R^ 2=  0
+01136                                                                 // so we got unormalized n =  (2 x / a ^ 2, 2 y / b ^ 2, 0) in the basis of the cylinder
+01137                                                                 // As we'll normalize it, we don't need  the 2 factor
+01138                                                                 
+01139                                                                 float px = ox + alphaCyl * dx;
+01140                                                                 float py = oy + alphaCyl * dy;
+01141 
+01142                                                                 CVector normal = px / (dimIt->x * dimIt->x) * I + py / (dimIt->y * dimIt->y) * J;
+01143                                                                 normal.normalize();
+01144 
+01145                                                                 ci.newPos = pos + startEnd + PSCollideEpsilon * normal;
+01146                                                                 ci.dist = startEnd.norm();
+01147                                                                 ci.newSpeed = (-2.f * (speed * normal)) * normal + speed;
+01148                                                                 ci.collisionZone = this;
+01149 
+01150                                                                 (*it)->collisionUpdate(ci, k);
+01151                                                         }                                               
+01152 
+01153                                         }
+01154                                 }                                                                       
+01155                         }
+01156                 }
+01157         }
+01158 }
+01159 
+01160 void CPSZoneCylinder::show(TAnimationTime ellapsedTime)
+01161 {
+01162         TPSAttribVector::const_iterator dimIt = _Dim.begin()
+01163                                                                         ,posIt = _Owner->getPos().begin()
+01164                                                                         , endPosIt = _Owner->getPos().end();
+01165 
+01166         CPSAttrib<CPlaneBasis>::const_iterator basisIt = _Basis.begin();
+01167                                                                         
+01168         setupDriverModelMatrix();       
+01169         CMatrix mat;
+01170 
+01171 
+01172                 
+01173         CPSLocated *loc;
+01174         uint32 index;
+01175         CPSLocatedBindable *lb;
+01176         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+01177 
+01178 
+01179         for (uint32 k = 0; posIt != endPosIt; ++posIt, ++dimIt, ++basisIt, ++k) 
+01180         {                       
+01181                 mat.setRot(basisIt->X, basisIt->Y, basisIt->X ^ basisIt->Y);
+01182                 mat.setPos(CVector::Null);
+01183 
+01184                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
+01185 
+01186                 
+01187                 CPSUtil::displayCylinder(*getDriver(), *posIt, mat, *dimIt, 32, col); 
+01188 
+01189                 mat.setPos(*posIt);
+01190                 CPSUtil::displayBasis(getDriver() ,getLocalToWorldMatrix(), mat, 1.f, *getFontGenerator(), *getFontManager());                          
+01191                 setupDriverModelMatrix();       
+01192         
+01193         }
+01194 }
+01195         
+01196 
+01197 
+01198 void CPSZoneCylinder::setMatrix(uint32 index, const CMatrix &m)
+01199 {
+01200         // transform the basis  
+01201         _Basis[index].X = m.getI();     
+01202         _Basis[index].Y = m.getJ();     
+01203 
+01204         // compute new pos
+01205         _Owner->getPos()[index] = m.getPos();
+01206         
+01207                                  
+01208 }
+01209 
+01210 
+01211 
+01212 CMatrix CPSZoneCylinder::getMatrix(uint32 index) const
+01213 {
+01214         CMatrix m;
+01215         m.setRot(_Basis[index].X, _Basis[index].Y, _Basis[index].X ^_Basis[index].Y);
+01216         m.setPos(_Owner->getPos()[index]);      
+01217         return m;
+01218 }
+01219 
+01220 
+01221 void CPSZoneCylinder::setScale(uint32 k, float scale)
+01222 {
+01223         _Dim[k] = CVector(scale, scale, scale);
+01224 }
+01225 
+01226 CVector CPSZoneCylinder::getScale(uint32 k) const
+01227 {
+01228         return _Dim[k];
+01229 }
+01230 
+01231 void CPSZoneCylinder::setScale(uint32 index, const CVector &s)
+01232 {
+01233         _Dim[index] = s;
+01234 }
+01235 
+01236 
+01237 void CPSZoneCylinder::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01238 {
+01239         f.serialVersion(1);
+01240         CPSZone::serial(f);
+01241         f.serial(_Basis);               
+01242         f.serial(_Dim);
+01243 }
+01244 
+01245 
+01246 
+01247 void CPSZoneCylinder::resize(uint32 size)
+01248 {
+01249         nlassert(size < (1 << 16));
+01250         _Basis.resize(size);
+01251         _Dim.resize(size);
+01252 }
+01253 
+01254 void CPSZoneCylinder::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+01255 {
+01256         _Basis.insert(CPlaneBasis(CVector::K));
+01257         _Dim.insert(CVector(1, 1, 1));
+01258 }
+01259 
+01260 void CPSZoneCylinder::deleteElement(uint32 index)
+01261 {
+01262         _Basis.remove(index);
+01263         _Dim.remove(index);
+01264 }
+01265 
+01266 
+01268 //      implementation of CPSZoneRectangle      //
+01270 
+01271 
+01272 
+01273 
+01274 
+01275 void CPSZoneRectangle::performMotion(TAnimationTime ellapsedTime)
+01276 {
+01277         MINI_TIMER(PSStatsZoneRectangle)
+01278         // for each target, we must check wether they are going through the rectangle
+01279         // if so they must bounce
+01280         TPSAttribVector::const_iterator rectanglePosIt, rectanglePosEnd, targetPosIt, targetPosEnd;
+01281         CPSAttrib<CPlaneBasis>::const_iterator basisIt;
+01282         TPSAttribFloat::const_iterator widthIt, heightIt;
+01283 
+01284         CVector dest;
+01285         CPSCollisionInfo ci;
+01286         CVector startEnd;
+01287         uint32 k;
+01288         const TPSAttribVector *speedAttr;
+01289         float posSide, negSide;
+01290         
+01291         // alpha is the ratio that gives the percent of endPos - startPos that hit the rectangle
+01292         float alpha; 
+01293 
+01294         CVector center;
+01295 
+01296         for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
+01297         {
+01298 
+01299                 basisIt = _Basis.begin();
+01300                 heightIt = _Height.begin();
+01301                 widthIt = _Width.begin();
+01302 
+01303                 speedAttr = &((*it)->getSpeed());
+01304                 // cycle through the rectangle
+01305 
+01306                 rectanglePosEnd = _Owner->getPos().end();
+01307                 for (rectanglePosIt = _Owner->getPos().begin(); rectanglePosIt != rectanglePosEnd
+01308                                 ; ++rectanglePosIt, ++basisIt, ++widthIt, ++heightIt)
+01309                 {
+01310                         
+01311                         // we must setup the rectangle in the good basis
+01312 
+01313                         const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
+01314 
+01315                         
+01316 
+01317                         NLMISC::CPlane p;
+01318                         center = m * (*rectanglePosIt);
+01319 
+01320                         const CVector X = m.mulVector(basisIt->X);
+01321                         const CVector Y = m.mulVector(basisIt->Y);
+01322 
+01323                         p.make(X ^ Y, center);          
+01324                         
+01325                         // deals with each particle
+01326 
+01327                         const float epsilon = 0.5f * PSCollideEpsilon;
+01328 
+01329                         targetPosEnd = (*it)->getPos().end();
+01330                         TPSAttribCollisionInfo::const_iterator ciIt = (*it)->getCollisionInfo().begin();
+01331                         for (targetPosIt = (*it)->getPos().begin(), k = 0; targetPosIt != targetPosEnd; ++targetPosIt, ++k, ++ciIt)
+01332                         {       
+01333                                 const CVector &pos = *targetPosIt;
+01334                                 const CVector &speed = (*speedAttr)[k];
+01335                                 // check whether the located is going through the rectangle
+01336                                 dest = pos + ellapsedTime *  speed * ciIt->TimeSliceRatio;
+01337 
+01338 
+01339                                 posSide = p * pos;
+01340                                 negSide = p * dest;
+01341                                                                 
+01342                                 if (posSide >= - epsilon && negSide <= epsilon)
+01343                                 {                                                                       
+01344                                                 if (fabsf(posSide - negSide) > std::numeric_limits<float>::min())
+01345                                                 {
+01346                                                         alpha = posSide / (posSide - negSide);
+01347                                                 }
+01348                                                 else
+01349                                                 {
+01350                                                         alpha = 0.f;
+01351                                                 }
+01352                                                 startEnd = alpha * (dest - pos);                                        
+01353                                                 ci.dist = startEnd.norm();
+01354                                                 // we translate the particle from an epsilon so that it won't get hooked to the rectangle
+01355                                                 ci.newPos = pos + startEnd;                             
+01356                                         
+01357 
+01358                                                 
+01359 
+01360                                                 if ( fabs( (pos - center) * X ) < *widthIt && fabs( (pos - center) * Y ) < *heightIt) // check collision against rectangle
+01361                                                 {
+01362                                                         ci.newPos += PSCollideEpsilon * p.getNormal();
+01363                                                         ci.newSpeed = _BounceFactor * (speed - 2.0f * (speed * p.getNormal()) * p.getNormal());                                         
+01364                                                         ci.collisionZone = this;                                                
+01365                                                         (*it)->collisionUpdate(ci, k);
+01366                                                 }
+01367                                         
+01368                                 }
+01369                         }       
+01370                 }
+01371         }
+01372 }
+01373 
+01374 
+01375 void CPSZoneRectangle::show(TAnimationTime ellapsedTime)
+01376 {
+01377         nlassert(_Owner);
+01378         const uint size = _Owner->getSize();
+01379         if (!size) return;
+01380         setupDriverModelMatrix();       
+01381         CMatrix mat;
+01382         
+01383         CPSLocated *loc;
+01384         uint32 index;
+01385         CPSLocatedBindable *lb;
+01386         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+01387 
+01388         for (uint k = 0; k < size; ++k) 
+01389         {       
+01390                 const CVector &I = _Basis[k].X;
+01391                 const CVector &J = _Basis[k].Y;
+01392                 mat.setRot(I, J , I ^J);
+01393                 mat.setPos(_Owner->getPos()[k]);
+01394                 CPSUtil::displayBasis(getDriver(), getLocalToWorldMatrix(), mat, 1.f, *getFontGenerator(), *getFontManager());                          
+01395                 setupDriverModelMatrix();       
+01396 
+01397                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
+01398         
+01399 
+01400 
+01401                 const CVector &pos = _Owner->getPos()[k];
+01402                 CPSUtil::display3DQuad(*getDriver(), pos + I * _Width[k] + J * _Height[k]
+01403                                                                                    , pos + I * _Width[k] - J * _Height[k]
+01404                                                                                    , pos - I * _Width[k] - J * _Height[k]
+01405                                                                                    , pos - I * _Width[k] + J * _Height[k], col);
+01406         }
+01407 }
+01408         
+01409 void CPSZoneRectangle::setMatrix(uint32 index, const CMatrix &m)
+01410 {
+01411         nlassert(_Owner);
+01412 
+01413         _Owner->getPos()[index] = m.getPos();
+01414         _Basis[index].X = m.getI();
+01415         _Basis[index].Y = m.getJ();
+01416 }
+01417 
+01418 
+01419 CMatrix CPSZoneRectangle::getMatrix(uint32 index) const
+01420 {
+01421         nlassert(_Owner);
+01422         CMatrix m;      
+01423         m.setRot(_Basis[index].X, _Basis[index].Y, _Basis[index].X ^ _Basis[index].Y);
+01424         m.setPos(_Owner->getPos()[index]);
+01425         return m;
+01426 }
+01427 
+01428 void CPSZoneRectangle::setScale(uint32 index, float scale)
+01429 {
+01430         _Width[index] = scale;
+01431         _Height[index] = scale;
+01432 }
+01433 void CPSZoneRectangle::setScale(uint32 index, const CVector &s)
+01434 {
+01435         _Width[index] = s.x;
+01436         _Height[index] = s.y;
+01437 }
+01438 CVector CPSZoneRectangle::getScale(uint32 index) const
+01439 {
+01440         return CVector(_Width[index], _Height[index], 1.f);
+01441 }
+01442 
+01443 
+01444 
+01445 void CPSZoneRectangle::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01446 {
+01447         f.serialVersion(1);
+01448         CPSZone::serial(f);
+01449         f.serial(_Basis);       
+01450         f.serial(_Width);
+01451         f.serial(_Height);
+01452 }
+01453 
+01454 
+01455 void CPSZoneRectangle::resize(uint32 size)
+01456 {
+01457         nlassert(size < (1 << 16));
+01458         _Basis.resize(size);
+01459         _Width.resize(size);
+01460         _Height.resize(size);
+01461 }
+01462 
+01463 void CPSZoneRectangle::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+01464 {
+01465         _Basis.insert(CPlaneBasis(CVector::K));
+01466         _Width.insert(1.f);
+01467         _Height.insert(1.f);
+01468 }
+01469 
+01470 void CPSZoneRectangle::deleteElement(uint32 index)
+01471 {
+01472         _Basis.remove(index);
+01473         _Width.remove(index);
+01474         _Height.remove(index);
+01475 }
+01476 
+01477 
+01478 
+01479 } // NL3D
+

Generated on Tue Mar 16 06:35:02 2004 for NeL by + +doxygen +1.3.6
+ + -- cgit v1.2.1