primitive_world_image.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdpacs.h"
00025 
00026 #include "nel/misc/hierarchical_timer.h"
00027 
00028 #include "primitive_world_image.h"
00029 #include "move_primitive.h"
00030 #include "move_element.h"
00031 
00032 using namespace NLMISC;
00033 
00034 
00035 namespace NLPACS
00036 {
00037 
00038 // ***************************************************************************
00039 
00040 CPrimitiveWorldImage::CPrimitiveWorldImage()
00041 {
00042     // Set to NULL
00043     for (uint i=0; i<4; i++)
00044         _MoveElement[i]=NULL;
00045 
00046     _DynamicFlags=0;
00047     _BBXMin=-FLT_MAX;
00048     _BBXMax=-FLT_MAX;
00049     _BBYMin=-FLT_MAX;
00050     _BBYMax=-FLT_MAX;
00051 }
00052 
00053 // ***************************************************************************
00054 
00055 void CPrimitiveWorldImage::deleteIt (CMoveContainer &container, uint8 worldImage)
00056 {
00057     // Free the move elements
00058     for (uint i=0; i<4; i++)
00059         if (_MoveElement[i])
00060             removeMoveElement (i, container, worldImage);
00061 }
00062 // ***************************************************************************
00063 
00064 void CPrimitiveWorldImage::copy (const CPrimitiveWorldImage& source)
00065 {
00066     // Copy
00067     this->operator=(source);
00068 
00069     // Reset some flags
00070     _DynamicFlags&=~InModifiedListFlag;
00071 
00072     // Pointer into the 4 possibles sorted lists of movable primitives. Must be NULL
00073     for (uint i=0; i<4; i++)
00074         _MoveElement[i]=NULL;
00075 }
00076 
00077 // ***************************************************************************
00078 
00079 bool CPrimitiveWorldImage::evalCollision (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin, double timeMax, uint32 testTime,
00080                                     uint32 maxTestIteration, double &firstContactTime, double &lastContactTime, CMovePrimitive& primitive,
00081                                     CMovePrimitive& otherPrimitive)
00082 {
00083 //  H_AUTO(PACS_PWI_evalCollision_long);
00084 
00085     // Mask test
00086     if (( (primitive.getCollisionMaskInternal() & otherPrimitive.getOcclusionMaskInternal())  == 0) &&
00087         ( (primitive.getOcclusionMaskInternal() & otherPrimitive.getCollisionMaskInternal())  == 0))
00088         return false;
00089 
00090     // Test time
00091     if ( (!primitive.checkTestTime (testTime, maxTestIteration)) || (!otherPrimitive.checkTestTime (testTime, maxTestIteration)) )
00092         return false;
00093 
00094     // Clear time min time max
00095     firstContactTime=FLT_MAX;
00096     lastContactTime=-FLT_MAX;
00097 
00098     // Switch the good test
00099     switch (primitive.getPrimitiveTypeInternal())
00100     {
00101 
00102     // Static box over...
00103     case UMovePrimitive::_2DOrientedBox:
00104         {
00105             // Switch second type
00106             switch (otherPrimitive.getPrimitiveTypeInternal())
00107             {
00108 
00109             // Static box over movable box
00110             case UMovePrimitive::_2DOrientedBox:
00111                 // Make the test
00112                 return evalCollisionOBoverOB (other, desc, timeMin, timeMax, firstContactTime, lastContactTime, primitive, otherPrimitive);
00113 
00114             // Static box over movable cylinder
00115             case UMovePrimitive::_2DOrientedCylinder:
00116                 // Make the test
00117                 return evalCollisionOBoverOC (other, desc, timeMin, timeMax, firstContactTime, lastContactTime, primitive, otherPrimitive);
00118 
00119             default:
00120             // Should not go here
00121             nlstop;
00122             }
00123         }
00124 
00125     // Static box over...
00126     case UMovePrimitive::_2DOrientedCylinder:
00127         {
00128             // Switch second type
00129             switch (otherPrimitive.getPrimitiveTypeInternal())
00130             {
00131 
00132             // Static box over movable box
00133             case UMovePrimitive::_2DOrientedBox:
00134                 {
00135                     // Make the test
00136                     bool collid=other.evalCollisionOBoverOC (*this, desc, timeMin, timeMax, firstContactTime, lastContactTime, otherPrimitive,
00137                         primitive);
00138                     if (collid)
00139                         desc.XChgContactNormals ();
00140                     return collid;
00141                 }
00142 
00143             // Static box over movable cylinder
00144             case UMovePrimitive::_2DOrientedCylinder:
00145                 // Make the test
00146                 return evalCollisionOCoverOC (other, desc, timeMin, timeMax, firstContactTime, lastContactTime, primitive, otherPrimitive);
00147 
00148             default:
00149             // Should not go here
00150             nlstop;
00151             }
00152         }
00153 
00154     default:
00155         // Should not go here
00156         nlstop;
00157     }
00158 
00159     return false;
00160 }
00161 
00162 // ***************************************************************************
00163 
00164 const TCollisionSurfaceDescVector *CPrimitiveWorldImage::evalCollision (CGlobalRetriever &retriever, CCollisionSurfaceTemp& surfaceTemp,
00165                                                                   uint32 testTime, uint32 maxTestIteration, CMovePrimitive& primitive)
00166 {
00167 //  H_AUTO(PACS_PWI_evalCollision_short);
00168 
00169     // Test time
00170     if (!primitive.checkTestTime (testTime, maxTestIteration))
00171         return NULL;
00172 
00173     // Switch the good test
00174     if (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox)
00175     {
00176         // Local I
00177         CVector locI ((float)(_OBData.EdgeDirectionX[0]*primitive.getLength(0)/2.0), (float)(_OBData.EdgeDirectionY[0]*primitive.getLength(1)/2.0), 0);
00178 
00179         // Local J
00180         CVector locJ ((float)(_OBData.EdgeDirectionX[1]*primitive.getLength(0)/2.0), (float)(_OBData.EdgeDirectionY[1]*primitive.getLength(1)/2.0), 0);
00181 
00182         // Test
00183         return retriever.testBBoxMove (_Position.getGlobalPos (), _DeltaPosition, locI, locJ, surfaceTemp);
00184     }
00185     else
00186     {
00187         // Check
00188         nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedCylinder);
00189 
00190         // Test
00191         //nlinfo ("1) %f %f %f\n", _DeltaPosition.x, _DeltaPosition.y, _DeltaPosition.z);
00192 
00193         return retriever.testCylinderMove (_Position.getGlobalPos (), _DeltaPosition, primitive.getRadiusInternal(), surfaceTemp);
00194     }
00195 }
00196 
00197 // ***************************************************************************
00198 
00199 void CPrimitiveWorldImage::doMove (CGlobalRetriever &retriever, CCollisionSurfaceTemp& surfaceTemp, double originalMax, double finalMax, bool keepZ /*= false*/)
00200 {
00201     H_AUTO(NLPACS_PWI_Do_Move);
00202 
00203 
00204     // Time to avance
00205     double ratio;
00206     if (finalMax!=originalMax)
00207         ratio=(finalMax-_InitTime)/(originalMax-_InitTime);
00208     else
00209         ratio=1;
00210 
00211     // Make the move
00212     if (!keepZ)
00213     {
00214         _Position.setGlobalPos (retriever.doMove(_Position.getGlobalPos(), _DeltaPosition, (float)ratio, surfaceTemp, false), retriever);
00215     }
00216     else
00217     {
00218         _Position.setGlobalPosKeepZ(retriever.doMove(_Position.getGlobalPos(), _DeltaPosition, (float)ratio, surfaceTemp, false), retriever);
00219     }
00220 
00221 
00222     // Final position
00223     _InitTime=finalMax;
00224 }
00225 
00226 // ***************************************************************************
00227 
00228 void CPrimitiveWorldImage::doMove (double timeMax)
00229 {
00230 //  H_AUTO(PACS_PWI_doMove_short);
00231 
00232     // Make the move
00233     _Position.setPos (_Position.getPos ()+_Speed*(timeMax-_InitTime));
00234 
00235     // Final position
00236     _InitTime=timeMax;
00237 }
00238 
00239 // ***************************************************************************
00240 
00241 bool CPrimitiveWorldImage::evalCollisionOBoverOB (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin, double timeMax,
00242                                             double &firstContactTime, double &lastContactTime, CMovePrimitive& primitive,
00243                                            CMovePrimitive& otherPrimitive)
00244 {
00245     // Checks
00246     nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00247     nlassert (otherPrimitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00248 
00249     // Find a collision
00250     bool find=false;
00251 
00252     // Best time
00253     desc.ContactTime=FLT_MAX;
00254 
00255     // Timemin
00256     double _timeMax=-FLT_MAX;
00257 
00258     // Check movable points over the edge
00259     uint pt;
00260     uint seg;
00261     for (pt=0; pt<4; pt++)
00262     for (seg=0; seg<4; seg++)
00263     {
00264         // Get collision time of the point over the segment
00265         CCollisionDesc d;
00266         if ( evalCollisionPoverS (other, d, pt, seg, primitive, otherPrimitive) )
00267         {
00268             // Find
00269             find=true;
00270 
00271             // Best time ?
00272             if (d.ContactTime<desc.ContactTime)
00273             {
00274                 // This is the new descriptor
00275                 desc=d;
00276             }
00277 
00278             // Best max time ?
00279             if (d.ContactTime>_timeMax)
00280             {
00281                 // This is the new max time
00282                 _timeMax=d.ContactTime;
00283             }
00284         }
00285     }
00286 
00287     // Check static points over the movable box
00288     for (pt=0; pt<4; pt++)
00289     for (seg=0; seg<4; seg++)
00290     {
00291         // Get collision time of the point over the segment
00292         CCollisionDesc d;
00293         if (other.evalCollisionPoverS (*this, d, pt, seg, primitive, otherPrimitive))
00294         {
00295             // Find
00296             find=true;
00297 
00298             // Best time ?
00299             if (d.ContactTime<desc.ContactTime)
00300             {
00301                 // This is the new descriptor
00302                 desc=d;
00303             }
00304 
00305             // Best max time ?
00306             if (d.ContactTime>_timeMax)
00307             {
00308                 // This is the new max time
00309                 _timeMax=d.ContactTime;
00310             }
00311         }
00312     }
00313 
00314     if (find)
00315     {
00316         // First last contact time
00317         firstContactTime=desc.ContactTime;
00318         lastContactTime=_timeMax;
00319 
00320         // Half time
00321         //double halfTime = (_timeMax+desc.ContactTime)/2.0;
00322 
00323         // Collision in the past ?
00324         //if (timeMin > halfTime)
00325         if (timeMin > _timeMax)
00326             // yes, abort
00327             return false;
00328 
00329         // Collision not in the future ?
00330         if (timeMax>desc.ContactTime)
00331         {
00332             // Clamp time
00333             if (desc.ContactTime<timeMin)
00334                 desc.ContactTime=timeMin;
00335 
00336             // yes, found it
00337             return true;
00338         }
00339     }
00340 
00341     // No collision found
00342     return false;
00343 }
00344 
00345 // ***************************************************************************
00346 
00347 bool CPrimitiveWorldImage::evalCollisionOBoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin, double timeMax,
00348                                             double &firstContactTime, double &lastContactTime, CMovePrimitive& primitive,
00349                                            CMovePrimitive& otherPrimitive)
00350 {
00351     // Checks
00352     nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00353     nlassert (otherPrimitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedCylinder);
00354 
00355     // Find a collision
00356     bool find=false;
00357 
00358     // Best time
00359     desc.ContactTime=FLT_MAX;
00360 
00361     // time min clip
00362     double _timeMax = -FLT_MAX;
00363 
00364     // Check movable points over the cylinder
00365     uint pt;
00366     for (pt=0; pt<4; pt++)
00367     {
00368         // Get collision time of the point over the segment
00369         CCollisionDesc d;
00370         double firstContactTime;
00371         double lastContactTime;
00372         if (evalCollisionPoverOC (other, d, pt, firstContactTime, lastContactTime, primitive, otherPrimitive))
00373         {
00374             // Found
00375             find=true;
00376 
00377             // Best time ?
00378             if (firstContactTime<desc.ContactTime)
00379             {
00380                 // This is the new descriptor
00381                 desc=d;
00382             }
00383 
00384             // Best max time ?
00385             if (lastContactTime>_timeMax)
00386             {
00387                 // New max time
00388                 _timeMax=lastContactTime;
00389             }
00390         }
00391     }
00392 
00393     // Check static points over the movable box
00394     uint seg;
00395     for (seg=0; seg<4; seg++)
00396     {
00397         // Get collision time of the point over the segment
00398         CCollisionDesc d;
00399         if (evalCollisionSoverOC (other, d, seg, primitive, otherPrimitive))
00400         {
00401             // Found
00402             find=true;
00403 
00404             // Best time ?
00405             if (d.ContactTime<desc.ContactTime)
00406             {
00407                 // This is the new descriptor
00408                 desc=d;
00409             }
00410 
00411             // Best max time ?
00412             if (d.ContactTime>_timeMax)
00413             {
00414                 // New max time
00415                 _timeMax=d.ContactTime;
00416             }
00417         }
00418     }
00419 
00420     if (find)
00421     {
00422         // First last contact time
00423         firstContactTime=desc.ContactTime;
00424         lastContactTime=_timeMax;
00425 
00426         // Half time
00427         //double halfTime = (_timeMax+desc.ContactTime)/2.0;
00428 
00429         // Collision in the past ?
00430         //if (timeMin > halfTime)
00431         if (timeMin > _timeMax)
00432             // yes, abort
00433             return false;
00434 
00435         // Collision not in the future ?
00436         if (timeMax>desc.ContactTime)
00437         {
00438             // Clamp time
00439             if (desc.ContactTime<timeMin)
00440                 desc.ContactTime=timeMin;
00441 
00442             // yes, found it
00443             return true;
00444         }
00445     }
00446 
00447     // No collision found
00448     return false;
00449 }
00450 
00451 // ***************************************************************************
00452 
00453 bool CPrimitiveWorldImage::evalCollisionPoverS (CPrimitiveWorldImage& other, CCollisionDesc& desc, uint numPoint, uint numSeg,
00454                                                 CMovePrimitive& primitive, CMovePrimitive& otherPrimitive)
00455 {
00456     // Checks
00457     nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00458     nlassert (otherPrimitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00459 
00460     // Some constants
00461     const double normalSegX=other._OBData.EdgeDirectionY[numSeg];
00462     const double normalSegY=-other._OBData.EdgeDirectionX[numSeg];
00463 
00464     // Relative speed
00465     const double speedX=other._Speed.x-_Speed.x;
00466     const double speedY=other._Speed.y-_Speed.y;
00467 
00468     // Dot product with the plan tangeante
00469     double dotProd= speedX*normalSegX + speedY*normalSegY;
00470     //if ( dotProd > 0 )
00471     if ( dotProd != 0 )
00472     {
00473         // Time of the collision
00474         double time= (normalSegX*(_OBData.PointPosX[numPoint] - other._OBData.PointPosX[numSeg]) +
00475             normalSegY*(_OBData.PointPosY[numPoint] - other._OBData.PointPosY[numSeg])) / dotProd;
00476 
00477         // Position of segment point at collision time
00478         const double segPosX= other._OBData.PointPosX[numSeg] + other._Speed.x*time;
00479         const double segPosY= other._OBData.PointPosY[numSeg] + other._Speed.y*time;
00480 
00481         // Position of the point at collision time
00482         const double ptPosX= _OBData.PointPosX[numPoint] + _Speed.x*time;
00483         const double ptPosY= _OBData.PointPosY[numPoint] + _Speed.y*time;
00484 
00485         // Direction of the collision on the segment
00486         const double dirX= ptPosX - segPosX;
00487         const double dirY= ptPosY - segPosY;
00488 
00489         // Length of this vector
00490         const double length= dirY*normalSegX - dirX*normalSegY;
00491 
00492         // Included ?
00493         if ( ( length >= 0 ) && ( length <= otherPrimitive.getLength(numSeg&1) ) )
00494         {
00495             // 2d Collid checked... Now check height
00496 
00497             // Pos Z
00498             const double pointSegZ=other._3dInitPosition.z;
00499             const double segPosZ= pointSegZ + other._Speed.z*time;
00500 
00501             // Some constants
00502             const double pointZ=_3dInitPosition.z;
00503             const double ptPosZ= pointZ + _Speed.z*time;
00504 
00505             // Included ?
00506             if ( (ptPosZ <= segPosZ + otherPrimitive.getHeightInternal()) && (ptPosZ + primitive.getHeightInternal() >= segPosZ) )
00507             {
00508                 // Ok Collision, fill the result
00509 
00510                 // Time
00511                 desc.ContactTime=time;
00512 
00513                 // Position
00514                 desc.ContactPosition.x=ptPosX;
00515                 desc.ContactPosition.y=ptPosY;
00516                 desc.ContactPosition.z=std::max (segPosZ, ptPosZ);
00517 
00518                 // Seg box normal
00519                 desc.ContactNormal1.x=normalSegX;
00520                 desc.ContactNormal1.y=normalSegY;
00521                 desc.ContactNormal1.z=0;
00522                 desc.ContactNormal0.x=-desc.ContactNormal1.x;
00523                 desc.ContactNormal0.y=-desc.ContactNormal1.y;
00524                 desc.ContactNormal0.z=0;
00525 
00526                 // End
00527                 return true;
00528             }
00529         }
00530     }
00531 
00532     // No collision
00533     return false;
00534 }
00535 
00536 // ***************************************************************************
00537 
00538 inline uint secondDegree (double a, double b, double c, double& s0, double& s1)
00539 {
00540     double d=b*b-4.f*a*c;
00541     if (d>0)
00542     {
00543         // sqrt d
00544         d=(double)sqrt (d);
00545 
00546         // 1 / 2a
00547         a=0.5f/a;
00548 
00549         // 2 solutions
00550         s0 = (-b-d)*a;
00551         s1 = (-b+d)*a;
00552 
00553         return 2;
00554     }
00555     else if (d<0)
00556     {
00557         // No solution
00558         return 0;
00559     }
00560     else
00561     {
00562         // 1 solution
00563         s0 = -b/(2.f*a);
00564 
00565         return 1;
00566     }
00567 }
00568 
00569 // ***************************************************************************
00570 
00571 bool CPrimitiveWorldImage::evalCollisionPoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, uint numPoint,
00572                                            double &firstContactTime, double &lastContactTime, CMovePrimitive& primitive,
00573                                            CMovePrimitive& otherPrimitive)
00574 {
00575     // Checks
00576     nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00577     nlassert (otherPrimitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedCylinder);
00578 
00579     /* Point Equ:
00580      * p(t) = p0 + v0*(t - t0)
00581      *
00582      * Cylinder center Equ:
00583      * p'(t) = p'0 + v'0*(t - t'0)
00584      *
00585      * Find t for this equation:
00586      * R² = Norm² (p(t) - p'(t))
00587      * R² = Norm² ( p0 + v0 ( t - t0 ) - p'0 - v'0 ( t - t'0 ) )
00588      *
00589      * A = p0 - v0*t0 - p'0 + v'0*t'0
00590      * B = (v0 - v'0)
00591      *
00592      * Norm² (B)*t² + 2*(A.B)*t + Norm² (A) - R² = 0
00593      *
00594      * a = Norm² (B)
00595      * b = 2*(A.B)
00596      * c = Norm² (A) - R²
00597      *
00598      * a*t² + b*t + c = 0
00599      */
00600 
00601     // Let's go
00602     const double _Ax = _OBData.PointPosX[numPoint] - other._3dInitPosition.x;
00603     const double _Ay = _OBData.PointPosY[numPoint] - other._3dInitPosition.y;
00604     const double _Bx = _Speed.x - other._Speed.x;
00605     const double _By = _Speed.y - other._Speed.y;
00606 
00607     // Eval system
00608     double s0, s1;
00609     double squareRadius=otherPrimitive.getRadiusInternal()*otherPrimitive.getRadiusInternal();
00610     uint numSolution=secondDegree (_Bx*_Bx+_By*_By, 2.f*(_Ax*_Bx+_Ay*_By), _Ax*_Ax+_Ay*_Ay-squareRadius, s0, s1);
00611     if (numSolution!=0)
00612     {
00613         // time
00614         double time;
00615 
00616         // Collision time
00617         if (numSolution==1)
00618         {
00619             firstContactTime=s0;
00620             lastContactTime=s0;
00621         }
00622         else
00623         {
00624             // First and last time
00625             if (s0<s1)
00626             {
00627                 firstContactTime=s0;
00628                 lastContactTime=s1;
00629             }
00630             else
00631             {
00632                 firstContactTime=s1;
00633                 lastContactTime=s0;
00634             }
00635         }
00636         time=firstContactTime;
00637 
00638         // Pos Z
00639         const double pointCylZ=other._3dInitPosition.z;
00640         const double cylPosZ= pointCylZ + other._Speed.z*time;
00641 
00642         // Some constants
00643         const double pointZ=_3dInitPosition.z;
00644         const double ptPosZ= pointZ + _Speed.z*time;
00645 
00646         // Z Included ?
00647         if ( (ptPosZ <= cylPosZ + otherPrimitive.getHeightInternal()) && (ptPosZ + primitive.getHeightInternal() >= cylPosZ) )
00648         {
00649             // Ok Collision, fill the result
00650 
00651             // Time
00652             desc.ContactTime=time;
00653 
00654             // Point position
00655             const double ptPosX= _OBData.PointPosX[numPoint] + _Speed.x*time;
00656             const double ptPosY= _OBData.PointPosY[numPoint] + _Speed.y*time;
00657 
00658             // Cylinder position
00659             const double cylPosX= other._3dInitPosition.x + other._Speed.x*time;
00660             const double cylPosY= other._3dInitPosition.y + other._Speed.y*time;
00661 
00662             // Position
00663             desc.ContactPosition.x=ptPosX;
00664             desc.ContactPosition.y=ptPosY;
00665             desc.ContactPosition.z=std::max (cylPosZ, ptPosZ);
00666 
00667             // Cylinder normal
00668             desc.ContactNormal1.x=ptPosX-cylPosX;
00669             desc.ContactNormal1.y=ptPosY-cylPosY;
00670             desc.ContactNormal1.z=0;
00671             desc.ContactNormal1.normalize ();
00672             desc.ContactNormal0.x=-desc.ContactNormal1.x;
00673             desc.ContactNormal0.y=-desc.ContactNormal1.y;
00674             desc.ContactNormal0.z=0;
00675 
00676             // End
00677             return true;
00678         }
00679     }
00680 
00681     // No collision
00682     return false;
00683 }
00684 
00685 // ***************************************************************************
00686 
00687 bool CPrimitiveWorldImage::evalCollisionSoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, uint numSeg, CMovePrimitive& primitive,
00688                                            CMovePrimitive& otherPrimitive)
00689 {
00690     // Checks
00691     nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedBox);
00692     nlassert (otherPrimitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedCylinder);
00693 
00694     // Some constants
00695     const double normalSegX=_OBData.EdgeDirectionY[numSeg];
00696     const double normalSegY=-_OBData.EdgeDirectionX[numSeg];
00697 
00698     // Relative speed
00699     const double speedX=other._Speed.x-_Speed.x;
00700     const double speedY=other._Speed.y-_Speed.y;
00701 
00702     // Dot product with the plan tangeante
00703     double dotProd= speedX*normalSegX + speedY*normalSegY;
00704     //if ( dotProd < 0 )
00705     if ( dotProd !=0 )
00706     {
00707         // Time of the collision
00708         double time= (otherPrimitive.getRadiusInternal() + normalSegX*(_OBData.PointPosX[numSeg] - other._3dInitPosition.x ) +
00709             normalSegY*(_OBData.PointPosY[numSeg] - other._3dInitPosition.y ) ) / dotProd;
00710 
00711         // Position of segment point at collision time
00712         const double segPosX= _OBData.PointPosX[numSeg] + _Speed.x*time;
00713         const double segPosY= _OBData.PointPosY[numSeg] + _Speed.y*time;
00714 
00715         // Position of the cylinder at collision time
00716         const double cylPosX= other._3dInitPosition.x + _Speed.x*time;
00717         const double cylPosY= other._3dInitPosition.y + _Speed.y*time;
00718 
00719         // Position de contact
00720         const double contactX= cylPosX - normalSegX*otherPrimitive.getRadiusInternal();
00721         const double contactY= cylPosY - normalSegY*otherPrimitive.getRadiusInternal();
00722 
00723         // Direction of the collision on the segment
00724         const double dirX= contactX - segPosX;
00725         const double dirY= contactY - segPosY;
00726 
00727         // Length of this vector
00728         const double length= dirY*normalSegX - dirX*normalSegY;
00729 
00730         // Included ?
00731         if ( ( length >= 0 ) && ( length <= primitive.getLength (numSeg&1) ) )
00732         {
00733             // 2d Collid checked... Now check height
00734 
00735             // Pos Z
00736             const double segPosZ= _3dInitPosition.z + _Speed.z*time;
00737 
00738             // Some constants
00739             const double cylPosZ= other._3dInitPosition.z + other._Speed.z*time;
00740 
00741             // Included ?
00742             if ( (cylPosZ <= segPosZ + primitive.getHeightInternal() ) && (cylPosZ + otherPrimitive.getHeightInternal() >= segPosZ) )
00743             {
00744                 // Ok Collision, fill the result
00745 
00746                 // Time
00747                 desc.ContactTime=time;
00748 
00749                 // Position
00750                 desc.ContactPosition.x=contactX;
00751                 desc.ContactPosition.y=contactY;
00752                 desc.ContactPosition.z=std::max (segPosZ, cylPosZ);
00753 
00754                 // Segment normal
00755                 desc.ContactNormal0.x=normalSegX;
00756                 desc.ContactNormal0.y=normalSegY;
00757                 desc.ContactNormal0.z=0;
00758 
00759                 // Seg box normal
00760                 desc.ContactNormal1.x=contactX-cylPosX;
00761                 desc.ContactNormal1.y=contactY-cylPosY;
00762                 desc.ContactNormal1.z=0;
00763                 desc.ContactNormal1.normalize ();
00764 
00765                 // End
00766                 return true;
00767             }
00768         }
00769     }
00770 
00771     // No collision
00772     return false;
00773 }
00774 
00775 
00776 // ***************************************************************************
00777 
00778 bool CPrimitiveWorldImage::evalCollisionOCoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin, double timeMax,
00779                                             double &firstContactTime, double &lastContactTime, CMovePrimitive& primitive,
00780                                            CMovePrimitive& otherPrimitive)
00781 {
00782     // Checks
00783     nlassert (primitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedCylinder);
00784     nlassert (otherPrimitive.getPrimitiveTypeInternal()==UMovePrimitive::_2DOrientedCylinder);
00785 
00786 
00787     /* Cylinder0 center equ:
00788      * p(t) = p0 + v0*(t - t0)
00789      *
00790      * Cylinder1 center equ:
00791      * p'(t) = p'0 + v'0*(t - t'0)
00792      *
00793      * Find t for this equation:
00794      * (R + R')² = Norm² (p(t) - p'(t))
00795      * (R + R')² = Norm² ( p0 + v0 ( t - t0 ) - p'0 - v'0 ( t - t'0 ) )
00796      *
00797      * A = p0 - v0*t0 - p'0 + v'0*t'0
00798      * B = (v0 - v'0)
00799      *
00800      * Norm² (B)*t² + 2*(A.B)*t + Norm² (A) - (R + R')² = 0
00801      *
00802      * a = Norm² (B)
00803      * b = 2*(A.B)
00804      * c = Norm² (A) - (R + R')²
00805      *
00806      * a*t² + b*t + c = 0
00807      */
00808 
00809     // Let's go
00810     const double _Ax = _3dInitPosition.x - other._3dInitPosition.x;
00811     const double _Ay = _3dInitPosition.y - other._3dInitPosition.y;
00812     const double _Bx = _Speed.x - other._Speed.x;
00813     const double _By = _Speed.y - other._Speed.y;
00814 
00815     // Eval system
00816     double s0, s1;
00817     double radiusSquare=primitive.getRadiusInternal()+otherPrimitive.getRadiusInternal();
00818     radiusSquare*=radiusSquare;
00819     uint numSolution=secondDegree (_Bx*_Bx+_By*_By, 2.f*(_Ax*_Bx+_Ay*_By), _Ax*_Ax+_Ay*_Ay-radiusSquare, s0, s1);
00820     if (numSolution!=0)
00821     {
00822         // time
00823         double _timeMin, _timeMax;
00824 
00825         // Collision time
00826         if (numSolution==1)
00827         {
00828             _timeMin=s0;
00829             _timeMax=s0;
00830         }
00831         else
00832         {
00833             // Time min and max
00834             if (s0>s1)
00835             {
00836                 _timeMin=s1;
00837                 _timeMax=s0;
00838             }
00839             else
00840             {
00841                 _timeMin=s0;
00842                 _timeMax=s1;
00843             }
00844         }
00845 
00846         // half time
00847         //const double halfTime=(_timeMin+_timeMax)/2.0;
00848 
00849         // Conatct time
00850         firstContactTime=_timeMin;
00851         lastContactTime=_timeMax;
00852 
00853         // Clip time
00854         if ((timeMin<_timeMax)&&(_timeMin<timeMax))
00855         {
00856             // Some constants
00857             const double cyl0Time= _timeMin;
00858             const double pointCyl0Z=_3dInitPosition.z;
00859             const double cyl0PosZ= pointCyl0Z + _Speed.z*cyl0Time;
00860 
00861             // Pos Z
00862             const double cyl1Time= _timeMin;
00863             const double pointCyl1Z=other._3dInitPosition.z;
00864             const double cyl1PosZ= pointCyl1Z + other._Speed.z * cyl1Time;
00865 
00866             // Z Included ?
00867             if ( (cyl0PosZ <= cyl1PosZ + otherPrimitive.getHeightInternal() ) && (cyl0PosZ + primitive.getHeightInternal() >= cyl1PosZ) )
00868             {
00869                 // Ok Collision, fill the result
00870 
00871                 // Time
00872                 desc.ContactTime=std::max (_timeMin, timeMin);
00873 
00874                 // Cylinder 0 position
00875                 const double cyl0PosX= _3dInitPosition.x + _Speed.x*cyl0Time;
00876                 const double cyl0PosY= _3dInitPosition.y + _Speed.y*cyl0Time;
00877 
00878                 // Cylinder 1 position
00879                 const double cyl1PosX= other._3dInitPosition.x + other._Speed.x*cyl1Time;
00880                 const double cyl1PosY= other._3dInitPosition.y + other._Speed.y*cyl1Time;
00881 
00882                 // First cylinder normal
00883                 desc.ContactNormal0.x= cyl1PosX - cyl0PosX;
00884                 desc.ContactNormal0.y= cyl1PosY - cyl0PosY;
00885                 desc.ContactNormal0.z= 0;
00886                 desc.ContactNormal0.normalize ();
00887 
00888                 // Contact position
00889                 desc.ContactPosition.x= desc.ContactNormal0.x*primitive.getRadiusInternal() + cyl0PosX;
00890                 desc.ContactPosition.y= desc.ContactNormal0.y*primitive.getRadiusInternal() + cyl0PosY;
00891                 desc.ContactPosition.z= std::max (cyl0PosZ, cyl1PosZ);
00892 
00893                 // Second cylinder normal
00894                 desc.ContactNormal1.x= -desc.ContactNormal0.x;
00895                 desc.ContactNormal1.y= -desc.ContactNormal0.y;
00896                 desc.ContactNormal1.z= 0;
00897 
00898                 // End
00899                 return true;
00900             }
00901         }
00902     }
00903 
00904     // No collision
00905     return false;
00906 }
00907 
00908 // ***************************************************************************
00909 
00910 void CPrimitiveWorldImage::precalcPos (CMovePrimitive &primitive)
00911 {
00912     // Type of the primitive
00913     uint type=primitive.getPrimitiveTypeInternal();
00914 
00915     // Box ?
00916     if (type==UMovePrimitive::_2DOrientedBox)
00917     {
00918         // Calc cosinus and sinus
00919         double cosinus=(double)cos(_OBData.Orientation);
00920         double sinus=(double)sin(_OBData.Orientation);
00921 
00922         // Size
00923         double halfWidth=primitive.getLength (0)/2;
00924         double halfDepth=primitive.getLength (1)/2;
00925 
00926         // First point
00927         _OBData.PointPosX[0]=cosinus*(-halfWidth)-sinus*(-halfDepth)+_3dInitPosition.x;
00928         _OBData.PointPosY[0]=sinus*(-halfWidth)+cosinus*(-halfDepth)+_3dInitPosition.y;
00929 
00930         // Second point
00931         _OBData.PointPosX[1]=cosinus*halfWidth-sinus*(-halfDepth)+_3dInitPosition.x;
00932         _OBData.PointPosY[1]=sinus*halfWidth+cosinus*(-halfDepth)+_3dInitPosition.y;
00933 
00934         // Third point
00935         _OBData.PointPosX[2]=cosinus*halfWidth-sinus*halfDepth+_3dInitPosition.x;
00936         _OBData.PointPosY[2]=sinus*halfWidth+cosinus*halfDepth+_3dInitPosition.y;
00937 
00938         // Fourth point
00939         _OBData.PointPosX[3]=cosinus*(-halfWidth)-sinus*halfDepth+_3dInitPosition.x;
00940         _OBData.PointPosY[3]=sinus*(-halfWidth)+cosinus*halfDepth+_3dInitPosition.y;
00941 
00942         // Direction
00943         double length0 = (primitive.getLength(0)==0)? 0.001 : primitive.getLength(0);
00944         double length1 = (primitive.getLength(1)==0)? 0.001 : primitive.getLength(1);
00945         double oneOverLength[2]= { 1 / length0, 1 / length1 };
00946 
00947         // Direction
00948         uint i;
00949         for (i=0; i<4; i++)
00950         {
00951             // Next index
00952             uint next=(i+1)&3;
00953             double oneOver=oneOverLength[i&1];
00954 
00955             // New direction
00956             _OBData.EdgeDirectionX[i]=(_OBData.PointPosX[next] - _OBData.PointPosX[i])*oneOver;
00957             _OBData.EdgeDirectionY[i]=(_OBData.PointPosY[next] - _OBData.PointPosY[i])*oneOver;
00958         }
00959     }
00960     else
00961     {
00962         // Should be a cylinder
00963         nlassert (type==UMovePrimitive::_2DOrientedCylinder);
00964     }
00965 }
00966 
00967 // ***************************************************************************
00968 
00969 void CPrimitiveWorldImage::precalcBB (double beginTime, double endTime, CMovePrimitive &primitive)
00970 {
00971     // Type of the primitive
00972     uint type=primitive.getPrimitiveTypeInternal();
00973 
00974     // Box ?
00975     if (type==UMovePrimitive::_2DOrientedBox)
00976     {
00977         // Orientation index
00978         sint orient= (sint)(256.f*_OBData.Orientation/(2.f*NLMISC::Pi));
00979         orient&=0xff;
00980         orient>>=6;
00981         nlassert (orient>=0);
00982         nlassert (orient<4);
00983 
00984         // Compute coordinates
00985         _BBXMin=FLT_MAX;
00986         _BBYMin=FLT_MAX;
00987         _BBXMax=-FLT_MAX;
00988         _BBYMax=-FLT_MAX;
00989 
00990         for (uint i=0; i<4; i++)
00991         {
00992             if (_OBData.PointPosX[i]<_BBXMin)
00993                 _BBXMin=_OBData.PointPosX[i];
00994             if (_OBData.PointPosX[i]>_BBXMax)
00995                 _BBXMax=_OBData.PointPosX[i];
00996             if (_OBData.PointPosY[i]<_BBYMin)
00997                 _BBYMin=_OBData.PointPosY[i];
00998             if (_OBData.PointPosY[i]>_BBYMax)
00999                 _BBYMax=_OBData.PointPosY[i];
01000         }
01001         _BBXMin=std::min (std::min (_BBXMin, _BBXMin+endTime*_Speed.x), _BBXMin+beginTime*_Speed.x);
01002         _BBXMax=std::max (std::max (_BBXMax, _BBXMax+endTime*_Speed.x), _BBXMax+beginTime*_Speed.x);
01003         _BBYMin=std::min (std::min (_BBYMin, _BBYMin+endTime*_Speed.y), _BBYMin+beginTime*_Speed.y);
01004         _BBYMax=std::max (std::max (_BBYMax, _BBYMax+endTime*_Speed.y), _BBYMax+beginTime*_Speed.y);
01005 
01006 /*
01007         // This code is faster but buggy..
01008         _BBXMin= _OBData.PointPosX[minX[orient]] + _Speed.x*beginTime;
01009         _BBXMin= std::min (_BBXMin, _OBData.PointPosX[minX[orient]] + _Speed.x*endTime);
01010 
01011         _BBYMin= _OBData.PointPosY[minY[orient]] + _Speed.y*beginTime;
01012         _BBYMin= std::min (_BBYMin, _OBData.PointPosY[minY[orient]] + _Speed.y*endTime);
01013 
01014         _BBXMax= _OBData.PointPosX[maxX[orient]] + _Speed.x*beginTime;
01015         _BBXMax= std::max (_BBXMax, _OBData.PointPosX[maxX[orient]] + _Speed.x*endTime);
01016 
01017         _BBYMax= _OBData.PointPosY[maxY[orient]] + _Speed.y*beginTime;
01018         _BBYMax= std::max (_BBYMax, _OBData.PointPosY[maxY[orient]] + _Speed.y*endTime);*/
01019     }
01020     else
01021     {
01022         // Should be a cylinder
01023         nlassert (type==UMovePrimitive::_2DOrientedCylinder);
01024 
01025         // Compute X coordinates
01026         _BBXMin= _3dInitPosition.x + _Speed.x*beginTime;
01027         _BBXMax= _3dInitPosition.x + _Speed.x*endTime;
01028         if (_BBXMin>_BBXMax)
01029         {
01030             double tmp=_BBXMin;
01031             _BBXMin=_BBXMax;
01032             _BBXMax=tmp;
01033         }
01034         _BBXMin-=primitive.getRadiusInternal();
01035         _BBXMax+=primitive.getRadiusInternal();
01036 
01037         // Compute Y coordinates
01038         _BBYMin= _3dInitPosition.y + _Speed.y*beginTime;
01039         _BBYMax= _3dInitPosition.y + _Speed.y*endTime;
01040         if (_BBYMin>_BBYMax)
01041         {
01042             double tmp=_BBYMin;
01043             _BBYMin=_BBYMax;
01044             _BBYMax=tmp;
01045         }
01046         _BBYMin-=primitive.getRadiusInternal();
01047         _BBYMax+=primitive.getRadiusInternal();
01048     }
01049 
01050     // Delta position
01051     _DeltaPosition=_Speed*(endTime-beginTime);
01052 }
01053 
01054 // ***************************************************************************
01055 
01056 void CPrimitiveWorldImage::addMoveElement (CMoveCell& cell, uint16 x, uint16 y, double centerX, double /* centerY */, CMovePrimitive *primitive,
01057                                            CMoveContainer &container, uint8 worldImage)
01058 {
01059     // Find a free place
01060     uint slot;
01061     for (slot=0; slot<4; slot++)
01062     {
01063         // Empty ?
01064         if (_MoveElement[slot]==NULL)
01065         {
01066             // Primitive center
01067             double cx=(_BBXMin+_BBXMax)/2.f;
01068 
01069             // Allocate move element
01070             _MoveElement[slot]=container.allocateMoveElement ();
01071             _MoveElement[slot]->Primitive=primitive;
01072             _MoveElement[slot]->X=x;
01073             _MoveElement[slot]->Y=y;
01074 
01075             // Insert in left or right ?
01076             if (cx<centerX)
01077                 // In the left
01078                 cell.linkFirstX (_MoveElement[slot]);
01079             else
01080                 // In the right
01081                 cell.linkLastX (_MoveElement[slot]);
01082 
01083             /*// Insert in left or right ?
01084             if (cy<centerY)
01085                 // In the left
01086                 cell.linkFirstY (_MoveElement[slot]);
01087             else
01088                 // In the right
01089                 cell.linkLastY (_MoveElement[slot]);*/
01090 
01091             // Move it
01092              cell.updateSortedLists (_MoveElement[slot], worldImage);
01093 
01094             // End
01095             break;
01096         }
01097     }
01098 }
01099 
01100 // ***************************************************************************
01101 
01102 void CPrimitiveWorldImage::addMoveElementendOfList (CMoveCell& cell, uint16 x, uint16 y, CMovePrimitive *primitive,
01103                                                     CMoveContainer &container)
01104 {
01105     // Find a free place
01106     uint slot;
01107     for (slot=0; slot<4; slot++)
01108     {
01109         // Empty ?
01110         if (_MoveElement[slot]==NULL)
01111         {
01112             // Allocate move element
01113             _MoveElement[slot]=container.allocateMoveElement ();
01114             _MoveElement[slot]->Primitive=primitive;
01115             _MoveElement[slot]->X=x;
01116             _MoveElement[slot]->Y=y;
01117 
01118             // In the right
01119             cell.linkLastX (_MoveElement[slot]);
01120 
01121             // End
01122             break;
01123         }
01124     }
01125 }
01126 
01127 // ***************************************************************************
01128 
01129 void CPrimitiveWorldImage::removeMoveElement (uint i, CMoveContainer &container, uint8 worldImage)
01130 {
01131     // Check
01132     nlassert (i<4);
01133     nlassert (_MoveElement[i]!=NULL);
01134 
01135     // Unlink the element
01136     container.unlinkMoveElement (_MoveElement[i], worldImage);
01137 
01138     // Free the move element
01139     container.freeMoveElement (_MoveElement[i]);
01140 
01141     // Set to NULL
01142     _MoveElement[i]=NULL;
01143 }
01144 
01145 // ***************************************************************************
01146 
01147 void CPrimitiveWorldImage::checkSortedList (uint8 worldImage)
01148 {
01149     // For the 4 elements
01150     for (uint i=0; i<4; i++)
01151     {
01152         // element here ?
01153         if (_MoveElement[i])
01154         {
01155             if (_MoveElement[i]->PreviousX)
01156                 nlassertonce (_MoveElement[i]->PreviousX->Primitive->getWorldImage(worldImage)->_BBXMin <= _BBXMin);
01157             if (_MoveElement[i]->NextX)
01158                 nlassertonce (_BBXMin <= _MoveElement[i]->NextX->Primitive->getWorldImage(worldImage)->_BBXMin);
01159         }
01160     }
01161 }
01162 
01163 // ***************************************************************************
01164 
01165 void CPrimitiveWorldImage::reaction (CPrimitiveWorldImage& second, const CCollisionDesc& desc, CGlobalRetriever* retriever,
01166                                CCollisionSurfaceTemp& surfaceTemp, bool collision, CMovePrimitive &primitive,
01167                                CMovePrimitive &otherPrimitive, CMoveContainer *container, uint8 worldImage, uint8 secondWorldImage,
01168                                bool secondConst)
01169 {
01170 //  H_AUTO(PACS_PWI_reaction_long);
01171 
01172     // Get the two reaction codes
01173     UMovePrimitive::TReaction firstReaction=primitive.getReactionTypeInternal();
01174     UMovePrimitive::TReaction secondReaction=otherPrimitive.getReactionTypeInternal();
01175 
01176     // Overide collsion
01177     collision = collision && (primitive.isObstacle ()) && (otherPrimitive.isObstacle ());
01178 
01179     // Get the two mass
01180     float mass0 = primitive.getMass ();
01181     float mass1 = otherPrimitive.getMass ();
01182 
01183     // Energy sum
01184     double projSpeed0 = desc.ContactNormal1 * _Speed;
01185     double projSpeed1 = desc.ContactNormal0 * second._Speed;
01186     double energySum = (- mass0 * projSpeed0 - mass1 * projSpeed1 ) / 2.0;
01187 
01188     // Old position
01189     CVectorD collisionPosition=_3dInitPosition;
01190     collisionPosition+=_Speed*desc.ContactTime;
01191 
01192     // Calc new speed
01193     CVectorD newSpeed;
01194 
01195     // Obstacle ?
01196     if (collision)
01197     {
01198         switch (firstReaction)
01199         {
01200         case UMovePrimitive::Slide:
01201             // Remove projected speed
01202             newSpeed=_Speed - projSpeed0 * desc.ContactNormal1;
01203 
01204             // Reflexion speed
01205             newSpeed+=( primitive.getAttenuation()*energySum / mass0 ) * desc.ContactNormal1;
01206             break;
01207         case UMovePrimitive::Reflexion:
01208             // Remove projected speed
01209             newSpeed=_Speed - projSpeed0 * desc.ContactNormal1;
01210 
01211             // Reflexion speed
01212             newSpeed+=( primitive.getAttenuation()*energySum / mass0 ) * desc.ContactNormal1;
01213             break;
01214         case UMovePrimitive::Stop:
01215             newSpeed.set (0,0,0);
01216             break;
01217         case UMovePrimitive::DoNothing:
01218             newSpeed=_Speed;
01219             break;
01220         default: break;
01221         }
01222 
01223         // Set new speed
01224         setSpeed (newSpeed, container, &primitive, worldImage);
01225 
01226         // New position at t=0
01227         if (retriever)
01228         {
01229             // Make a domove in the Ben data
01230             double  deltaDist= _DeltaPosition.norm();
01231             double  deltaTime;
01232             if(deltaDist<0.000001)
01233                 deltaTime= 0;
01234             else
01235                 deltaTime=(collisionPosition-_Position.getPos ()).norm()/deltaDist;
01236             nlassert (deltaTime>=0);
01237             nlassert (deltaTime<=1);
01238 
01239             UGlobalPosition newPosition = retriever->doMove (_Position.getGlobalPos (), _DeltaPosition,
01240                 (float)deltaTime, surfaceTemp, true);
01241 
01242             // Set the new position
01243             _Position.setGlobalPos (newPosition, *retriever);
01244 
01245             // Position at t=0
01246             _3dInitPosition = _Position.getPos() - newSpeed * desc.ContactTime;
01247 
01248             // New init time
01249             _InitTime = desc.ContactTime;
01250         }
01251         else
01252         {
01253             // No retriever used
01254             _Position.setPos (collisionPosition);
01255 
01256             // Position at t=0
01257             _3dInitPosition = collisionPosition - newSpeed * desc.ContactTime;
01258 
01259             // New init time
01260             _InitTime = desc.ContactTime;
01261         }
01262 
01263         // Dirt pos
01264         dirtPos (container, &primitive, worldImage);
01265 
01266         // ****** Second object
01267 
01268         // Is second object in a static world ?
01269         if (!secondConst)
01270         {
01271             // Old position
01272             collisionPosition=second._3dInitPosition;
01273             collisionPosition+=second._Speed * desc.ContactTime;
01274 
01275             // Obstacle ?
01276             switch (secondReaction)
01277             {
01278             case UMovePrimitive::Slide:
01279                 // Remove projected speed
01280                 newSpeed=second._Speed - projSpeed1 * desc.ContactNormal0;
01281 
01282                 // Reflexion speed
01283                 newSpeed+=( otherPrimitive.getAttenuation()*energySum / mass1 ) * desc.ContactNormal1;
01284                 break;
01285             case UMovePrimitive::Reflexion:
01286                 // Remove projected speed
01287                 newSpeed=second._Speed - projSpeed1 * desc.ContactNormal0;
01288 
01289                 // Reflexion speed
01290                 newSpeed+=( otherPrimitive.getAttenuation()*energySum / mass1 ) * desc.ContactNormal0;
01291                 break;
01292             case UMovePrimitive::Stop:
01293                 newSpeed.set (0,0,0);
01294                 break;
01295             case UMovePrimitive::DoNothing:
01296                 newSpeed=second._Speed;
01297                 break;
01298             default: break;
01299             }
01300 
01301             // Set new speed
01302             second.setSpeed (newSpeed, container, &otherPrimitive, secondWorldImage);
01303 
01304             // New position at t=0
01305             if (retriever)
01306             {
01307                 // Make a domove in the Ben data
01308                 double  deltaDist= second._DeltaPosition.norm();
01309                 double  deltaTime;
01310                 if(deltaDist==0)
01311                     deltaTime= 0;
01312                 else
01313                     deltaTime=(collisionPosition-second._Position.getPos ()).norm()/deltaDist;
01314                 clamp (deltaTime, 0.0, 1.0);
01315 
01316                 UGlobalPosition newPosition = retriever->doMove (second._Position.getGlobalPos (), second._DeltaPosition,
01317                     (float)deltaTime, surfaceTemp, true);
01318 
01319                 // Set the new position
01320                 second._Position.setGlobalPos (newPosition, *retriever);
01321 
01322                 // Position at t=0
01323                 second._3dInitPosition = second._Position.getPos() - newSpeed * desc.ContactTime;
01324 
01325                 // New init time
01326                 second._InitTime = desc.ContactTime;
01327             }
01328             else
01329             {
01330                 // No retriever used
01331                 second._Position.setPos (collisionPosition);
01332 
01333                 // Position at t=0
01334                 second._3dInitPosition = collisionPosition - newSpeed * desc.ContactTime;
01335 
01336                 // New init time
01337                 second._InitTime = desc.ContactTime;
01338             }
01339 
01340             // Dirt pos
01341             second.dirtPos (container, &otherPrimitive, secondWorldImage);
01342         }
01343     }
01344 }
01345 
01346 // ***************************************************************************
01347 
01348 void CPrimitiveWorldImage::reaction (const CCollisionSurfaceDesc&   surfaceDesc, const UGlobalPosition& globalPosition,
01349                                CGlobalRetriever& retriever, double /* ratio */, double dt, CMovePrimitive &primitive, CMoveContainer &container,
01350                                uint8 worldImage)
01351 {
01352 //  H_AUTO(PACS_PWI_reaction_short);
01353 
01354     // Reaction type
01355     uint32 type=primitive.getReactionTypeInternal();
01356 
01357     // Reaction to the collision: copy the CGlobalRetriever::CGlobalPosition
01358     _Position.setGlobalPos (globalPosition, retriever);
01359 
01360     // Relfexion or slide ?
01361     if ((type==UMovePrimitive::Reflexion)||(type==UMovePrimitive::Slide))
01362     {
01363         // Slide ?
01364         if (type==UMovePrimitive::Slide)
01365         {
01366             // Project last delta on plane of collision.
01367             _Speed-= surfaceDesc.ContactNormal*(surfaceDesc.ContactNormal*_Speed-NELPACS_DIST_BACK/(dt-surfaceDesc.ContactTime));
01368         }
01369 
01370         // Reflexion ?
01371         if (type==UMovePrimitive::Reflexion)
01372         {
01373             // Project last delta on plane of collision.
01374             double speedProj=surfaceDesc.ContactNormal*_Speed;
01375             _Speed-=surfaceDesc.ContactNormal*(speedProj+speedProj*primitive.getAttenuation()-NELPACS_DIST_BACK/(dt-surfaceDesc.ContactTime));
01376         }
01377     }
01378     else
01379     {
01380         // Stop ?
01381         if (type==UMovePrimitive::Stop)
01382         {
01383             _Speed.set (0,0,0);
01384         }
01385     }
01386 
01387     // Contact time
01388     double contactTime=surfaceDesc.ContactTime;
01389 
01390     // Init position
01391     _3dInitPosition = _Position.getPos() - _Speed * contactTime;
01392 
01393     // Set contactTime
01394     _InitTime=contactTime;
01395 
01396     // Dirt pos
01397     dirtPos (&container, &primitive, worldImage);
01398 }
01399 
01400 // ***************************************************************************
01401 
01402 void CPrimitiveWorldImage::setGlobalPosition (const UGlobalPosition& pos, CMoveContainer& container, CMovePrimitive &primitive, uint8 worldImage)
01403 {
01404     // Cast type
01405     nlassert (dynamic_cast<const CMoveContainer*>(&container));
01406     const CMoveContainer *cont=(const CMoveContainer*)&container;
01407 
01408     if (!cont->getGlobalRetriever()) return;
01409     // Use the global retriever ?
01410     nlassert (cont->getGlobalRetriever());
01411 
01412     // Get the pos
01413     _Position.setGlobalPos (pos, *cont->getGlobalRetriever());
01414 
01415     // Precalc some values
01416     _3dInitPosition = _Position.getPos ();
01417     _InitTime = 0;
01418 
01419     // Speed NULL
01420     _Speed=CVector::Null;
01421 
01422     // Dirt BB
01423     dirtPos (&container, &primitive, worldImage);
01424 }
01425 
01426 // ***************************************************************************
01427 
01428 void CPrimitiveWorldImage::setGlobalPosition (const NLMISC::CVectorD& pos, CMoveContainer& container, CMovePrimitive &primitive, uint8 worldImage, bool keepZ /*= false*/, UGlobalPosition::TType type /* =UGlobalPosition::Unspecified*/)
01429 {
01430     // Cast type
01431     nlassert (dynamic_cast<const CMoveContainer*>(&container));
01432     const CMoveContainer *cont=(const CMoveContainer*)&container;
01433 
01434     // Get the retriever
01435     CGlobalRetriever *retriever=cont->getGlobalRetriever();
01436 
01437     // Use a global retriever
01438     if (retriever)
01439     {
01440         // Get a cvector
01441 //      CVector vect=pos;       // better with CVectorD
01442 
01443         // Get global position
01444         UGlobalPosition globalPosition=retriever->retrievePosition (pos, 1.0e10, type);
01445 
01446         if (keepZ)
01447         {
01448             // Set the position
01449             _Position.setPos (pos);
01450 
01451             // Set global position
01452             _Position.setGlobalPosKeepZ (globalPosition, *retriever);
01453         }
01454         else
01455         {
01456             // Set global position
01457             _Position.setGlobalPos (globalPosition, *retriever);
01458         }
01459     }
01460     else
01461     {
01462         // Set the position
01463         _Position.setPos (pos);
01464     }
01465 
01466     // Precalc some values
01467     _3dInitPosition = _Position.getPos ();
01468     _InitTime = 0;
01469 
01470     // Speed NULL
01471     _Speed=CVector::Null;
01472 
01473     // Dirt BB
01474     dirtPos (&container, &primitive, worldImage);
01475 }
01476 
01477 // ***************************************************************************
01478 
01479 void CPrimitiveWorldImage::move (const NLMISC::CVectorD& speed, CMoveContainer& container, CMovePrimitive &primitive, uint8 worldImage)
01480 {
01481     // New speed
01482     setSpeed (speed, &container, &primitive, worldImage);
01483 
01484     // Set initial position
01485     _3dInitPosition = _Position.getPos ();
01486 
01487     // Set initial time
01488     _InitTime = 0;
01489 
01490     // Dirt BB
01491     dirtPos (&container, &primitive, worldImage);
01492 }
01493 
01494 // ***************************************************************************
01495 
01496 
01497 } // NLPACS

Generated on Thu Jan 7 08:26:36 2010 for NeL by  doxygen 1.6.1