From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/ps__zone_8cpp-source.html | 1526 ++++++++++++++++++++++++++++ 1 file changed, 1526 insertions(+) create mode 100644 docs/doxygen/nel/ps__zone_8cpp-source.html (limited to 'docs/doxygen/nel/ps__zone_8cpp-source.html') diff --git a/docs/doxygen/nel/ps__zone_8cpp-source.html b/docs/doxygen/nel/ps__zone_8cpp-source.html new file mode 100644 index 00000000..c4b5f654 --- /dev/null +++ b/docs/doxygen/nel/ps__zone_8cpp-source.html @@ -0,0 +1,1526 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

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