00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
00085 target->releaseCollisionInfo();
00086 target->releaseNonIntegrableForceRef();
00087 }
00088
00089
00090
00091 void CPSZone::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
00092 {
00093
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
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
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
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
00214
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
00224 float alpha;
00225
00226 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
00227 {
00228
00229 speedAttr = &((*it)->getSpeed());
00230
00231
00232 planePosEnd = _Owner->getPos().end();
00233 for (planePosIt = _Owner->getPos().begin(), normalIt = _Normal.begin(); planePosIt != planePosEnd
00234 ; ++planePosIt, ++normalIt)
00235 {
00236
00237
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
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
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
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
00320
00321
00322
00323
00324 void CPSZoneSphere::performMotion(TAnimationTime ellapsedTime)
00325 {
00326
00327
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
00347
00348 spherePosEnd = _Owner->getPos().end();
00349 for (spherePosIt = _Owner->getPos().begin(), radiusIt = _Radius.begin(); spherePosIt != spherePosEnd
00350 ; ++spherePosIt, ++radiusIt)
00351 {
00352
00353
00354
00355 const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
00356
00357
00358
00359 CVector center = m * *spherePosIt;
00360
00361
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
00371
00372
00373
00374
00375 rOut = (pos - center) * (pos - center);
00376
00377
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
00386
00387 if ( rIn <= radiusIt->R2)
00388 {
00389
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;
00396
00397
00398 d = sqrtf(d);
00399
00400
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
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
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
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
00526
00527 void CPSZoneDisc::performMotion(TAnimationTime ellapsedTime)
00528 {
00529
00530
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
00541 float hitRadius2;
00542
00543
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
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
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
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
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
00598 ci.newPos = *targetPosIt + startEnd + PSCollideEpsilon * p.getNormal();
00599
00600
00601
00602
00603 hitRadius2 = (ci.newPos - center) * (ci.newPos - center);
00604
00605 if (hitRadius2 < radiusIt->R2)
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
00656 _Owner->getPos()[index] = m.getPos();
00657
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
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
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
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
00966
00967 const CMatrix &m = CPSLocated::getConversionMatrix(*it, this->_Owner);
00968
00969
00970
00971
00972 CVector center = m * *cylinderPosIt;
00973
00974
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
00981 CVector projectedPos, tPos;
00982
00983
00984 CVector destProjectedPos, destTPos;
00985
00986
00987
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
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
01016
01017
01018 if (
01019 (
01020 ((destTPos * K) < dimIt->z)
01021 && ((destTPos * K) > -dimIt->z)
01022 && (destProjectedPos * destProjectedPos < 1.f)
01023 )
01024 )
01025 {
01026
01027
01028
01029 const float epsilon = 10E-3f;
01030
01031 float alphaTop, alphaBottom, alphaCyl;
01032
01033 const float denum = (dest - pos) * K;
01034
01035
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
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
01060
01061
01062
01063 const float ox = tPos * I, oy = tPos * J, dx = (destTPos - tPos) * I, dy = (destTPos - tPos) * J;
01064
01065
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
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
01094
01095
01096
01097 if (alphaTop < alphaBottom && alphaTop < alphaCyl)
01098 {
01099
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
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
01124
01125 CVector startEnd = alphaCyl * (dest - pos);
01126
01127
01128
01129
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
01193 _Basis[index].X = m.getI();
01194 _Basis[index].Y = m.getJ();
01195
01196
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
01262
01263
01264
01265
01266
01267 void CPSZoneRectangle::performMotion(TAnimationTime ellapsedTime)
01268 {
01269
01270
01271
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
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
01297
01298 rectanglePosEnd = _Owner->getPos().end();
01299 for (rectanglePosIt = _Owner->getPos().begin(); rectanglePosIt != rectanglePosEnd
01300 ; ++rectanglePosIt, ++basisIt, ++widthIt, ++heightIt)
01301 {
01302
01303
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
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
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
01347 ci.newPos = pos + startEnd;
01348
01349
01350
01351
01352 if ( fabs( (pos - center) * X ) < *widthIt && fabs( (pos - center) * Y ) < *heightIt)
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 }