move_container.cpp File Reference


Detailed Description

Id
move_container.cpp,v 1.45 2004/02/09 14:57:33 legros Exp

Definition in file move_container.cpp.

#include "stdpacs.h"
#include "pacs/move_primitive.h"
#include "pacs/move_element.h"
#include "pacs/primitive_block.h"
#include "nel/misc/hierarchical_timer.h"
#include "nel/misc/i_xml.h"
#include <math.h>
#include <float.h>

Go to the source code of this file.

Defines

#define NELPACS_ALLOC_DYNAMIC_INFO   100
#define NELPACS_ALLOC_STATIC_INFO   100
#define NLPACS_HAUTO_EVAL_COLLISION   H_AUTO_USE ( NLPACS_Eval_Collision )

Functions

 H_AUTO_DECL (NLPACS_Eval_Collision) namespace NLPACS


Define Documentation

#define NELPACS_ALLOC_DYNAMIC_INFO   100
 

Definition at line 40 of file move_container.cpp.

#define NELPACS_ALLOC_STATIC_INFO   100
 

Definition at line 41 of file move_container.cpp.

#define NLPACS_HAUTO_EVAL_COLLISION   H_AUTO_USE ( NLPACS_Eval_Collision )
 

Referenced by H_AUTO_DECL().


Function Documentation

H_AUTO_DECL NLPACS_Eval_Collision   ) 
 

Definition at line 43 of file move_container.cpp.

References file, NLMISC::CMatrix::getPos(), H_AUTO, height, index, min, NLMISC::CMatrix::mulVector(), NELPACS_CONTAINER_TRIGGER_DEFAULT_SIZE, NELPACS_DIST_BACK, nlassert, NLPACS_HAUTO_EVAL_COLLISION, nlwarning, NLMISC::CVector::normalize(), NLMISC::Pi, r, NLMISC::IStream::serial(), sint, size, uint, uint16, uint8, width, x, NLMISC::CVector::x, y, NLMISC::CVector::y, and NLMISC::CVector::z.

00048    : 
00049 
00050           // Non collisionnable primitive
00051         Their moves are evaluate one by one with evalNCPrimitiveCollision().
00052         If a collision is found, reaction() is called.
00053   
00054         // Collisionnable primitives
00055         Each primitive must be moved first with the move() method.
00056         Their moves are evaluate all at once. All the collisions found are time sorted in a time orderin table (_TimeOT).
00057         While the table is not empty, the first collision occured in time is solved and  
00058         If a collision is found, reaction() is called.
00059         
00060           
00061 ****************************************************************************/
00062 
00063 namespace NLPACS 
00064 {
00065 
00066 // ***************************************************************************
00067 
00068 CMoveContainer::~CMoveContainer ()
00069 {
00070         clear ();
00071 }
00072 
00073 // ***************************************************************************
00074 
00075 void CMoveContainer::clear ()
00076 {
00077         // Clear all primitives
00078         std::set<CMovePrimitive*>::iterator ite=_PrimitiveSet.begin();
00079         while (ite!=_PrimitiveSet.end ())
00080         {
00081                 freePrimitive (*ite);
00082                 ite++;
00083         }
00084 
00085         // Clear primitive set
00086         _PrimitiveSet.clear ();
00087 
00088         // Clear root changed
00089         _ChangedRoot.clear ();
00090 
00091         // Clear static world image set
00092         _StaticWorldImage.clear ();
00093 
00094         // Clear cell array
00095         _VectorCell.clear ();
00096 
00097         // Clear time ot
00098         _TimeOT.clear ();
00099 }
00100 
00101 // ***************************************************************************
00102 
00103 void CMoveContainer::init (double xmin, double ymin, double xmax, double ymax, uint widthCellCount, uint heightCellCount, 
00104                                                    double primitiveMaxSize, uint8 numWorldImage, uint maxIteration, uint otSize)
00105 {
00106         // Clear arrays
00107         clear ();
00108 
00109         // Create world images
00110         _ChangedRoot.resize (numWorldImage);
00111         for (uint i=0; i<numWorldImage; i++)
00112                 _ChangedRoot[i]=NULL;
00113 
00114         // Not in test mode
00115         _Retriever=NULL;
00116 
00117         // Element size
00118         _PrimitiveMaxSize=primitiveMaxSize;
00119 
00120         // BB
00121         _Xmin=xmin;
00122         _Ymin=ymin;
00123         _Xmax=xmax;
00124         _Ymax=ymax;
00125 
00126         // Cells count
00127         _CellCountWidth=widthCellCount;
00128         _CellCountHeight=heightCellCount;
00129 
00130         // Cells size
00131         _CellWidth=(_Xmax - _Xmin)/(double)_CellCountWidth;
00132         _CellHeight=(_Ymax - _Ymin)/(double)_CellCountHeight;
00133 
00134         // Cell array
00135         _VectorCell.resize (numWorldImage);
00136         for (uint j=0; j<numWorldImage; j++)
00137                 _VectorCell[j].resize (_CellCountWidth * _CellCountHeight);
00138 
00139         // resize OT
00140         _OtSize=otSize;
00141         _TimeOT.resize (otSize);
00142 
00143         // Clear the OT
00144         clearOT ();
00145 
00146         // Clear test time
00147         _TestTime=0xffffffff;
00148         _MaxTestIteration=maxIteration;
00149 
00150         // Resize trigger array
00151         _Triggers.resize (NELPACS_CONTAINER_TRIGGER_DEFAULT_SIZE);
00152 }
00153 
00154 // ***************************************************************************
00155 
00156 void CMoveContainer::init (CGlobalRetriever* retriever, uint widthCellCount, uint heightCellCount, double primitiveMaxSize, 
00157                 uint8 numWorldImage, uint maxIteration, uint otSize)
00158 {
00159         // Get min max of the global retriever BB
00160         CVector min=retriever->getBBox().getMin();
00161         CVector max=retriever->getBBox().getMax();
00162 
00163         // Setup min max
00164         double xmin=min.x;
00165         double ymin=min.y;
00166         double xmax=max.x;
00167         double ymax=max.y;
00168 
00169         // Init
00170         init (xmin, ymin, xmax, ymax, widthCellCount, heightCellCount, primitiveMaxSize, numWorldImage, maxIteration, otSize);
00171 
00172         // Init the retriever
00173         _Retriever=retriever;
00174 }
00175 
00176 // ***************************************************************************
00177 
00178 void  CMoveContainer::evalCollision (double deltaTime, uint8 worldImage)
00179 {
00180         NL_ALLOC_CONTEXT( Pacs )
00181         NLPACS_HAUTO_EVAL_COLLISION
00182 
00183 //      H_AUTO(PACS_MC_evalCollision);
00184 
00185         // New test time
00186         _TestTime++;
00187 
00188         // Delta time
00189         _DeltaTime=deltaTime;
00190 
00191         // Clear triggers
00192         _Triggers.clear ();
00193 
00194         // Update the bounding box and position of modified primitives
00195         updatePrimitives (0.f, worldImage);
00196 
00197 #ifdef NL_DEBUG
00198         // Check list integrity
00199         //checkSortedList ();
00200 #endif // NL_DEBUG
00201 
00202         // Get first collision
00203         _PreviousCollisionNode = &_TimeOT[0];
00204 
00205         // Eval all collisions
00206         evalAllCollisions (0.f, worldImage);
00207 
00208         // Clear modified list
00209         clearModifiedList (worldImage);
00210 
00211         // Modified list is empty at this point
00212         nlassert (_ChangedRoot[worldImage]==NULL);
00213 
00214         // Previous node is a 'hard' OT node
00215         nlassert (!_PreviousCollisionNode->isInfo());
00216 
00217         // Get next collision
00218         CCollisionOTInfo        *nextCollision;
00219         {
00220                 H_AUTO (NLPACS_Get_Next_Info);
00221                 nextCollision=_PreviousCollisionNode->getNextInfo ();
00222         }
00223 
00224         // Collision ?
00225         while (nextCollision)
00226         {
00227                 // Get new previous OT hard node
00228                 _PreviousCollisionNode=nextCollision->getPrevious ();
00229 
00230                 // Previous node is a 'hard' OT node
00231                 nlassert (!_PreviousCollisionNode->isInfo());
00232 
00233                 // Keep this collision
00234                 reaction (*nextCollision);
00235 
00236                 // Remove this collision from ot
00237                 if (!nextCollision->isCollisionAgainstStatic ())
00238                 {
00239                         // Remove the primitive from OT
00240                         nextCollision->unlink();
00241 
00242                         CCollisionOTDynamicInfo *info = static_cast<CCollisionOTDynamicInfo*>(nextCollision);
00243                         if (info->getFirstPrimitive())
00244                                 info->getFirstPrimitive()->removeCollisionOTInfo(info);
00245                         if (info->getSecondPrimitive())
00246                                 info->getSecondPrimitive()->removeCollisionOTInfo(info);
00247                 }
00248 
00249                 // Last time
00250                 double newTime=nextCollision->getCollisionTime ();
00251 
00252                 // Remove modified objects from the OT
00253                 removeModifiedFromOT (worldImage);
00254 
00255                 // Must have been removed
00256                 nlassert (nextCollision->getPrevious ()==NULL);
00257                 nlassert (nextCollision->CCollisionOT::getNext ()==NULL);
00258 
00259                 // Update the bounding box and position of modified primitives
00260                 updatePrimitives (newTime, worldImage);
00261 
00262                 // Eval all collisions of modified objects for the new delta t
00263                 evalAllCollisions (newTime, worldImage);
00264 
00265                 // Clear modified list
00266                 clearModifiedList (worldImage);
00267 
00268                 // Get next collision
00269                 nextCollision=_PreviousCollisionNode->getNextInfo ();
00270         }
00271 
00272 #ifdef NL_DEBUG
00273         // OT must be cleared
00274         checkOT ();
00275 #endif // NL_DEBUG
00276 
00277         // Free ordered table info
00278         freeAllOTInfo ();
00279 
00280         // Some init
00281         _PreviousCollisionNode=NULL;
00282 }
00283 
00284 // ***************************************************************************
00285 
00286 bool CMoveContainer::testMove (UMovePrimitive* primitive, const CVectorD& speed, double deltaTime, uint8 worldImage, CVectorD *contactNormal)
00287 {
00288         NL_ALLOC_CONTEXT( Pacs )
00289 
00290 //      H_AUTO(PACS_MC_testMove);
00291 
00292         if (contactNormal)
00293                 *contactNormal = CVectorD::Null;
00294 
00295         // Cast
00296         nlassert (dynamic_cast<CMovePrimitive*>(primitive));
00297         CMovePrimitive* prim=static_cast<CMovePrimitive*>(primitive);
00298 
00299         // New test time
00300         _TestTime++;
00301 
00302         // Delta time
00303         _DeltaTime=deltaTime;
00304 
00305         // Get the world image primitive
00306         uint8 primitiveWorldImage;
00307         CPrimitiveWorldImage *wI;
00308         if (prim->isNonCollisionable ())
00309         {
00310                 wI=prim->getWorldImage (0);
00311                 primitiveWorldImage=worldImage;
00312         }
00313         else
00314         {
00315                 wI=prim->getWorldImage (worldImage);
00316                 primitiveWorldImage=worldImage;
00317         }
00318 
00319         // Backup speed
00320         CVectorD oldSpeed=wI->getSpeed ();
00321 
00322         // Set speed
00323         wI->move (speed, *this, *prim, primitiveWorldImage);
00324 
00325         // Update the bounding box and position of the primitive
00326         wI->update (0, _DeltaTime, *prim);
00327 
00328         // Compute cells overlaped by the primitive
00329         if (!prim->isNonCollisionable ())
00330                 updateCells (prim, worldImage);
00331 
00332 #ifdef NL_DEBUG
00333         // Check list integrity
00334 //      checkSortedList ();
00335 #endif // NL_DEBUG
00336 
00337         // Result
00338         bool result=false;
00339         bool testMoveValid;
00340 
00341         // Eval first each static world images
00342         result=evalOneTerrainCollision (0, prim, primitiveWorldImage, true, testMoveValid, NULL, contactNormal);
00343 
00344         // Eval first each static world images
00345         if (!result)
00346         {
00347                 std::set<uint8>::iterator ite=_StaticWorldImage.begin();
00348                 while (ite!=_StaticWorldImage.end())
00349                 {
00350 
00351                         // Eval in this world image
00352                         result=evalOnePrimitiveCollision (0, prim, *ite, primitiveWorldImage, true, true, testMoveValid, NULL, contactNormal);
00353 
00354                         // If found, abort
00355                         if (result)
00356                                 break;
00357 
00358                         // Next world image
00359                         ite++;
00360                 }
00361         }
00362 
00363         // Eval collisions if not found and not tested
00364         if ((!result) && (_StaticWorldImage.find (worldImage)==_StaticWorldImage.end()))
00365                 result=evalOnePrimitiveCollision (0, prim, worldImage, primitiveWorldImage, true, false, testMoveValid, NULL, contactNormal);
00366 
00367         // Backup speed only if the primitive is inserted in the world image
00368         if (prim->isInserted (primitiveWorldImage))
00369                 wI->move (oldSpeed, *this, *prim, primitiveWorldImage);
00370 
00371 #ifdef NL_DEBUG
00372         // OT must be cleared
00373         checkOT ();
00374 #endif // NL_DEBUG
00375 
00376         // Free ordered table info
00377         freeAllOTInfo ();
00378 
00379         // Some init
00380         _PreviousCollisionNode=NULL;
00381 
00382         // Return result
00383         return !result;
00384 }
00385 
00386 // ***************************************************************************
00387 
00388 void CMoveContainer::updatePrimitives (double beginTime, uint8 worldImage)
00389 {
00390         H_AUTO (NLPACS_Update_Primitives);
00391 
00392         // For each changed primitives
00393         CMovePrimitive *changed=_ChangedRoot[worldImage];
00394         while (changed)
00395         {
00396                 // Get the primitive world image
00397                 CPrimitiveWorldImage *wI;
00398                 if (changed->isNonCollisionable())
00399                         wI=changed->getWorldImage (0);
00400                 else
00401                         wI=changed->getWorldImage (worldImage);
00402 
00403                 // Force the build of the bounding box
00404                 wI->update (beginTime, _DeltaTime, *changed);
00405 
00406                 // Is inserted in this world image ?
00407                 if (changed->isInserted (worldImage))
00408                 {
00409 
00410                         // Compute cells overlaped by the primitive
00411                         updateCells (changed, worldImage);
00412                 }
00413 
00414                 // Next primitive
00415                 changed=wI->getNextModified ();
00416         }
00417 }
00418 
00419 // ***************************************************************************
00420 
00421 void CMoveContainer::updateCells (CMovePrimitive *primitive, uint8 worldImage)
00422 {
00423 //      H_AUTO(PACS_MC_updateCells);
00424 
00425         // Get the primitive world image
00426         CPrimitiveWorldImage *wI=primitive->getWorldImage (worldImage);
00427 
00428         // Check BB width not too large
00429         if (wI->getBBXMax() - wI->getBBXMin() > _CellWidth)
00430         {
00431                 nlwarning ("Primitives have moved more than a cell.");
00432         }
00433 
00434         // Check BB height not too large
00435         if (wI->getBBYMax() - wI->getBBYMin() > _CellHeight)
00436         {
00437                 nlwarning ("Primitives have moved more than a cell.");
00438         }
00439 
00440         // Get coordinate in the cell array
00441         sint minx=(int)floor ((wI->getBBXMin() - _Xmin) / _CellWidth);
00442         sint miny=(int)floor ((wI->getBBYMin() - _Ymin) / _CellHeight);
00443         sint maxx=(int)floor ((wI->getBBXMax() - _Xmin) / _CellWidth);
00444         sint maxy=(int)floor ((wI->getBBYMax() - _Ymin) / _CellHeight);
00445 
00446         // Born
00447         if (minx<0)
00448                 minx=0;
00449         if (miny<0)
00450                 miny=0;
00451         if (maxx>=(int)_CellCountWidth)
00452                 maxx=(int)_CellCountWidth-1;
00453         if (maxy>=(int)_CellCountHeight)
00454                 maxy=(int)_CellCountHeight-1;
00455 
00456         maxx=std::min (minx+1, maxx);
00457         maxy=std::min (miny+1, maxy);
00458 
00459         // flags founded
00460         bool found[4]={false, false, false, false};
00461 
00462         // For each old cells
00463         uint i;
00464         for (i=0; i<4; i++)
00465         {
00466                 // Element
00467                 CMoveElement *elm = wI->getMoveElement (i);
00468 
00469                 // Old element in this cell ?
00470                 if ( elm )
00471                 {
00472                         // Check
00473                         nlassert (elm->X<_CellCountWidth);
00474                         nlassert (elm->Y<_CellCountHeight);
00475 
00476                         // Must remove it ?
00477                         if ( (elm->X < minx) || (elm->X > maxx) || (elm->Y < miny) || (elm->Y > maxy) )
00478                         {
00479                                 // Yes remove it
00480                                 wI->removeMoveElement (i, *this, worldImage);
00481                         }
00482                         else
00483                         {
00484                                 // Checks
00485                                 nlassert (((elm->X - minx)==0)||((elm->X - minx)==1));
00486                                 nlassert (((elm->Y - miny)==0)||((elm->Y - miny)==1));
00487 
00488                                 // Update position
00489 #ifndef TEST_CELL
00490                                 _VectorCell[worldImage][elm->X+elm->Y*_CellCountWidth].updateSortedLists (elm, worldImage);
00491 #endif
00492 
00493                                 // Check found cells
00494                                 found[ elm->X - minx + ((elm->Y - miny) << (maxx-minx)) ]=true;
00495                         }
00496                 }
00497         }
00498 
00499         // For each case selected
00500         int x, y;
00501         i=0;
00502         for (y=miny; y<=(int)maxy; y++)
00503         for (x=minx; x<=(int)maxx; x++)
00504         {
00505                 // Check the formula
00506                 nlassert ((int)i == (x - minx + ((y - miny) << (maxx-minx)) ));
00507 
00508                 // If the cell is not found
00509                 if (!found[i])
00510                 {
00511                         // Center of the cell
00512                         double cx=((double)x+0.5f)*_CellWidth+_Xmin;
00513                         double cy=((double)y+0.5f)*_CellHeight+_Ymin;
00514 
00515                         // Add it in the list
00516                         wI->addMoveElement (_VectorCell[worldImage][x+y*_CellCountWidth], (uint16)x, (uint16)y, cx, cy, primitive, *this, worldImage);
00517                 }
00518 
00519                 // Next cell
00520                 i++;
00521         }
00522 }
00523 
00524 // ***************************************************************************
00525 
00526 void CMoveContainer::getCells (CMovePrimitive *primitive, uint8 worldImage, uint8 primitiveWorldImage, CMoveElement **elementArray)
00527 {
00528 //      H_AUTO(PACS_MC_getCells);
00529 
00530         // Get the primitive world image
00531         CPrimitiveWorldImage *wI;
00532         if (primitive->isNonCollisionable())
00533                 wI=primitive->getWorldImage (0);        
00534         else
00535                 wI=primitive->getWorldImage (primitiveWorldImage);
00536 
00537         // Check BB width not too large
00538         if (wI->getBBXMax() - wI->getBBXMin() > _CellWidth)
00539         {
00540                 nlwarning ("Primitives have moved more than a cell.");
00541         }
00542 
00543         // Check BB height not too large
00544         if (wI->getBBYMax() - wI->getBBYMin() > _CellHeight)
00545         {
00546                 nlwarning ("Primitives have moved more than a cell.");
00547         }
00548 
00549         // Get coordinate in the cell array
00550         int minx=(int)floor ((wI->getBBXMin() - _Xmin) / _CellWidth);
00551         int miny=(int)floor ((wI->getBBYMin() - _Ymin) / _CellHeight);
00552         int maxx=(int)floor ((wI->getBBXMax() - _Xmin) / _CellWidth);
00553         int maxy=(int)floor ((wI->getBBYMax() - _Ymin) / _CellHeight);
00554 
00555         // Born
00556         if (minx<0)
00557                 minx=0;
00558         if (miny<0)
00559                 miny=0;
00560         if (maxx>=(int)_CellCountWidth)
00561                 maxx=(int)_CellCountWidth-1;
00562         if (maxy>=(int)_CellCountHeight)
00563                 maxy=(int)_CellCountHeight-1;
00564 
00565         maxx=std::min (minx+1, maxx);
00566         maxy=std::min (miny+1, maxy);
00567 
00568         // For each case selected
00569         int x, y;
00570         int i=0;
00571         for (y=miny; y<=(int)maxy; y++)
00572         for (x=minx; x<=(int)maxx; x++)
00573         {
00574                 // Check the formula
00575                 nlassert ((int)i == (x - minx + ((y - miny) << (maxx-minx)) ));
00576 
00577                 // Center of the cell
00578                 double cx=((double)x+0.5f)*_CellWidth+_Xmin;
00579 
00580                 // Primitive center
00581                 double pcx=(wI->getBBXMin()+wI->getBBXMax())/2.f;
00582 
00583                 elementArray[i]->Primitive=primitive;
00584                 elementArray[i]->X=x;
00585                 elementArray[i]->Y=y;
00586                 // Insert in left or right ?
00587                 if (pcx<cx)
00588                 {
00589                         // In the left
00590                         elementArray[i]->NextX=_VectorCell[worldImage][x+y*_CellCountWidth].getFirstX ();
00591                         elementArray[i]->PreviousX=NULL;
00592                 }
00593                 else
00594                 {
00595                         // In the right
00596                         elementArray[i]->PreviousX=_VectorCell[worldImage][x+y*_CellCountWidth].getLastX ();
00597                         elementArray[i]->NextX=NULL;
00598                 }
00599 
00600                 // Next cell
00601                 i++;
00602         }
00603 
00604         // Erase last array element
00605         for (; i<4; i++)
00606         {
00607                 elementArray[i]=NULL;
00608         }
00609 }
00610 
00611 // ***************************************************************************
00612 
00613 void CMoveContainer::clearModifiedList (uint8 worldImage)
00614 {
00615         H_AUTO (NLPACS_Clear_Modified_List);
00616         
00617         // For each changed primitives
00618         CMovePrimitive *changed=_ChangedRoot[worldImage];
00619         while (changed)
00620         {
00621                 // Get the world image primitive
00622                 CPrimitiveWorldImage *wI;
00623                 if (changed->isNonCollisionable())
00624                         wI=changed->getWorldImage (0);
00625                 else
00626                         wI=changed->getWorldImage (worldImage);
00627                 
00628                 // Next primitive
00629                 changed=wI->getNextModified ();
00630 
00631                 // Remove it from the list
00632                 wI->setInModifiedListFlag (false);
00633         }
00634 
00635         // Empty list
00636         _ChangedRoot[worldImage]=NULL;
00637 }
00638 
00639 // ***************************************************************************
00640 
00641 void CMoveContainer::checkSortedList ()
00642 {
00643         // Check each primitives in the set
00644         std::set<CMovePrimitive*>::iterator ite=_PrimitiveSet.begin();
00645         while (ite!=_PrimitiveSet.end())
00646         {
00647                 // Check
00648                 (*ite)->checkSortedList ();
00649 
00650                 ite++;
00651         }
00652 }
00653 
00654 // ***************************************************************************
00655 
00656 bool CMoveContainer::evalOneTerrainCollision (double beginTime, CMovePrimitive *primitive, uint8 primitiveWorldImage, 
00657                                                                            bool testMove, bool &testMoveValid, CCollisionOTStaticInfo *staticColInfo, CVectorD *contactNormal)
00658 {
00659 //      H_AUTO(PACS_MC_evalOneCollision);
00660         H_AUTO(NLPACS_Eval_One_Terrain_Collision);
00661         
00662         // Find its collisions
00663         bool found=false;
00664 
00665         // Get the primitive world image
00666         CPrimitiveWorldImage *wI;
00667         if (primitive->isNonCollisionable())
00668                 wI=primitive->getWorldImage (0);
00669         else
00670                 wI=primitive->getWorldImage (primitiveWorldImage);
00671 
00672         // Begin time must be the same as beginTime
00673         //nlassert (wI->getInitTime()==beginTime);
00674         if (wI->getInitTime() != beginTime)
00675         {
00676                 nlwarning("PACS: evalOneTerrainCollision() failure, wI->getInitTime() [%f] != beginTime [%f]", wI->getInitTime(), beginTime);
00677                 return false;
00678         }
00679 
00680         // Test its static collision
00681         if (_Retriever)
00682         {
00683                 // Delta pos..
00684                 // Test retriever with the primitive
00685                 const TCollisionSurfaceDescVector *result=wI->evalCollision (*_Retriever, _SurfaceTemp, _TestTime, _MaxTestIteration, *primitive);
00686                 if (result)
00687                 {
00688                         // TEST MOVE MUST BE OK !!
00689                         testMoveValid=true;
00690 
00691                         // Size of the array
00692                         uint size=result->size();
00693 
00694                         // For each detected collisions
00695                         for (uint c=0; c<size; c++)
00696                         {
00697                                 // Ref on the collision
00698                                 CCollisionSurfaceDesc desc=(*result)[c];
00699                                 double contactTime = (_DeltaTime-beginTime)*desc.ContactTime+beginTime;
00700 
00701                                 /*
00702                                  *  If beginTime is 0.999999999 and desc.ContactTime<1.0, contactTime will be 1.0.
00703                                  *  In this case, we force contactTime to be beginTime to avoid collision at time == 1.0.
00704                                 **/
00705                                 if ((contactTime >= 1.0) && (beginTime < 1.0) && (desc.ContactTime < 1.0))
00706                                         contactTime = beginTime;
00707 
00708                                 // Set the container's time space contact time
00709                                 desc.ContactTime = contactTime;
00710 
00711                                 // ptr on the surface
00712                                 const CRetrievableSurface *surf= _Retriever->getSurfaceById (desc.ContactSurface);
00713 
00714                                 // TODO: check surface flags  against primitive flags HERE:
00715                                 // Is a wall ?
00716                                 bool isWall;
00717                                 if(!surf)
00718                                         isWall= true;
00719                                 else
00720                                         isWall= !(surf->isFloor() || surf->isCeiling());
00721 
00722                                 // stop on a wall.
00723                                 if(isWall)
00724                                 {
00725                                         // Test move ?
00726                                         if (testMove)
00727                                         {
00728                                                 // return contact normal only when testmove and vector provided
00729                                                 if (contactNormal)
00730                                                         *contactNormal = desc.ContactNormal;
00731                                                 return true;
00732                                         }
00733                                         else
00734                                         {
00735                                                 // OK, collision if we are a collisionable primitive
00736                                                 newCollision (primitive, desc, primitiveWorldImage, beginTime, staticColInfo);
00737 
00738                                                 // One collision found
00739                                                 found=true;
00740                                                 break;
00741                                         }
00742                                 }
00743                         }
00744                 }
00745                 else
00746                         // More than maxtest made, exit
00747                         return false;
00748         }
00749         return found;
00750 }
00751 
00752 // ***************************************************************************
00753 
00754 bool CMoveContainer::evalOnePrimitiveCollision (double beginTime, CMovePrimitive *primitive, uint8 worldImage, uint8 primitiveWorldImage, 
00755                                                                            bool testMove, bool secondIsStatic, bool &testMoveValid, CCollisionOTDynamicInfo *dynamicColInfo,
00756                                                                                 CVectorD *contactNormal)
00757 {
00758 //      H_AUTO(PACS_MC_evalOneCollision);
00759         H_AUTO(NLPACS_Eval_One_Primitive_Collision);
00760 
00761         // Find its collisions
00762         bool found=false;
00763 
00764         // Get the primitive world image
00765         CPrimitiveWorldImage *wI;
00766         if (primitive->isNonCollisionable())
00767                 wI=primitive->getWorldImage (0);
00768         else
00769                 wI=primitive->getWorldImage (primitiveWorldImage);
00770 
00771         // Begin time must be the same as beginTime
00772         //nlassert (wI->getInitTime()==beginTime);
00773         if (wI->getInitTime() != beginTime)
00774         {
00775                 nlwarning("PACS: evalOnePrimitiveCollision() failure, wI->getInitTime() [%f] != beginTime [%f]", wI->getInitTime(), beginTime);
00776                 return false;
00777         }
00778 
00779         // Element table
00780         CMoveElement    tableNotInserted[4];
00781         CMoveElement    *table[4];
00782 
00783         // Single test ?
00784         bool singleTest=testMove;
00785         
00786         // Is in world image
00787         if ((worldImage==primitiveWorldImage) && wI->isInWorldImageFlag())
00788         {
00789                 // Get move element table from the primitive
00790                 table[0]=wI->getMoveElement (0);
00791                 table[1]=wI->getMoveElement (1);
00792                 table[2]=wI->getMoveElement (2);
00793                 table[3]=wI->getMoveElement (3);
00794         }
00795         else
00796         {
00797                 // Set table pointers
00798                 table[0]=tableNotInserted+0;
00799                 table[1]=tableNotInserted+1;
00800                 table[2]=tableNotInserted+2;
00801                 table[3]=tableNotInserted+3;
00802 
00803                 // Get cells
00804                 getCells (primitive, worldImage, primitiveWorldImage, table);
00805 
00806                 // Force the test
00807                 singleTest=true;
00808         }
00809 
00810         // For each move element
00811         for (uint i=0; i<4; i++)
00812         {
00813                 // Get the element
00814                 CMoveElement    *elm=table[i];
00815 
00816                 // Element valid ?
00817                 if (elm)
00818                 {
00819                         // Check
00820                         nlassert (elm->Primitive==primitive);
00821                         // Primitive to the left
00822 
00823                         // Lookup in X sorted list on the left
00824                         CMoveElement    *other=elm->PreviousX;
00825                         nlassert (other!=elm);
00826 
00827                         while (other && (wI->getBBXMin() - other->Primitive->getWorldImage(worldImage)->getBBXMin() < _PrimitiveMaxSize) )
00828                         {
00829                                 // Other primitive
00830                                 CMovePrimitive  *otherPrimitive=other->Primitive;
00831                                 CPrimitiveWorldImage *otherWI=otherPrimitive->getWorldImage (worldImage);
00832                                 nlassert (otherPrimitive!=primitive);
00833 
00834                                 // Continue the check if the other primitive is not int the modified list or if its pointer is higher than primitive
00835                                 if ( singleTest || ( (!otherWI->isInModifiedListFlag ()) || (primitive<otherPrimitive) ) )
00836                                 {
00837                                         // Look if valid in X
00838                                         if (wI->getBBXMin() < otherWI->getBBXMax())
00839                                         {
00840                                                 // Look if valid in Y
00841                                                 if ( (wI->getBBYMin() < otherWI->getBBYMax()) && (otherWI->getBBYMin() < wI->getBBYMax()) )
00842                                                 {
00843                                                         // If not already in collision with this primitive
00844                                                         if (!primitive->isInCollision (otherPrimitive))
00845                                                         {
00846                                                                 if (evalPrimAgainstPrimCollision (beginTime, primitive, otherPrimitive, wI, otherWI, testMove,
00847                                                                         primitiveWorldImage, worldImage, secondIsStatic, dynamicColInfo, contactNormal))
00848                                                                 {
00849                                                                         if (testMove)
00850                                                                                 return true;
00851                                                                         found=true;
00852                                                                 }
00853                                                         }
00854                                                 }
00855                                         }
00856                                 }
00857 
00858                                 // Next primitive to the left
00859                                 other = other->PreviousX;
00860                         }
00861 
00862                         // Lookup in X sorted list on the right
00863                         other=elm->NextX;
00864 
00865                         // Primitive to the right
00866                         while (other && (other->Primitive->getWorldImage(worldImage)->getBBXMin() < wI->getBBXMax()) )
00867                         {
00868                                 // Other primitive
00869                                 CMovePrimitive  *otherPrimitive=other->Primitive;
00870                                 CPrimitiveWorldImage *otherWI=otherPrimitive->getWorldImage (worldImage);
00871                                 nlassert (otherPrimitive!=primitive);
00872 
00873                                 // Continue the check if the other primitive is not in the modified list or if its pointer is higher than primitive
00874                                 if ( singleTest || ( (!otherWI->isInModifiedListFlag ()) || (primitive<otherPrimitive) ) )
00875                                 {
00876                                         // Look if valid in Y
00877                                         if ( (wI->getBBYMin() < otherWI->getBBYMax()) && (otherWI->getBBYMin() < wI->getBBYMax()) )
00878                                         {
00879                                                 // If not already in collision with this primitive
00880                                                 if (!primitive->isInCollision (otherPrimitive))
00881                                                 {
00882                                                         if (evalPrimAgainstPrimCollision (beginTime, primitive, otherPrimitive, wI, otherWI, testMove,
00883                                                         primitiveWorldImage, worldImage, secondIsStatic, dynamicColInfo, contactNormal))
00884                                                         {
00885                                                                 if (testMove)
00886                                                                         return true;
00887                                                                 found=true;
00888                                                         }
00889                                                 }
00890                                         }
00891                                 }
00892 
00893                                 // Next primitive to the left
00894                                 other = other->NextX;
00895                         }
00896                 }
00897         }
00898 
00899         return found;
00900 }
00901 
00902 // ***************************************************************************
00903 
00904 bool CMoveContainer::evalPrimAgainstPrimCollision (double beginTime, CMovePrimitive *primitive, CMovePrimitive *otherPrimitive, 
00905                                                                                         CPrimitiveWorldImage *wI, CPrimitiveWorldImage *otherWI, bool testMove,
00906                                                                                         uint8 firstWorldImage, uint8 secondWorldImage, bool secondIsStatic, CCollisionOTDynamicInfo *dynamicColInfo,
00907                                                                                         CVectorD *contactNormal)
00908 {
00909 //      H_AUTO(PACS_MC_evalPrimAgainstPrimCollision);
00910 
00911         // Test the primitive
00912         double firstTime, lastTime;
00913 
00914         // Collision
00915         CCollisionDesc desc;
00916         if (wI->evalCollision (*otherWI, desc, beginTime, _DeltaTime, _TestTime, _MaxTestIteration, 
00917                                                                 firstTime, lastTime, *primitive, *otherPrimitive))
00918         {
00919                 // Enter or exit
00920                 bool enter = (beginTime<=firstTime) && (firstTime<_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::EnterTrigger) 
00921                         || (otherPrimitive->getTriggerType()&UMovePrimitive::EnterTrigger));
00922                 bool exit = (beginTime<=lastTime) && (lastTime<_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::ExitTrigger) 
00923                         || (otherPrimitive->getTriggerType()&UMovePrimitive::ExitTrigger));
00924                 bool overlap = (firstTime<=beginTime) && (lastTime>_DeltaTime) && ((primitive->getTriggerType()&UMovePrimitive::OverlapTrigger) 
00925                         || (otherPrimitive->getTriggerType()&UMovePrimitive::OverlapTrigger));
00926                 bool contact = ( beginTime<((firstTime+lastTime)/2) ) && (firstTime<=_DeltaTime);
00927                 bool collision = contact && (primitive->isObstacle() && otherPrimitive->isObstacle ());
00928                 
00929                 // Return collision time
00930 
00931                 if (testMove)
00932                         return contact;
00933 
00942                 if (primitive->isNonCollisionable () && (enter || exit || overlap))
00943                 {
00944                         if (primitive->isTriggered (*otherPrimitive, enter, exit))
00945                         {
00946                                 // Add a trigger
00947                                 if (enter)
00948                                         newTrigger (primitive, otherPrimitive, desc, UTriggerInfo::In);
00949                                 if (exit)
00950                                         newTrigger (primitive, otherPrimitive, desc, UTriggerInfo::Out);
00951                                 if (overlap)
00952                                         newTrigger (primitive, otherPrimitive, desc, UTriggerInfo::Inside);
00953                         }
00954 
00955                         // If the other primitive is not an obstacle, skip it because it will re-generate collisions.
00956                         if (!collision)
00957                                 return false;
00958                 }
00959 
00960                 // OK, collision
00961                 if (contact || enter || exit || overlap)
00962                         newCollision (primitive, otherPrimitive, desc, contact, enter, exit, overlap, firstWorldImage, secondWorldImage, secondIsStatic,
00963                                                         dynamicColInfo);
00964 
00965                 // Collision
00966                 return collision;
00967         }
00968         return false;
00969 }
00970 
00971 // ***************************************************************************
00972 
00973 void CMoveContainer::evalAllCollisions (double beginTime, uint8 worldImage)
00974 {
00975         H_AUTO(NLPACS_Eval_All_Collisions);
00976 
00977         // First primitive
00978         CMovePrimitive  *primitive=_ChangedRoot[worldImage];
00979 
00980         // For each modified primitive
00981         while (primitive)
00982         {
00983                 // Get the primitive world image
00984                 uint8 primitiveWorldImage;
00985                 CPrimitiveWorldImage *wI;
00986                 if (primitive->isNonCollisionable ())
00987                 {
00988                         wI=primitive->getWorldImage (0);
00989                         primitiveWorldImage=worldImage;
00990                 }
00991                 else
00992                 {
00993                         wI=primitive->getWorldImage (worldImage);
00994                         primitiveWorldImage=worldImage;
00995                 }
00996 
00997                 CVectorD d0=wI->getDeltaPosition();
00998 
00999                 // Find a collision
01000                 bool found=false;
01001                 bool testMoveValid=false;
01002 
01003                 // Eval collision on the terrain
01004                 found|=evalOneTerrainCollision (beginTime, primitive, primitiveWorldImage, false, testMoveValid, NULL, NULL);
01005 
01006                 // If the primitive can collid other primitive..
01007                 if (primitive->getCollisionMask())
01008                 {
01009                         // Eval collision in each static world image
01010                         std::set<uint8>::iterator ite=_StaticWorldImage.begin();
01011                         while (ite!=_StaticWorldImage.end())
01012                         {
01013                                 // Eval in this world image
01014                                 found|=evalOnePrimitiveCollision (beginTime, primitive, *ite, primitiveWorldImage, false, true, testMoveValid, NULL, NULL);
01015 
01016                                 // Next world image
01017                                 ite++;
01018                         }
01019                 }
01020 
01021                 CVectorD d1=wI->getDeltaPosition();
01022 
01023                 // If the primitive can collid other primitive..
01024                 if (primitive->getCollisionMask())
01025                 {
01026                         // Eval collision in the world image if not already tested
01027                         if (_StaticWorldImage.find (worldImage)==_StaticWorldImage.end())
01028                                 found|=evalOnePrimitiveCollision (beginTime, primitive, worldImage, primitiveWorldImage, false, false, testMoveValid, NULL, NULL);
01029                 }
01030 
01031                 CVectorD d2=wI->getDeltaPosition();
01032 
01033                 // No collision ?
01034                 if (!found)
01035                 {
01036                         //nlassert ((d0==d1)&&(d0==d2));
01037                         //nlassert (f1==f2);
01038 
01039                         if (_Retriever&&testMoveValid)
01040                         {                                                               
01041                                 // Do move
01042                                 wI->doMove (*_Retriever, _SurfaceTemp, _DeltaTime, _DeltaTime, primitive->getDontSnapToGround());                               
01043                         }
01044                         else
01045                         {
01046                                 // Do move
01047                                 wI->doMove (_DeltaTime);
01048                         }
01049                 }
01050 
01051                 // Next primitive
01052                 primitive=wI->getNextModified ();
01053         }
01054 }
01055 
01056 // ***************************************************************************
01057 
01058 void CMoveContainer::newCollision (CMovePrimitive* first, CMovePrimitive* second, const CCollisionDesc& desc, bool collision, bool enter, bool exit, bool inside,
01059                                                                    uint firstWorldImage, uint secondWorldImage, bool secondIsStatic, CCollisionOTDynamicInfo *dynamicColInfo)
01060 {
01061 //      H_AUTO(PACS_MC_newCollision_short);
01062 
01063         nlassert ((dynamicColInfo && first->isNonCollisionable ()) || (!dynamicColInfo && first->isCollisionable ()));
01064 
01065         if (dynamicColInfo)
01066         {
01067                 dynamicColInfo->init (first, second, desc, collision, enter, exit, inside, firstWorldImage, secondWorldImage, secondIsStatic);
01068         }
01069         else
01070         {
01071                 // Get an ordered time index. Always round to the future.
01072                 int index=(int)(ceil (desc.ContactTime*(double)_OtSize/_DeltaTime) );
01073 
01074                 // Clamp left.
01075                 if (index<0)
01076                         index=0;
01077 
01078                 // If in time
01079                 if (index<(int)_OtSize)
01080                 {
01081                         // Build info
01082                         CCollisionOTDynamicInfo *info = allocateOTDynamicInfo ();
01083                         info->init (first, second, desc, collision, enter, exit, inside, firstWorldImage, secondWorldImage, secondIsStatic);
01084 
01085                         // Add in the primitive list
01086                         first->addCollisionOTInfo (info);
01087                         second->addCollisionOTInfo (info);
01088 
01089                         // Insert in the time ordered table
01090                         //nlassert (index<(int)_TimeOT.size());
01091                         if (index >= (int)_TimeOT.size())
01092                         {
01093                                 nlwarning("PACS: newCollision() failure, index [%d] >= (int)_TimeOT.size() [%d], clamped to max", index, (int)_TimeOT.size());
01094                                 index = _TimeOT.size()-1;
01095                         }
01096                         _TimeOT[index].link (info);
01097 
01098                         // Check it is after the last hard collision
01099                         nlassert (_PreviousCollisionNode<=&_TimeOT[index]);
01100                 }
01101         }
01102 }
01103 
01104 // ***************************************************************************
01105 
01106 void CMoveContainer::newCollision (CMovePrimitive* first, const CCollisionSurfaceDesc& desc, uint8 worldImage, double beginTime, CCollisionOTStaticInfo *staticColInfo)
01107 {
01108 //      H_AUTO(PACS_MC_newCollision_long);
01109 
01110         // Check
01111         nlassert (_Retriever);
01112         nlassert ((staticColInfo && first->isNonCollisionable ()) || (!staticColInfo && first->isCollisionable ()));
01113 
01114         // Get the world image
01115         CPrimitiveWorldImage *wI;
01116         if (first->isNonCollisionable())
01117                 wI=first->getWorldImage (0);
01118         else
01119                 wI=first->getWorldImage (worldImage);
01120 
01121         // Time
01122         double time=desc.ContactTime;
01123 /*
01124         if (time == _DeltaTime)
01125                 time -= _DeltaTime*FLT_EPSILON;
01126 */
01127 
01128         // Check time interval
01129 
01130         //nlassertex (beginTime<=time, ("beginTime=%f, time=%f", beginTime, time));
01131         //nlassertex (time<_DeltaTime, ("time=%f, _DeltaTime=%f", time, _DeltaTime));
01132 
01133         if (beginTime > time)
01134         {
01135                 nlwarning("PACS: beginTime=%f > time=%f", beginTime, time);
01136         }
01137 
01138         if (time >= _DeltaTime)
01139         {
01140                 nlwarning("PACS: time=%f >= _DeltaTime=%f", time, _DeltaTime);
01141         }
01142 
01143 
01144         // Time of the collision.
01145         time-=NELPACS_DIST_BACK/wI->getSpeed().norm();
01146         time=std::max(time, beginTime);
01147         double ratio=(time-beginTime)/(_DeltaTime-beginTime);
01148 
01149 /*
01150         nlassert (ratio>=0);
01151         nlassert (ratio<=1);
01152 */
01153 
01154         if (ratio < 0.0)
01155         {
01156                 nlwarning("PACS: ratio=%f < 0.0", ratio);
01157                 ratio = 0.0;
01158         }
01159 
01160         if (ratio > 1.0)
01161         {
01162                 nlwarning("PACS: ratio=%f > 1.0", ratio);
01163                 ratio = 1.0;
01164         }
01165 
01166         if (staticColInfo)
01167         {
01168                 // Make a new globalposition
01169                 UGlobalPosition endPosition=_Retriever->doMove (wI->getGlobalPosition(), wI->getDeltaPosition(), 
01170                         (float)ratio, _SurfaceTemp, false);
01171 
01172                 // Init the info descriptor
01173                 staticColInfo->init (first, desc, endPosition, ratio, worldImage);
01174         }
01175         else
01176         {
01177                 // Get an ordered time index. Always round to the future.
01178                 int index=(int)(ceil (time*(double)_OtSize/_DeltaTime) );
01179 
01180                 // Clamp left.
01181                 if (index<0)
01182                         index=0;
01183 
01184                 // If in time
01185                 if (index<(int)_OtSize)
01186                 {
01187                         // Build info
01188                         CCollisionOTStaticInfo *info = allocateOTStaticInfo ();
01189 
01190                         // Make a new globalposition
01191                         UGlobalPosition endPosition=_Retriever->doMove (wI->getGlobalPosition(), wI->getDeltaPosition(), 
01192                                 (float)ratio, _SurfaceTemp, false);
01193 
01194                         // Init the info descriptor
01195                         info->init (first, desc, endPosition, ratio, worldImage);
01196 
01197                         // Add in the primitive list
01198                         first->addCollisionOTInfo (info);
01199 
01200                         // Insert in the time ordered table
01201                         //nlassert (index<(int)_TimeOT.size());
01202                         if (index >= (int)_TimeOT.size())
01203                         {
01204                                 nlwarning("PACS: newCollision() failure, index [%d] >= (int)_TimeOT.size() [%d], clamped to max", index, (int)_TimeOT.size());
01205                                 index = _TimeOT.size()-1;
01206                         }
01207                         _TimeOT[index].link (info);
01208 
01209                         // Check it is after the last hard collision
01210                         nlassert (_PreviousCollisionNode<=&_TimeOT[index]);
01211                 }
01212         }
01213 }
01214 
01215 // ***************************************************************************
01216 
01217 void CMoveContainer::newTrigger (CMovePrimitive* first, CMovePrimitive* second, const CCollisionDesc& desc, uint triggerType)
01218 {
01219         // Element index
01220         uint index=_Triggers.size();
01221 
01222         // Add one element
01223         _Triggers.resize (index+1);
01224 
01225         // Fill info
01226         _Triggers[index].Object0=first->UserData;
01227         _Triggers[index].Object1=second->UserData;
01228         _Triggers[index].CollisionDesc=desc;
01229         _Triggers[index].CollisionType = triggerType;
01230 }
01231 
01232 // ***************************************************************************
01233 
01234 void CMoveContainer::checkOT ()
01235 {
01236         // Check
01237         nlassert (_OtSize==_TimeOT.size());
01238 
01239         // Check linked list
01240         for (uint i=0; i<_OtSize-1; i++)
01241         {
01242                 // Check link
01243                 nlassert ( _TimeOT[i].getNext() == (&(_TimeOT[i+1])) );
01244                 nlassert ( _TimeOT[i+1].getPrevious() == (&(_TimeOT[i])) );
01245         }
01246 
01247         // Check first and last
01248         nlassert ( _TimeOT[0].getPrevious() == NULL );
01249         nlassert ( _TimeOT[_OtSize-1].getNext() == NULL );
01250 }
01251 
01252 // ***************************************************************************
01253 
01254 void CMoveContainer::clearOT ()
01255 {
01256         // Check
01257         nlassert (_OtSize==_TimeOT.size());
01258 
01259         // clear the list
01260         uint i;
01261         for (i=0; i<_OtSize; i++)
01262                 _TimeOT[i].clear ();
01263 
01264         // Relink the list
01265         for (i=0; i<_OtSize-1; i++)
01266                 // Link the two cells
01267                 _TimeOT[i].link (&(_TimeOT[i+1]));
01268 }
01269 
01270 // ***************************************************************************
01271 
01272 void CMoveContainer::removeModifiedFromOT (uint8 worldImage)
01273 {
01274         // For each changed primitives
01275         CMovePrimitive *changed=_ChangedRoot[worldImage];
01276         while (changed)
01277         {
01278                 // Remove from ot list
01279                 changed->removeCollisionOTInfo ();
01280 
01281                 // Get the primitive world image
01282                 CPrimitiveWorldImage *wI;
01283                 if (changed->isNonCollisionable())
01284                         wI=changed->getWorldImage (0);
01285                 else
01286                         wI=changed->getWorldImage (worldImage);
01287                 
01288                 // Next primitive
01289                 changed=wI->getNextModified ();
01290         }
01291 }
01292 
01293 // ***************************************************************************
01294 
01295 CCollisionOTDynamicInfo *CMoveContainer::allocateOTDynamicInfo ()
01296 {
01297         return _AllocOTDynamicInfo.allocate ();
01298 }
01299 
01300 // ***************************************************************************
01301 
01302 CCollisionOTStaticInfo *CMoveContainer::allocateOTStaticInfo ()
01303 {
01304         return _AllocOTStaticInfo.allocate ();
01305 }
01306 
01307 // ***************************************************************************
01308 
01309 // Free all ordered table info
01310 void CMoveContainer::freeAllOTInfo ()
01311 {
01312         H_AUTO (NLPACS_Free_All_OT_Info);
01313         
01314         _AllocOTDynamicInfo.free ();
01315         _AllocOTStaticInfo.free ();
01316 }
01317 
01318 // ***************************************************************************
01319 
01320 CMovePrimitive *CMoveContainer::allocatePrimitive (uint8 firstWorldImage, uint8 numWorldImage)
01321 {
01322         // Simply allocate
01323         return new CMovePrimitive (this, firstWorldImage, numWorldImage);
01324 }
01325 
01326 // ***************************************************************************
01327 
01328 void CMoveContainer::freePrimitive (CMovePrimitive *primitive)
01329 {
01330         // Simply deallocate
01331         delete primitive;
01332 }
01333 
01334 // ***************************************************************************
01335 
01336 CPrimitiveWorldImage    **CMoveContainer::allocateWorldImagesPtrs (uint numPtrs)
01337 {
01338         return new CPrimitiveWorldImage*[numPtrs];
01339 }
01340 
01341 // ***************************************************************************
01342 
01343 void CMoveContainer::freeWorldImagesPtrs (CPrimitiveWorldImage **ptrs)
01344 {
01345                 delete [] ptrs;
01346 }
01347 
01348 // ***************************************************************************
01349 
01350 CPrimitiveWorldImage    *CMoveContainer::allocateWorldImage ()
01351 {
01352         return new CPrimitiveWorldImage;
01353 }
01354 
01355 // ***************************************************************************
01356 
01357 void CMoveContainer::freeWorldImage (CPrimitiveWorldImage *worldImage)
01358 {
01359         delete worldImage;
01360 }
01361 
01362 // ***************************************************************************
01363 
01364 CMoveElement *CMoveContainer::allocateMoveElement ()
01365 {
01366         // Simply allocate
01367         return new CMoveElement;
01368 }
01369 
01370 // ***************************************************************************
01371 
01372 void CMoveContainer::freeMoveElement (CMoveElement *element)
01373 {
01374         // Simply deallocate
01375         delete element;
01376 }
01377 
01378 // ***************************************************************************
01379 
01380 void    UMoveContainer::deleteMoveContainer (UMoveContainer     *container)
01381 {
01382         delete (CMoveContainer*)container;
01383 }
01384 
01385 // ***************************************************************************
01386 
01387 UMovePrimitive *CMoveContainer::addCollisionablePrimitive (uint8 firstWorldImage, uint8 numWorldImage, const UMovePrimitive *copyFrom)
01388 {
01389         NL_ALLOC_CONTEXT( Pacs )
01390 
01391         // Allocate primitive
01392         CMovePrimitive *primitive=allocatePrimitive (firstWorldImage, numWorldImage);
01393 
01394         // Add into the set
01395         _PrimitiveSet.insert (primitive);
01396 
01397         // if copy from primitive is not null, copy attributes
01398         if (copyFrom != NULL)
01399         {
01400                 primitive->setPrimitiveType(copyFrom->getPrimitiveType());
01401                 primitive->setReactionType(copyFrom->getReactionType());
01402                 primitive->setTriggerType(copyFrom->getTriggerType());
01403                 primitive->setCollisionMask(copyFrom->getCollisionMask());
01404                 primitive->setOcclusionMask(copyFrom->getOcclusionMask());
01405                 primitive->setObstacle(copyFrom->getObstacle());
01406                 primitive->setAbsorbtion(copyFrom->getAbsorbtion());
01407                 primitive->setHeight(copyFrom->getHeight());
01408                 if (primitive->getPrimitiveType() == UMovePrimitive::_2DOrientedBox)
01409                 {
01410                         float   width=0.0f, height=0.0f;
01411                         copyFrom->getSize(width, height);
01412                         primitive->setSize(width, height);
01413                 }
01414                 else
01415                 {
01416                         primitive->setRadius(copyFrom->getRadius());
01417                 }
01418         }
01419 
01420         // Return it
01421         return primitive;
01422 }
01423 
01424 // ***************************************************************************
01425 
01426 UMovePrimitive *CMoveContainer::addNonCollisionablePrimitive (const UMovePrimitive *copyFrom)
01427 {
01428         NL_ALLOC_CONTEXT( Pacs )
01429 
01430         // Allocate primitive
01431         CMovePrimitive *primitive=allocatePrimitive (0, 1);
01432         
01433         // Set as noncollisionable
01434         primitive->setNonCollisionable (true);
01435         
01436         // Add into the set
01437         _PrimitiveSet.insert (primitive);
01438 
01439         // if copy from primitive is not null, copy attributes
01440         if (copyFrom != NULL)
01441         {
01442                 primitive->setPrimitiveType(copyFrom->getPrimitiveType());
01443                 primitive->setReactionType(copyFrom->getReactionType());
01444                 primitive->setTriggerType(copyFrom->getTriggerType());
01445                 primitive->setCollisionMask(copyFrom->getCollisionMask());
01446                 primitive->setOcclusionMask(copyFrom->getOcclusionMask());
01447                 primitive->setObstacle(copyFrom->getObstacle());
01448                 primitive->setAbsorbtion(copyFrom->getAbsorbtion());
01449                 primitive->setHeight(copyFrom->getHeight());
01450                 if (primitive->getPrimitiveType() == UMovePrimitive::_2DOrientedBox)
01451                 {
01452                         float   width=0.0f, height=0.0f;
01453                         copyFrom->getSize(width, height);
01454                         primitive->setSize(width, height);
01455                 }
01456                 else
01457                 {
01458                         primitive->setRadius(copyFrom->getRadius());
01459                 }
01460         }
01461 
01462         // Return it
01463         return primitive;
01464 }
01465 
01466 // ***************************************************************************
01467 
01468 void CMoveContainer::removePrimitive (UMovePrimitive* primitive)
01469 {
01470         NL_ALLOC_CONTEXT( Pacs )
01471 
01472         // CMovePrimitive pointer
01473         CMovePrimitive *prim=(CMovePrimitive*)primitive;
01474 
01475         // Get the primitive world image
01476         for (uint8 i=0; i<prim->getNumWorldImage (); i++)
01477         {
01478                 // World image
01479                 uint8 worldImage=prim->getFirstWorldImage ()+i;
01480 
01481                 // Get primitive world image
01482                 CPrimitiveWorldImage *wI=prim->getWorldImage (worldImage);
01483 
01484                 // In modified list ?
01485                 if (wI->isInModifiedListFlag ())
01486                 {
01487                         // Non collisionable primitive ?
01488                         if (prim->isNonCollisionable())
01489                         {
01490                                 // Remove from all world image
01491                                 removeNCFromModifiedList (prim, worldImage);
01492                         }
01493                         else
01494                         {
01495                                 // Remove from modified list
01496                                 removeFromModifiedList (prim, worldImage);
01497                         }
01498                 }
01499         }
01500 
01501         // Remove from the set
01502         _PrimitiveSet.erase (prim);
01503 
01504         // Erase it
01505         freePrimitive (prim);
01506 }
01507 
01508 // ***************************************************************************
01509 
01510 void CMoveContainer::removeNCFromModifiedList (CMovePrimitive* primitive, uint8 worldImage)
01511 {
01512         // For each world image
01513         uint i;
01514         uint worldImageCount = _ChangedRoot.size();
01515         for (i=0; i<worldImageCount; i++)
01516         {
01517                 // For each changed primitives
01518                 CMovePrimitive *changed=_ChangedRoot[i];
01519                 CPrimitiveWorldImage *previous=NULL;
01520                 CPrimitiveWorldImage *wI=primitive->getWorldImage (worldImage);
01521 
01522                 while (changed)
01523                 {
01524                         // Get the primitive world image
01525                         CPrimitiveWorldImage *changedWI=changed->getWorldImage (worldImage);
01526 
01527                         // Remove from ot list
01528                         if (changed==primitive)
01529                         {
01530                                 // There is a previous primitive ?
01531                                 if (previous)
01532                                         previous->linkInModifiedList (wI->getNextModified ());
01533                                 else
01534                                         _ChangedRoot[i]=wI->getNextModified ();
01535 
01536                                 // Unlink
01537                                 wI->linkInModifiedList (NULL);
01538                                 wI->setInModifiedListFlag (false);
01539                                 break;
01540                         }
01541                         
01542                         // Next primitive
01543                         previous=changedWI;
01544                         changed=changedWI->getNextModified ();
01545                 }
01546 
01547                 // Breaked ?
01548                 if (changed==primitive)
01549                         break;
01550         }
01551 }
01552 
01553 // ***************************************************************************
01554  
01555 void CMoveContainer::removeFromModifiedList (CMovePrimitive* primitive, uint8 worldImage)
01556 {
01557         // For each changed primitives
01558         CMovePrimitive *changed=_ChangedRoot[worldImage];
01559         CPrimitiveWorldImage *previous=NULL;
01560         CPrimitiveWorldImage *wI=primitive->getWorldImage (worldImage);
01561 
01562         while (changed)
01563         {
01564                 // Get the primitive world image
01565                 CPrimitiveWorldImage *changedWI=changed->getWorldImage (worldImage);
01566 
01567                 // Remove from ot list
01568                 if (changed==primitive)
01569                 {
01570                         // There is a previous primitive ?
01571                         if (previous)
01572                                 previous->linkInModifiedList (wI->getNextModified ());
01573                         else
01574                                 _ChangedRoot[worldImage]=wI->getNextModified ();
01575 
01576                         // Unlink
01577                         wI->linkInModifiedList (NULL);
01578                         wI->setInModifiedListFlag (false);
01579                         break;
01580                 }
01581                 
01582                 // Next primitive
01583                 previous=changedWI;
01584                 changed=changedWI->getNextModified ();
01585         }
01586 }
01587 
01588 // ***************************************************************************
01589  
01590 void CMoveContainer::unlinkMoveElement  (CMoveElement *element, uint8 worldImage)
01591 {
01592         // Some checks
01593         nlassert (element->X<_CellCountWidth);
01594         nlassert (element->Y<_CellCountHeight);
01595 
01596         // Unlink it
01597         CMoveCell &cell=_VectorCell[worldImage][element->X+element->Y*_CellCountWidth];
01598         cell.unlinkX (element);
01599         //cell.unlinkY (element);
01600 }
01601 
01602 // ***************************************************************************
01603 
01604 void CMoveContainer::reaction (const CCollisionOTInfo& first)
01605 {
01606 //      H_AUTO(PACS_MC_reaction);
01607 
01608         // Static collision ?
01609         if (first.isCollisionAgainstStatic())
01610         {
01611                 // Check mode
01612                 nlassert (_Retriever);
01613 
01614                 // Cast
01615                 const CCollisionOTStaticInfo *staticInfo=safe_cast<const CCollisionOTStaticInfo*> (&first);
01616 
01617                 // Get the primitive world image
01618                 CMovePrimitive *movePrimitive=staticInfo->getPrimitive ();
01619                 CPrimitiveWorldImage *wI;
01620                 if (movePrimitive->isNonCollisionable ())
01621                         wI=movePrimitive->getWorldImage (0);
01622                 else
01623                         wI=movePrimitive->getWorldImage (staticInfo->getWorldImage());
01624 
01625                 // Dynamic collision
01626                 wI->reaction ( staticInfo->getCollisionDesc (), staticInfo->getGlobalPosition (),
01627                                                 *_Retriever, staticInfo->getDeltaTime(), _DeltaTime, *staticInfo->getPrimitive (), *this, staticInfo->getWorldImage());
01628         }
01629         else
01630         {
01631                 // Cast
01632                 const CCollisionOTDynamicInfo *dynInfo=safe_cast<const CCollisionOTDynamicInfo*> (&first);
01633 
01634                 // Get the primitives world image
01635                 CPrimitiveWorldImage *firstWI;
01636                 if (dynInfo->getFirstPrimitive ()->isNonCollisionable ())
01637                         firstWI=dynInfo->getFirstPrimitive ()->getWorldImage (0);
01638                 else
01639                         firstWI=dynInfo->getFirstPrimitive ()->getWorldImage (dynInfo->getFirstWorldImage());
01640 
01641                 CPrimitiveWorldImage *secondWI;
01642                 if (dynInfo->getSecondPrimitive ()->isNonCollisionable ())
01643                         secondWI=dynInfo->getSecondPrimitive ()->getWorldImage (0);
01644                 else
01645                         secondWI=dynInfo->getSecondPrimitive ()->getWorldImage (dynInfo->getSecondWorldImage());
01646 
01647                 // Dynamic collision
01648                 firstWI->reaction ( *secondWI, dynInfo->getCollisionDesc (), _Retriever, _SurfaceTemp, dynInfo->isCollision(), 
01649                                                         *dynInfo->getFirstPrimitive (), *dynInfo->getSecondPrimitive (), this, dynInfo->getFirstWorldImage(),
01650                                                         dynInfo->getSecondWorldImage(), dynInfo->isSecondStatic());
01651 
01660                 if (dynInfo->getFirstPrimitive ()->isCollisionable ())
01661                 {
01662                         if (dynInfo->getFirstPrimitive ()->isTriggered (*dynInfo->getSecondPrimitive (), dynInfo->isEnter(), dynInfo->isExit()))
01663                         {
01664                                 if (dynInfo->isEnter())
01665                                         newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::In);
01666                                 if (dynInfo->isExit())
01667                                         newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::Out);
01668                                 if (dynInfo->isInside())
01669                                         newTrigger (dynInfo->getFirstPrimitive (), dynInfo->getSecondPrimitive (), dynInfo->getCollisionDesc (), UTriggerInfo::Inside);
01670                         }
01671                 }
01672         }
01673 }
01674 
01675 // ***************************************************************************
01676 
01677 void CMoveContainer::setAsStatic (uint8 worldImage)
01678 {
01679         NL_ALLOC_CONTEXT( Pacs )
01680 
01681         // Add this world image in the static set of world image
01682         _StaticWorldImage.insert (worldImage);
01683 }
01684 
01685 // ***************************************************************************
01686 
01687 void CMoveContainer::duplicateWorldImage (uint8 source, uint8 dest)
01688 {
01689         NL_ALLOC_CONTEXT( Pacs )
01690 
01691         // Cell count
01692         uint cellCount=_CellCountWidth*_CellCountHeight;
01693 
01694         // Clear dest modified list
01695         clearModifiedList (dest);
01696 
01697         // Clear destination cells
01698         uint i;
01699         for (i=0; i<cellCount; i++)
01700         {
01701                 // Get first X
01702                 CMoveElement *elm;
01703                 while ((elm=_VectorCell[dest][i].getFirstX ()))
01704                 {
01705                         // Get primitive world image
01706                         CPrimitiveWorldImage *wI=elm->Primitive->getWorldImage (dest);
01707 
01708                         // Remove the primitive
01709                         int i;
01710                         for (i=0; i<4; i++)
01711                         {
01712                                 if (wI->getMoveElement(i))
01713                                         wI->removeMoveElement (i, *this, dest);
01714                         }
01715                 }
01716         }
01717 
01718         // Duplicate destination cells
01719         for (i=0; i<cellCount; i++)
01720         {
01721                 // Get first X
01722                 CMoveElement *elm=_VectorCell[source][i].getFirstX ();
01723                 while (elm)
01724                 {
01725                         // Get primitive world image
01726                         CPrimitiveWorldImage *wISource=elm->Primitive->getWorldImage (source);
01727                         CPrimitiveWorldImage *wIDest=elm->Primitive->getWorldImage (dest);
01728 
01729                         // First time the primitive is visited ?
01730                         if (wIDest->getMoveElement (0)==NULL)
01731                         {
01732                                 wIDest->copy (*wISource);
01733                         }
01734                 
01735                         // Add at the end of the list
01736                         wIDest->addMoveElementendOfList (_VectorCell[dest][i], elm->X, elm->Y, elm->Primitive, *this);
01737 
01738                         // Added ?
01739                         nlassert (wIDest->getMoveElement (0)!=NULL);
01740 
01741                         // Next primitive
01742                         elm=elm->NextX;
01743                 }
01744         }
01745 }
01746 
01747 // ***************************************************************************
01748 
01749 UMoveContainer *UMoveContainer::createMoveContainer (double xmin, double ymin, double xmax, double ymax, 
01750                 uint widthCellCount, uint heightCellCount, double primitiveMaxSize, uint8 numWorldImage, 
01751                 uint maxIteration, uint otSize)
01752 {
01753         NL_ALLOC_CONTEXT( Pacs )
01754 
01755         // Create a CMoveContainer
01756         return new CMoveContainer (xmin, ymin, xmax, ymax, widthCellCount, heightCellCount, primitiveMaxSize, numWorldImage, maxIteration, otSize);
01757 }
01758 
01759 // ***************************************************************************
01760 
01761 UMoveContainer *UMoveContainer::createMoveContainer (UGlobalRetriever* retriever, uint widthCellCount, 
01762         uint heightCellCount, double primitiveMaxSize, uint8 numWorldImage, uint maxIteration, uint otSize)
01763 {
01764         NL_ALLOC_CONTEXT( Pacs )
01765 
01766         // Cast
01767         nlassert (dynamic_cast<CGlobalRetriever*>(retriever));
01768         CGlobalRetriever* r=static_cast<CGlobalRetriever*>(retriever);
01769 
01770         // Create a CMoveContainer
01771         return new CMoveContainer (r, widthCellCount, heightCellCount, primitiveMaxSize, numWorldImage, maxIteration, otSize);
01772 }
01773 
01774 // ***************************************************************************
01775 
01776 void UCollisionDesc::serial (NLMISC::IStream& stream)
01777 {
01778         stream.serial (ContactPosition);
01779         stream.serial (ContactNormal0);
01780         stream.serial (ContactNormal1);
01781         stream.serial (ContactTime);
01782 };
01783 
01784 // ***************************************************************************
01785 
01786 void UTriggerInfo::serial (NLMISC::IStream& stream)
01787 {
01788         stream.serial (Object0);
01789         stream.serial (Object1);
01790         stream.serial (CollisionDesc);
01791 }
01792 
01793 
01794 
01795 // ***************************************************************************
01796 void CMoveContainer::addCollisionnablePrimitiveBlock(UPrimitiveBlock *pb,uint8 firstWorldImage,uint8 numWorldImage,std::vector<UMovePrimitive*> *primitives,float orientation,const NLMISC::CVector &position, bool dontSnapToGround /* = false*/, const NLMISC::CVector &scale /* = NLMISC::CVector(1.0f, 1.0f, 1.0f)*/)
01797 {
01798         NL_ALLOC_CONTEXT( Pacs )
01799 
01800         CPrimitiveBlock *block = NLMISC::safe_cast<CPrimitiveBlock *>(pb);
01801         // Reserve the pointer array
01802         if (primitives)
01803                 primitives->reserve (block->Primitives.size());
01804 
01805         // For each primitive
01806         uint prim;
01807         for (prim=0; prim<block->Primitives.size(); prim++)
01808         {
01809                 // Create a collisionable primitive
01810                 UMovePrimitive *primitive = addCollisionablePrimitive (firstWorldImage, numWorldImage);
01811                 
01812                 // Ref on the block descriptor
01813                 CPrimitiveDesc &desc = block->Primitives[prim];
01814 
01815                 // Set its properties
01816                 primitive->setPrimitiveType (desc.Type);
01817                 primitive->setReactionType (desc.Reaction);
01818                 primitive->setTriggerType (desc.Trigger);
01819                 primitive->setCollisionMask (desc.CollisionMask);
01820                 primitive->setOcclusionMask (desc.OcclusionMask);
01821                 primitive->setObstacle (desc.Obstacle);
01822                 primitive->setAbsorbtion (desc.Attenuation);
01823                 primitive->setDontSnapToGround(dontSnapToGround);
01824                 primitive->UserData = desc.UserData;
01825                 if (desc.Type == UMovePrimitive::_2DOrientedBox)
01826                 {
01827                         // ONLY ASSUME UNIFORM SCALE ON X/Y
01828                         primitive->setSize (desc.Length[0]*scale.x, desc.Length[1]*scale.x);
01829                 }
01830                 else
01831                 {
01832                         // ONLY ASSUME UNIFORM SCALE ON X/Y
01833                         nlassert (desc.Type == UMovePrimitive::_2DOrientedCylinder);
01834                         primitive->setRadius (desc.Length[0]*scale.x);
01835                 }
01836                 primitive->setHeight (desc.Height*scale.z);
01837 
01838                 // Insert the primitives
01839 
01840                 // For each world image
01841                 uint wI;
01842                 for (wI=firstWorldImage; wI<(uint)(firstWorldImage+numWorldImage); wI++)
01843                 {
01844                         // Insert the primitive
01845                         primitive->insertInWorldImage (wI);
01846 
01847                         // Final position&
01848                         float cosa = (float) cos (orientation);
01849                         float sina = (float) sin (orientation);
01850                         CVector finalPos;
01851                         finalPos.x = cosa * desc.Position.x * scale.x - sina * desc.Position.y * scale.y + position.x;
01852                         finalPos.y = sina * desc.Position.x * scale.x + cosa * desc.Position.y * scale.y + position.y;
01853                         finalPos.z = desc.Position.z *scale.z + position.z;
01854 
01855                         // Set the primtive orientation
01856                         if (desc.Type == UMovePrimitive::_2DOrientedBox)
01857                                 primitive->setOrientation ((float)fmod (desc.Orientation + orientation, 2*Pi), wI);
01858 
01859                         // Set the primitive global position
01860                         primitive->setGlobalPosition (finalPos, wI);
01861                 }
01862 
01863                 // Feedback asked ?
01864                 if (primitives)
01865                 {
01866                         // Add the pointer
01867                         primitives->push_back (primitive);
01868                 }
01869         }                       
01870 }
01871 
01872 
01873 // ***************************************************************************
01874 
01875 bool CMoveContainer::loadCollisionablePrimitiveBlock (const char *filename, uint8 firstWorldImage, uint8 numWorldImage, std::vector<UMovePrimitive*> *primitives, float orientation, const NLMISC::CVector &position, bool dontSnapToGround /*= false*/)
01876 {
01877         NL_ALLOC_CONTEXT( Pacs )
01878 
01879         // Check world image
01880         if ( (uint)(firstWorldImage+numWorldImage) > _ChangedRoot.size() )
01881         {
01882                 nlwarning ("Invalid world image number.");
01883                 return false;
01884         }
01885 
01886         // Try to load the file
01887         CIFile file;
01888         if (file.open (filename))
01889         {
01890                 // Create the XML stream
01891                 CIXml input;
01892 
01893                 // Init
01894                 if (input.init (file))
01895                 {
01896                         // The primitive block
01897                         CPrimitiveBlock block;
01898 
01899                         // Serial it
01900                         file.serial (block);
01901 
01902                         // add primitives
01903                         addCollisionnablePrimitiveBlock(&block, firstWorldImage, numWorldImage, primitives, orientation, position, dontSnapToGround);
01904                 
01905                         return true;
01906                 }
01907                 else
01908                 {
01909                         // Warning
01910                         nlwarning ("Can't init XML stream with file %s.", filename);
01911 
01912                         return false;
01913                 }
01914         }
01915         else
01916         {
01917                 // Warning
01918                 nlwarning ("Can't load primitive block %s.", filename);
01919 
01920                 return false;
01921         }
01922 }
01923 
01924 
01925 // ***************************************************************************
01926 void CMoveContainer::getPrimitives(std::vector<const UMovePrimitive *> &dest) const
01927 {       
01928         NL_ALLOC_CONTEXT( Pacs )
01929 
01930         dest.resize(_PrimitiveSet.size());
01931         std::copy(_PrimitiveSet.begin(), _PrimitiveSet.end(), dest.begin());
01932 }
01933 
01934 
01935 // ***************************************************************************
01936 void UMoveContainer::getPACSCoordsFromMatrix(NLMISC::CVector &pos,float &angle,const NLMISC::CMatrix &mat)
01937 {
01938         pos = mat.getPos();
01939         CVector orient = mat.mulVector(NLMISC::CVector::I);
01940         orient.z = 0.f;
01941         orient.normalize();
01942         angle = orient.y >= 0.f ? ::acosf(orient.x)  
01943                                                         : 2.f * (float) NLMISC::Pi - ::acosf(orient.x);
01944 
01945 }
01946 
01947 // ***************************************************************************
01948 bool CMoveContainer::evalNCPrimitiveCollision (double deltaTime, UMovePrimitive *primitive, uint8 worldImage)
01949 {
01950         NL_ALLOC_CONTEXT( Pacs )
01951 
01952         // New test time
01953         _TestTime++;
01954 
01955         // Clear triggers
01956         _Triggers.clear ();
01957 
01958         // Only non-collisionable primitives
01959         if (!primitive->isCollisionable())
01960         {
01961                 // Delta time
01962                 _DeltaTime=deltaTime;
01963 
01964                 // Begin of the time slice to compute
01965                 double beginTime = 0;
01966                 double collisionTime = deltaTime;
01967 
01968                 // Get the world image
01969                 CPrimitiveWorldImage *wI = ((CMovePrimitive*)primitive)->getWorldImage (0);
01970 
01971                 CCollisionOTInfo *firstCollision = NULL;
01972                 do
01973                 {
01974                         //nlassert (beginTime < 1.0);
01975                         if (beginTime >= 1.0)
01976                         {
01977                                 nlwarning("PACS: evalNCPrimitiveCollision() failure, beginTime [%f] >= 1.0", beginTime);
01978                                 return false;
01979                         }
01980 
01981                         // Update the primitive
01982                         wI->update (beginTime, deltaTime, *(CMovePrimitive*)primitive);
01983 
01984                         CVectorD d0=wI->getDeltaPosition();
01985 
01986                         // Eval collision again the terrain
01987                         bool testMoveValid = false;
01988                         CCollisionOTStaticInfo staticColInfo;
01989                         CCollisionOTDynamicInfo dynamicColInfoWI0;
01990                         CCollisionOTDynamicInfo dynamicColInfoWI;
01991 
01992                         firstCollision = NULL;
01993 
01994                         // If collision found, note it is on the landscape
01995                         if (evalOneTerrainCollision (beginTime, (CMovePrimitive*)primitive, worldImage, false, testMoveValid, &staticColInfo, NULL))
01996                         {
01997                                 firstCollision = &staticColInfo;
01998                         }
01999 
02000                         // Eval collision again the static primitives
02001                         std::set<uint8>::iterator ite=_StaticWorldImage.begin();
02002                         while (ite!=_StaticWorldImage.end())
02003                         {
02004                                 // Eval in this world image
02005                                 if (evalOnePrimitiveCollision (beginTime, (CMovePrimitive*)primitive, *ite, worldImage, false, true, testMoveValid, &dynamicColInfoWI0, NULL))
02006                                 {
02007                                         // First collision..
02008                                         if (!firstCollision || (firstCollision->getCollisionTime () > dynamicColInfoWI0.getCollisionTime ()))
02009                                         {
02010                                                 firstCollision = &dynamicColInfoWI0;
02011                                         }
02012                                 }
02013 
02014                                 // Next world image
02015                                 ite++;
02016                         }
02017 
02018                         // Checks
02019                         CVectorD d1=wI->getDeltaPosition();
02020 
02021                         // Eval collision again the world image
02022                         if (_StaticWorldImage.find (worldImage)==_StaticWorldImage.end())
02023                         {
02024                                 if (evalOnePrimitiveCollision (beginTime, (CMovePrimitive*)primitive, worldImage, worldImage, false, false, testMoveValid, &dynamicColInfoWI, NULL))
02025                                 {
02026                                         // First collision..
02027                                         if (!firstCollision || (firstCollision->getCollisionTime () > dynamicColInfoWI.getCollisionTime ()))
02028                                         {
02029                                                 firstCollision = &dynamicColInfoWI;
02030                                         }
02031                                 }
02032                         }
02033 
02034                         // Checks
02035                         CVectorD d2=wI->getDeltaPosition();
02036                         nlassert ((d0==d1)&&(d0==d2));
02037 
02038 //                      if (found)
02039 //                              nlstop;
02040                         
02041                         // Reaction
02042                         if (firstCollision)
02043                         {
02044                                 collisionTime = firstCollision->getCollisionTime ();
02045                                 reaction (*firstCollision);
02046                                 //nlassert (collisionTime != 1);
02047 
02048                                 if (collisionTime == 1)
02049                                 {
02050                                         nlwarning("PACS: evalNCPrimitiveCollision() failure, collisionTime [%f] == 1", collisionTime);
02051                                         return false;
02052                                 }
02053                         }
02054                         else
02055                         {
02056                                 // Retriever mode ?
02057                                 if (_Retriever&&testMoveValid)
02058                                 {                                                               
02059                                         // Do move
02060                                         wI->doMove (*_Retriever, _SurfaceTemp, deltaTime, collisionTime, ((CMovePrimitive*)primitive)->getDontSnapToGround());
02061                                 }
02062                                 else
02063                                 {
02064                                         // Do move
02065                                         wI->doMove (_DeltaTime);
02066                                 }
02067                         }
02068                         
02069                         beginTime = collisionTime;
02070                 }
02071                 while (firstCollision);
02072         }
02073         else
02074                 return false;
02075 
02076         return true;
02077 }
02078 
02079 
02080 } // NLPACS


Generated on Tue Mar 16 06:43:06 2004 for NeL by doxygen 1.3.6