From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/a04624.html | 2169 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2169 insertions(+) create mode 100644 docs/doxygen/nel/a04624.html (limited to 'docs/doxygen/nel/a04624.html') diff --git a/docs/doxygen/nel/a04624.html b/docs/doxygen/nel/a04624.html new file mode 100644 index 00000000..18ad80a6 --- /dev/null +++ b/docs/doxygen/nel/a04624.html @@ -0,0 +1,2169 @@ + + +NeL: move_container.cpp File Reference + + + +
+

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
+ + -- cgit v1.2.1