NL3D::CMiniCol Class Reference

#include <mini_col.h>


Detailed Description

This is a TEMPORARY collision "system".
Author:
Lionel Berenguier

Nevrax France

Date:
2000

Definition at line 54 of file mini_col.h.

Public Member Functions

void addZone (uint16 zoneId)
 Add a zone to the collision system. Zone must be loaded into the landscape before.

 CMiniCol ()
 Constructor.

void getFaces (std::vector< CTriangle > &triresult, const CAABBox &bbox)
bool getGroundNormal (const CVector &pos, CVector &normal, float hup=0.5, float hbot=1000)
void init (CLandscape *land, float radMin=100, float radDelta=50)
 Init the size of the collision system, and init it with the landscape.

void removeZone (uint16 zoneId)
 Remove a zone from the collision system. Zone do not have to be loaded into the landscape.

void setCenter (const CVector &center)
 Reset the center of interset of the collision zone.

bool snapToGround (CVector &pos, float hup=0.5, float hbot=1000)
bool testMove (const CVector &prec, CVector &cur)

Private Types

typedef CQuadGrid< CFaceTGrid
typedef std::set< CZoneIdentTZoneSet

Private Member Functions

void addFaces (const std::vector< CTriangle > &faces, uint16 zoneId, uint16 patchId)
void addLandscapePart (uint16 zoneId, uint16 patchId)
void removeLandScapePart (uint16 zoneId, uint16 patchId, const CBSphere &sphere)

Private Attributes

TGrid _Grid
CRefPtr< CLandscape_Landscape
float _RadMax
float _RadMin
TZoneSet _Zones


Member Typedef Documentation

typedef CQuadGrid<CFace> NL3D::CMiniCol::TGrid [private]
 

Definition at line 134 of file mini_col.h.

typedef std::set<CZoneIdent> NL3D::CMiniCol::TZoneSet [private]
 

Definition at line 135 of file mini_col.h.


Constructor & Destructor Documentation

NL3D::CMiniCol::CMiniCol  ) 
 

Constructor.

Definition at line 47 of file mini_col.cpp.

References _RadMax, _RadMin, NL3D::CQuadGrid< T >::create(), and NL3D::GridEltSize.

00048 {
00049         _RadMin= 100;
00050         _RadMax= 125;
00051         _Grid.create(GridSize, GridEltSize);
00052 }


Member Function Documentation

void NL3D::CMiniCol::addFaces const std::vector< CTriangle > &  faces,
uint16  zoneId,
uint16  patchId
[private]
 

Definition at line 56 of file mini_col.cpp.

References NLMISC::CAABBox::extend(), NL3D::CMiniCol::CFace::Face, NLMISC::CAABBox::getMax(), NLMISC::CAABBox::getMin(), NL3D::CQuadGrid< T >::insert(), NLMISC::CPlane::make(), NL3D::CMiniCol::CFace::PatchId, NL3D::CMiniCol::CFace::Plane, NLMISC::CAABBox::setCenter(), sint, uint16, NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, NLMISC::CTriangle::V2, and NL3D::CMiniCol::CFace::ZoneId.

Referenced by addLandscapePart().

00057 {
00058         for(sint i=0;i<(sint)faces.size();i++)
00059         {
00060                 const CTriangle &f= faces[i];
00061                 CAABBox box;
00062                 box.setCenter(f.V0);
00063                 box.extend(f.V1);
00064                 box.extend(f.V2);
00065                 CFace   node;
00066                 node.Face= f;
00067                 node.Plane.make(f.V0, f.V1, f.V2);
00068                 node.ZoneId= zoneId;
00069                 node.PatchId=patchId;
00070                 _Grid.insert(box.getMin(), box.getMax(), node);
00071         }
00072 }

void NL3D::CMiniCol::addLandscapePart uint16  zoneId,
uint16  patchId
[private]
 

Definition at line 76 of file mini_col.cpp.

References addFaces(), and uint16.

Referenced by setCenter().

00077 {
00078         vector<CTriangle> faces;
00079         _Landscape->buildCollideFaces(zoneId, patchId, faces);
00080         addFaces(faces, zoneId, patchId);
00081 }

void NL3D::CMiniCol::addZone uint16  zoneId  ) 
 

Add a zone to the collision system. Zone must be loaded into the landscape before.

Definition at line 116 of file mini_col.cpp.

References _Zones, NLMISC::CBSphere::Center, NLMISC::CAABBoxExt::getCenter(), NL3D::CZone::getNumPatchs(), NL3D::CZone::getPatchBSphere(), NLMISC::CAABBoxExt::getRadius(), NL3D::CZone::getZoneBB(), nlassert, NL3D::CMiniCol::CZoneIdent::Patchs, NLMISC::CBSphere::Radius, sint, NL3D::CMiniCol::CZoneIdent::Sphere, uint16, and NL3D::CMiniCol::CZoneIdent::ZoneId.

00117 {
00118         CZoneIdent      newZone;
00119 
00120         // landscape must have been inited.
00121         nlassert(_Landscape);
00122         const CZone     *zone= _Landscape->getZone(zoneId);
00123         // zone must be loaded into landscape.
00124         nlassert(zone);
00125 
00126         // Fill the newzone.
00127         newZone.ZoneId= zoneId;
00128         newZone.Sphere.Center= zone->getZoneBB().getCenter();
00129         newZone.Sphere.Radius= zone->getZoneBB().getRadius();
00130         newZone.Patchs.resize(zone->getNumPatchs());
00131         for(sint i=0;i<zone->getNumPatchs();i++)
00132         {
00133                 newZone.Patchs[i].Sphere= zone->getPatchBSphere(i);
00134         }
00135 
00136         // Add it to the set (if not already done...).
00137         _Zones.insert(newZone);
00138 }

void NL3D::CMiniCol::getFaces std::vector< CTriangle > &  triresult,
const CAABBox bbox
 

This function get the faces which intersect a bbox..

Definition at line 467 of file mini_col.cpp.

References NL3D::CQuadGrid< T >::begin(), NL3D::CQuadGrid< T >::end(), NLMISC::CAABBox::getMax(), NLMISC::CAABBox::getMin(), NLMISC::CAABBox::intersect(), NL3D::CQuadGrid< T >::select(), NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, and NLMISC::CTriangle::V2.

00468 {
00469         triresult.clear();
00470 
00471         // Select.
00472         _Grid.select(bbox.getMin(),bbox.getMax());
00473 
00474         // For each face, test if it is under pos, then test if height is correct.
00475         CQuadGrid<CFace>::CIterator     iFace;
00476         for(iFace= _Grid.begin();iFace!=_Grid.end();iFace++)
00477         {
00478                 CTriangle       &face= (*iFace).Face;
00479 
00480                 if(bbox.intersect(face.V0, face.V1, face.V2))
00481                 {
00482                         triresult.push_back(face);
00483                 }
00484         }
00485 
00486 }

bool NL3D::CMiniCol::getGroundNormal const CVector pos,
CVector normal,
float  hup = 0.5,
float  hbot = 1000
 

This function get the ground normal under a position. hbot and hup are the margin where face can be taken.

Definition at line 341 of file mini_col.cpp.

References NL3D::CQuadGrid< T >::begin(), NL3D::CQuadGrid< T >::end(), NLMISC::CAABBox::extend(), NLMISC::CPlane::getNormal(), height, NLMISC::CAABBox::include(), NLMISC::CPlane::intersect(), NL3D::CQuadGrid< T >::select(), NLMISC::CAABBox::setCenter(), NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, NLMISC::CTriangle::V2, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z.

00342 {
00343         CVector b1,b2;
00344         bool    found=false;
00345         float   height=0.0;
00346 
00347 
00348         // Select quad nodes which contains pos.
00349         b1=b2=pos;
00350         b1.z-= hbot;
00351         b2.z+= hup;
00352         // Select.
00353         _Grid.select(b1,b2);
00354 
00355         // For each face, test if it is under pos, then test if height is correct.
00356         CQuadGrid<CFace>::CIterator     iFace;
00357         for(iFace= _Grid.begin();iFace!=_Grid.end();iFace++)
00358         {
00359                 CTriangle       &pFace= (*iFace).Face;
00360                 CPlane          &pPlane= (*iFace).Plane;
00361                 // Order is important.
00362                 CVector         &p0= pFace.V0;
00363                 CVector         &p1= pFace.V1;
00364                 CVector         &p2= pFace.V2;
00365 
00366                 // TOIMP: This is VERY SLOW!!! (hope that the quadtree will help, but it still very slow...).
00367 
00368                 // Yoyo Debug, test, if the point may be IN the bbox.
00369                 CAABBox         bbFace;
00370                 bbFace.setCenter(p0);
00371                 bbFace.extend(p1);
00372                 bbFace.extend(p2);
00373                 CVector         bext=p0;
00374                 bext.z= maxof(p0.z, p1.z, p2.z)+hbot;
00375                 bbFace.extend(bext);
00376                 bext.z= minof(p0.z, p1.z, p2.z)-hup;
00377                 bbFace.extend(bext);
00378                 if(!bbFace.include(pos))
00379                         continue;
00380 
00381                 // Test if the face enclose the pos in X/Y plane.
00382                 // NB: compute and using a BBox to do a rapid test is not a very good idea, since it will 
00383                 // add an overhead which is NOT negligeable compared to the following test.
00384                 float           a,b,c;          // 2D cartesian coefficients of line in plane X/Y.
00385                 // Line p0-p1.
00386                 a= -(p1.y-p0.y);
00387                 b= (p1.x-p0.x);
00388                 c= -(p0.x*a + p0.y*b);
00389                 if( (a*pos.x + b*pos.y + c) < 0)        continue;
00390                 // Line p1-p2.
00391                 a= -(p2.y-p1.y);
00392                 b= (p2.x-p1.x);
00393                 c= -(p1.x*a + p1.y*b);
00394                 if( (a*pos.x + b*pos.y + c) < 0)        continue;
00395                 // Line p2-p0.
00396                 a= -(p0.y-p2.y);
00397                 b= (p0.x-p2.x);
00398                 c= -(p2.x*a + p2.y*b);
00399                 if( (a*pos.x + b*pos.y + c) < 0)        continue;
00400 
00401 
00402                 // Compute the possible height.
00403                 CVector         tmp;
00404                 // intersect the vertical line with the plane.
00405                 tmp= pPlane.intersect(pos, pos-CVector(0,0,100));
00406                 float           h= tmp.z;
00407                 // Test if it would fit in the wanted field.
00408                 if(h>pos.z+hup) continue;
00409                 if(h<pos.z-hbot)        continue;
00410 
00411                 // OK!!
00412                 if(!found)
00413                 {
00414                         found=true;
00415                         height=h;
00416                         normal= pPlane.getNormal();
00417                 }
00418                 else
00419                 {
00420                         if(h>height)
00421                         {
00422                                 normal= pPlane.getNormal();
00423                                 height= h;
00424                         }
00425                 }
00426         }
00427 
00428         return found;
00429 }

void NL3D::CMiniCol::init CLandscape land,
float  radMin = 100,
float  radDelta = 50
 

Init the size of the collision system, and init it with the landscape.

Definition at line 107 of file mini_col.cpp.

References _RadMax, and _RadMin.

00108 {
00109         _Landscape= land;
00110         _RadMin= radMin;
00111         _RadMax= radMin+radDelta;
00112 }

void NL3D::CMiniCol::removeLandScapePart uint16  zoneId,
uint16  patchId,
const CBSphere sphere
[private]
 

Definition at line 85 of file mini_col.cpp.

References NL3D::CQuadGrid< T >::begin(), NLMISC::CBSphere::Center, NL3D::CQuadGrid< T >::end(), NL3D::CQuadGrid< T >::erase(), NLMISC::CAABBox::getMax(), NLMISC::CAABBox::getMin(), NLMISC::CBSphere::Radius, NL3D::CQuadGrid< T >::select(), NLMISC::CAABBox::setCenter(), NLMISC::CAABBox::setHalfSize(), and uint16.

Referenced by removeZone(), and setCenter().

00086 {
00087         // Build the AAbox which englobe the bsphere of the patch.
00088         CAABBox         bb;
00089         bb.setCenter(sphere.Center);
00090         float   l= sphere.Radius;
00091         bb.setHalfSize(CVector(l,l,l));
00092 
00093         // For optimisation, select only faces which are IN the bbox of the patch.
00094         _Grid.select(bb.getMin(), bb.getMax());
00095         CQuadGrid<CFace>::CIterator     iFace;
00096         for(iFace= _Grid.begin();iFace!=_Grid.end();)
00097         {
00098                 if((*iFace).isFromPatch(zoneId, patchId))
00099                         iFace= _Grid.erase(iFace);
00100                 else
00101                         iFace++;
00102         }
00103 }

void NL3D::CMiniCol::removeZone uint16  zoneId  ) 
 

Remove a zone from the collision system. Zone do not have to be loaded into the landscape.

Definition at line 142 of file mini_col.cpp.

References _Zones, NL3D::CMiniCol::CPatchIdent::Inserted, NL3D::CMiniCol::CZoneIdent::NPatchInserted, NL3D::CMiniCol::CZoneIdent::Patchs, removeLandScapePart(), sint, NL3D::CMiniCol::CPatchIdent::Sphere, uint16, and NL3D::CMiniCol::CZoneIdent::ZoneId.

00143 {
00144         CZoneIdent      delZone;
00145 
00146 
00147         // First, delete all patch from the grid.
00148         //=======================================
00149         // Fill the key part only.
00150         delZone.ZoneId= zoneId;
00151         // Find the zone (or quit).
00152         TZoneSet::iterator      itZone;
00153         itZone= _Zones.find(delZone);
00154         if(itZone==_Zones.end())
00155                 return;
00156 
00157         CZoneIdent      &zone= const_cast<CZoneIdent&>(*itZone);
00158         for(sint i=0;i<(sint)zone.Patchs.size();i++)
00159         {
00160                 CPatchIdent     &pa= zone.Patchs[i];
00161                 if(pa.Inserted)
00162                 {
00163                         // Reject the patch.
00164                         removeLandScapePart(zone.ZoneId, i, pa.Sphere);
00165                         pa.Inserted= false;
00166                         zone.NPatchInserted--;
00167                 }
00168         }
00169 
00170         // Then, delete it.
00171         //=================
00172         _Zones.erase(delZone);
00173         
00174 }

void NL3D::CMiniCol::setCenter const CVector center  ) 
 

Reset the center of interset of the collision zone.

Definition at line 178 of file mini_col.cpp.

References _RadMax, _RadMin, _Zones, addLandscapePart(), NLMISC::CBSphere::Center, NL3D::CMiniCol::CPatchIdent::Inserted, NLMISC::CBSphere::intersect(), NL3D::CMiniCol::CZoneIdent::NPatchInserted, NL3D::CMiniCol::CZoneIdent::Patchs, removeLandScapePart(), sint, NL3D::CMiniCol::CPatchIdent::Sphere, NL3D::CMiniCol::CZoneIdent::Sphere, NLMISC::CVector::z, and NL3D::CMiniCol::CZoneIdent::ZoneId.

00179 {
00180         CBSphere        BMin(center, _RadMin), BMax(center, _RadMax);
00181 
00182         // For all zones, test if must insert patchs..
00183         TZoneSet::iterator      itZone;
00184         for(itZone= _Zones.begin();itZone!=_Zones.end();itZone++)
00185         {
00186                 CZoneIdent      &zone= const_cast<CZoneIdent&>(*itZone);
00187 
00188                 // Tests must be done in 2D...
00189                 BMin.Center.z= zone.Sphere.Center.z;
00190                 BMax.Center.z= zone.Sphere.Center.z;
00191 
00192                 // Must test first if the zone is IN the area.
00193                 //=============================================
00194                 bool    zoneIn= false;
00195                 if(zone.NPatchInserted==0)
00196                 {
00197                         if(BMin.intersect(zone.Sphere))
00198                                 zoneIn= true;
00199                 }
00200                 else
00201                         zoneIn= true;
00202 
00203                 // Then for all patchs, must test if the patch must be inserted, or rejected.
00204                 //=============================================
00205                 if(zoneIn)
00206                 {
00207                         for(sint i=0;i<(sint)zone.Patchs.size();i++)
00208                         {
00209                                 CPatchIdent     &pa= zone.Patchs[i];
00210 
00211                                 // Tests must be done in 2D...
00212                                 BMin.Center.z= pa.Sphere.Center.z;
00213                                 BMax.Center.z= pa.Sphere.Center.z;
00214 
00215                                 if(pa.Inserted)
00216                                 {
00217                                         // Reject the patch, if entirely OUT the max radius.
00218                                         if(!BMax.intersect(pa.Sphere))
00219                                         {
00220                                                 removeLandScapePart(zone.ZoneId, i, pa.Sphere);
00221                                                 pa.Inserted= false;
00222                                                 zone.NPatchInserted--;
00223                                         }
00224                                 }
00225                                 else
00226                                 {
00227                                         // Insert the pacth, if only partially IN the min radius.
00228                                         if(BMin.intersect(pa.Sphere))
00229                                         {
00230                                                 addLandscapePart(zone.ZoneId, i);
00231                                                 pa.Inserted= true;
00232                                                 zone.NPatchInserted++;
00233                                         }
00234                                 }
00235                         }
00236                 }
00237         }
00238 }

bool NL3D::CMiniCol::snapToGround CVector pos,
float  hup = 0.5,
float  hbot = 1000
 

This function snap a position on the current set of faces. hbot and hup are the margin where pos.z can't change. (the pos can't move higher than +hup and lower than -hbot)

Definition at line 242 of file mini_col.cpp.

References NL3D::CQuadGrid< T >::begin(), NL3D::CQuadGrid< T >::end(), height, NLMISC::CPlane::intersect(), NL3D::CQuadGrid< T >::select(), NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, NLMISC::CTriangle::V2, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z.

Referenced by testMove().

00243 {
00244         CVector b1,b2;
00245         bool    found=false;
00246         float   height;
00247 
00248 
00249         // Select quad nodes which contains pos.
00250         b1=b2=pos;
00251         b1.z-= hbot;
00252         b2.z+= hup;
00253         // Select.
00254         _Grid.select(b1,b2);
00255 
00256         // For each face, test if it is under pos, then test if height is correct.
00257         CQuadGrid<CFace>::CIterator     iFace;
00258         for(iFace= _Grid.begin();iFace!=_Grid.end();iFace++)
00259         {
00260                 CTriangle       &pFace= (*iFace).Face;
00261                 CPlane          &pPlane= (*iFace).Plane;
00262                 // Order is important.
00263                 CVector         &p0= pFace.V0;
00264                 CVector         &p1= pFace.V1;
00265                 CVector         &p2= pFace.V2;
00266 
00267                 // TOIMP: This is VERY SLOW!!! (hope that the quadtree will help, but it still very slow...).
00268 
00269                 // Yoyo Debug, test, if the point may be IN the bbox.
00270                 /*CAABBox               bbFace;
00271                 bbFace.setCenter(p0);
00272                 bbFace.extend(p1);
00273                 bbFace.extend(p2);
00274                 CVector         bext=p0;
00275                 bext.z= maxof(p0.z, p1.z, p2.z)+hbot;
00276                 bbFace.extend(bext);
00277                 bext.z= minof(p0.z, p1.z, p2.z)-hup;
00278                 bbFace.extend(bext);
00279                 if(!bbFace.include(pos))
00280                         continue;*/
00281 
00282                 // Test if the face enclose the pos in X/Y plane.
00283                 // NB: compute and using a BBox to do a rapid test is not a very good idea, since it will 
00284                 // add an overhead which is NOT negligeable compared to the following test.
00285                 float           a,b,c;          // 2D cartesian coefficients of line in plane X/Y.
00286                 // Line p0-p1.
00287                 a= -(p1.y-p0.y);
00288                 b= (p1.x-p0.x);
00289                 c= -(p0.x*a + p0.y*b);
00290                 if( (a*pos.x + b*pos.y + c) < 0)        continue;
00291                 // Line p1-p2.
00292                 a= -(p2.y-p1.y);
00293                 b= (p2.x-p1.x);
00294                 c= -(p1.x*a + p1.y*b);
00295                 if( (a*pos.x + b*pos.y + c) < 0)        continue;
00296                 // Line p2-p0.
00297                 a= -(p0.y-p2.y);
00298                 b= (p0.x-p2.x);
00299                 c= -(p2.x*a + p2.y*b);
00300                 if( (a*pos.x + b*pos.y + c) < 0)        continue;
00301 
00302 
00303                 // Compute the possible height.
00304                 CVector         tmp;
00305                 // intersect the vertical line with the plane.
00306                 tmp= pPlane.intersect(pos, pos-CVector(0,0,100));
00307 
00308                 /*
00309                 // CTriangle intersect() method.
00310                 CVector tmp;
00311                 if(pFace.intersect(b1, b2, tmp, pPlane))
00312                 */
00313                 {
00314                         float           h= tmp.z;
00315                         // Test if it would fit in the wanted field.
00316                         if(h>pos.z+hup) continue;
00317                         if(h<pos.z-hbot)        continue;
00318 
00319                         // OK!!
00320                         if(!found)
00321                         {
00322                                 found=true;
00323                                 height=h;
00324                         }
00325                         else
00326                         {
00327                                 height= max(height,h);
00328                         }
00329                 }
00330         }
00331 
00332         if(found)
00333                 pos.z= height;
00334 
00335         return found;
00336 }

bool NL3D::CMiniCol::testMove const CVector prec,
CVector cur
 

This function test if a move is OK, by snaping it to ground, and test if angle is<45deg. If !OK, cur is set to prec, and false is returned.

Definition at line 433 of file mini_col.cpp.

References NLMISC::CVector::norm(), NLMISC::CVector::normalize(), NLMISC::Pi, and snapToGround().

00434 {
00435         CVector dir= cur-prec;
00436         dir.normalize();
00437 
00438         // Angle max.
00439         float   anglemax= 65;   // 65 degrees.
00440         anglemax= (float)tan( anglemax*Pi/180);
00441 
00442         // Must not go to near of a wall.
00443         CVector test= cur+dir*0.5;
00444         float   norm= (test-prec).norm();
00445         norm*=anglemax;
00446         if(!snapToGround(test, norm, norm))
00447         {
00448                 cur= prec;
00449                 return false;
00450         }
00451         else
00452         {
00453                 // Must test and snap the current position.
00454                 norm= (cur-prec).norm();
00455                 norm*=anglemax;
00456                 if(!snapToGround(cur, norm, norm))
00457                 {
00458                         cur= prec;
00459                         return false;
00460                 }
00461         }
00462         return true;
00463 }


Field Documentation

TGrid NL3D::CMiniCol::_Grid [private]
 

Definition at line 140 of file mini_col.h.

CRefPtr<CLandscape> NL3D::CMiniCol::_Landscape [private]
 

Definition at line 138 of file mini_col.h.

float NL3D::CMiniCol::_RadMax [private]
 

Definition at line 139 of file mini_col.h.

Referenced by CMiniCol(), init(), and setCenter().

float NL3D::CMiniCol::_RadMin [private]
 

Definition at line 139 of file mini_col.h.

Referenced by CMiniCol(), init(), and setCenter().

TZoneSet NL3D::CMiniCol::_Zones [private]
 

Definition at line 141 of file mini_col.h.

Referenced by addZone(), removeZone(), and setCenter().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 06:56:22 2004 for NeL by doxygen 1.3.6