NL3D::CTessFacePriorityList Class Reference

#include <tess_face_priority_list.h>


Detailed Description

This class manage a Priority list of elements, inserted with a "distance". The priority list can be shifted, so elements with new distance <=0 are pulled from the priority list.

NB: it works quite well if you have (as example) a distStep of 1, and you shift only with value of 0.01 etc.., because it manages a "Remainder system", which do the good stuff. How does it works? in essence, it is a Rolling table, with 1+ shift back when necessary (maybe not at each shift()).

Additionally, it includes a "2D quadrant" notion. If you use this class to know when the "camera" enters a specific area, then Quadrants help you because the notion of direction is kept. Only the XY plane is used here.

Instead, if you use this class to know when the "camera" leaves a specific area, then the quadrant notion is not interesting since the camera can leave the area in any direction...

Author:
Lionel Berenguier

Nevrax France

Date:
2001

Definition at line 112 of file tess_face_priority_list.h.

Public Member Functions

void clear ()
 CTessFacePriorityList ()
 Constructor.

const NLMISC::CVectorgetQuadrantDirection (uint quadrantId) const
void init (float distStep, uint numEntries, float distMaxMod, uint numQuadrant)
void insert (uint quadrantId, float distance, CTessFace *value)
uint selectQuadrant (const NLMISC::CVector &direction)
void shift (const NLMISC::CVector &direction, CTessFacePListNode &pulledElements)
void shiftAll (CTessFacePListNode &pulledElements)
 ~CTessFacePriorityList ()

Private Attributes

uint _EntryModStart
uint _MaskEntries
uint _MaskQuadrant
uint _NEntries
uint _NumQuadrant
float _OODistStep
uint _QuarterQuadrantEnd [4]
uint _QuarterQuadrantStart [4]
float _Remainder
The rolling tables
std::vector< CRollingTable_RollingTables


Constructor & Destructor Documentation

NL3D::CTessFacePriorityList::CTessFacePriorityList  ) 
 

Constructor.

Definition at line 134 of file tess_face_priority_list.cpp.

References _EntryModStart, _MaskEntries, _NEntries, _NumQuadrant, and _OODistStep.

00135 {
00136         _OODistStep= 1;
00137         _NEntries= 0;
00138         _MaskEntries= 0;
00139         _EntryModStart= 0;
00140         _NumQuadrant= 0;
00141 }

NL3D::CTessFacePriorityList::~CTessFacePriorityList  ) 
 

Definition at line 144 of file tess_face_priority_list.cpp.

References clear().

00145 {
00146         clear();
00147 }


Member Function Documentation

void NL3D::CTessFacePriorityList::clear  ) 
 

Clear the priority list. All elements are removed. NB: for convenience, the remainder is reset.

Definition at line 201 of file tess_face_priority_list.cpp.

References _RollingTables.

Referenced by init(), and ~CTessFacePriorityList().

00202 {
00203         // just clear all the rolling tables.
00204         _RollingTables.clear();
00205 }

const NLMISC::CVector& NL3D::CTessFacePriorityList::getQuadrantDirection uint  quadrantId  )  const [inline]
 

get the quadrant dir associated to the Id. Undefined if 0.

Definition at line 145 of file tess_face_priority_list.h.

References _RollingTables, and uint.

Referenced by NL3D::CTessFace::updateRefineSplit().

00145 {return _RollingTables[quadrantId].QuadrantDirection;}

void NL3D::CTessFacePriorityList::init float  distStep,
uint  numEntries,
float  distMaxMod,
uint  numQuadrant
 

Clear and Init the priority list. It reserve (numQuadrants+1) Rolling table of numEntries entries.

Parameters:
numEntries gives the number of entries and MUST be powerOf2. distMax= numEntries*distStep distMaxMod is important for performance and MUST be < 1. eg: distMaxMod= 0.8. It is a trick to avoid the "Too Far Priority problem". Imagine you have a setup such distMax= 1000, and you insert(1100, an element). If we clamp to the max, it may be a bad thing, because ALL elements inserted after 1000 will be poped in one shift(), after 1000 shift(1) for example. To avoid this, if distMaxMod==0.8, then insert(1050) will really insert at 850, so elements will be poped not as the same time (for the extra cost of some elements get poped too early...).
numQuadrant set 0 if don't want to support quadrant notion. else set >=4 and a power of 2 (else nlassert)

Definition at line 150 of file tess_face_priority_list.cpp.

References _EntryModStart, _MaskEntries, _MaskQuadrant, _NEntries, _NumQuadrant, _OODistStep, _QuarterQuadrantEnd, _QuarterQuadrantStart, _RollingTables, NLMISC::clamp(), clear(), NLMISC::CMatrix::getJ(), NLMISC::isPowerOf2(), nlassert, NLMISC::Pi, NLMISC::CMatrix::rotateZ(), and uint.

Referenced by NL3D::CLandscape::CLandscape().

00151 {
00152         uint i;
00153         nlassert(distStep>0);
00154         nlassert(numEntries>0 && isPowerOf2(numEntries));
00155         nlassert(distMaxMod<1);
00156         nlassert(numQuadrant==0 || (numQuadrant>=4 && isPowerOf2(numQuadrant)) );
00157 
00158         // clear the prioriy list before.
00159         clear();
00160 
00161         // setup
00162         _OODistStep= 1.0f / distStep;
00163         _NEntries= numEntries;
00164         _MaskEntries= _NEntries-1;
00165         _EntryModStart= (uint)ceil(distMaxMod * _NEntries);
00166         NLMISC::clamp(_EntryModStart, 0U, _NEntries-1);
00167         _NumQuadrant= numQuadrant;
00168 
00169         // Build the Rolling tables.
00170         _RollingTables.resize(1+_NumQuadrant);
00171         for(i=0;i<_RollingTables.size();i++)
00172         {
00173                 _RollingTables[i].init(_NEntries);
00174                 // setup the quadrant direction. NB: 0 not used since "Direction less rolling table"
00175                 if(i>=1)
00176                 {
00177                         uint    idx= i-1;
00178                         // split evenly the plane with direction.
00179                         float   angle= float(2*Pi*idx)/_NumQuadrant;
00180                         CMatrix mat;
00181                         mat.rotateZ(angle);
00182                         // setup the vector
00183                         _RollingTables[i].QuadrantDirection= mat.getJ();
00184                 }
00185         }
00186 
00187         // Build Quarter Selection. In is in CCW order. Out: see selectQuadrant()
00188         const   uint    quarterLut[4]= {1,3,2,0};
00189         _MaskQuadrant= _NumQuadrant-1;
00190         for(i=0;i<4;i++)
00191         {
00192                 // Re-Order for faster ASM acces. see selectQuadrant()
00193                 uint    idx= quarterLut[i];
00194                 _QuarterQuadrantStart[idx]= i*_NumQuadrant/4;
00195                 _QuarterQuadrantEnd[idx]= 1+ (i+1)*_NumQuadrant/4;
00196         }
00197 
00198 }

void NL3D::CTessFacePriorityList::insert uint  quadrantId,
float  distance,
CTessFace value
 

Insert an element at a given distance, and in a given quadrant. Insert at the closest step. eg insert(1.2, elt) will insert elt at entry 1 (assuming distStep==1 here). Special case: if distance<=0, it is ensured that at each shift(), the element will be pulled. NB: manage correctly the entry where it is inserted, according to the Remainder system.

USE OptFastFloor if distance>0 => MUST be enclosed in OptFastFloorBegin/OptFastFloorEnd()

Parameters:
quadrantId set 0 if you want to insert in the "direction less" rolling table. else set the value returned by selectQuadrant()
distance if quadrantId==0, distance should be the norm()-SphereSize, else it shoudl be direction*quadrantDirection-SphereSize.

Definition at line 273 of file tess_face_priority_list.cpp.

References _EntryModStart, _MaskEntries, _NEntries, _OODistStep, _RollingTables, NL3D::CTessFacePriorityList::CRollingTable::insertInRollTable(), nlassert, NLMISC::OptFastFloor(), NL3D::CTessFacePriorityList::CRollingTable::Remainder, sint, uint, and value.

Referenced by NL3D::CTessFace::doMerge(), NL3D::CTessFace::split(), NL3D::CTessFace::splitRectangular(), NL3D::CTessFace::updateRefineMerge(), and NL3D::CTessFace::updateRefineSplit().

00274 {
00275         // plist must be inited.
00276         nlassert(_NEntries>0 && quadrantId<_RollingTables.size());
00277 
00278         // First, setup in our basis.
00279         distance*= _OODistStep;
00280 
00281         // Insert int the good quadrant
00282         CRollingTable   &rollTable= _RollingTables[quadrantId];
00283 
00284         // Then, look where we must insert it.
00285         sint    idInsert;
00286         if(distance<=0)
00287                 idInsert= 0;
00288         else
00289         {
00290                 // Must insert so we can't miss it when a shift occurs (=> floor).
00291                 idInsert= NLMISC::OptFastFloor(distance + rollTable.Remainder);
00292         }
00293         idInsert= std::max(0, idInsert);
00294 
00295         // Manage Mod.
00296         // If the element to insert must be inserted at  distance > distMax.
00297         if(idInsert>(sint)_MaskEntries)
00298         {
00299                 // Compute number of entries to apply the mod.
00300                 uint    nMod= _NEntries - _EntryModStart;
00301                 // Of how many entries are we too far.
00302                 idInsert= idInsert - _MaskEntries;
00303                 // Then loop in the interval [_EntryModStart, _NEntries[.
00304                 idInsert= idInsert % nMod;
00305                 idInsert= _EntryModStart + idInsert;
00306         }
00307 
00308         // insert in the Roll Table.
00309         rollTable.insertInRollTable(idInsert, value);
00310 }

uint NL3D::CTessFacePriorityList::selectQuadrant const NLMISC::CVector direction  ) 
 

prior to insert an element with a direction notion, select which quadrant according to the direction Camera -> center of interest.

Returns:
0 if no quadrant available, else the quadrant id

Definition at line 209 of file tess_face_priority_list.cpp.

References _MaskQuadrant, _NumQuadrant, _QuarterQuadrantEnd, _QuarterQuadrantStart, _RollingTables, uint, NLMISC::CVector::x, and NLMISC::CVector::y.

Referenced by NL3D::CTessFace::updateRefineSplit().

00210 {
00211         // if numQuadrants=0, ret 0.
00212         if(_NumQuadrant==0)
00213                 return 0;
00214 
00215 
00216         // select the quarter.
00217         uint    quarterId;
00218 #ifdef  NL_OS_WINDOWS
00219         __asm
00220         {
00221                 mov             esi, direction
00222                 mov             eax, [esi]direction.y
00223                 mov             ebx, [esi]direction.x
00224                 // read the sign
00225                 and             eax, 0x80000000
00226                 and             ebx, 0x80000000
00227                 // set the bit
00228                 shr             eax, 30
00229                 shr             ebx, 31
00230                 // assemble
00231                 or              eax, ebx
00232                 mov             quarterId, eax
00233         }
00234 #else
00235         if(direction.y>0)
00236         {
00237                 if(direction.x>0)       quarterId= 0;
00238                 else                            quarterId= 1;
00239         }
00240         else
00241         {
00242                 if(direction.x>0)       quarterId= 2;
00243                 else                            quarterId= 3;
00244         }
00245 #endif
00246 
00247         // Run only the quadrants of the associated quarter.
00248         uint    quadrantStart= _QuarterQuadrantStart[quarterId];
00249         uint    quadrantEnd= _QuarterQuadrantEnd[quarterId];
00250 
00251 
00252         // For all quadrants of the quarter, return the best direction
00253         float   bestDirPs= -FLT_MAX;
00254         uint    bestQuadrant= 0;
00255         for(uint i=quadrantStart;i<quadrantEnd;i++)
00256         {
00257                 // get the quadrant Id. Must mask for last (0). And Start at 1 in the _RollingTables.
00258                 uint    quadrantId= (i&_MaskQuadrant)+1;
00259                 // Test with this quadrant
00260                 float   ps= direction*_RollingTables[i].QuadrantDirection;
00261                 if(ps>bestDirPs)
00262                 {
00263                         bestDirPs= ps;
00264                         bestQuadrant= i;
00265                 }
00266         }
00267 
00268         return bestQuadrant;
00269 }

void NL3D::CTessFacePriorityList::shift const NLMISC::CVector direction,
CTessFacePListNode pulledElements
 

Shift the Priority list in a given direction. NB: for each rolling table, even if shiftDistance==0, all elements in the entry 0 are pulled out. pulledElements is the root of the list which will contains elements pulled from the list.

Definition at line 314 of file tess_face_priority_list.cpp.

References _NEntries, _OODistStep, _RollingTables, NL3D::CTessFacePListNode::appendPList(), NL3D::CTessFacePriorityList::CRollingTable::getRollTableEntry(), nlassert, NLMISC::CVector::norm(), NL3D::CTessFacePriorityList::CRollingTable::QuadrantDirection, NL3D::CTessFacePriorityList::CRollingTable::Remainder, NL3D::CTessFacePriorityList::CRollingTable::shiftEntries(), uint, and NL3D::CTessFacePListNode::unlinkInPList().

Referenced by NL3D::CLandscape::refine().

00315 {
00316         // plist must be inited.
00317         nlassert(_NEntries>0);
00318 
00319         pulledElements.unlinkInPList();
00320 
00321         // Shift all the rolling tables
00322         for(uint i=0;i<_RollingTables.size();i++)
00323         {
00324                 CRollingTable   &rollTable= _RollingTables[i];
00325                 float   shiftDistance;
00326 
00327                 // if quadrant 0, Direction less => get distance with Euler norm.
00328                 if(i==0)
00329                 {
00330                         shiftDistance= direction.norm();
00331                 }
00332                 // Else compute the effective distance we run to the plane.
00333                 else
00334                 {
00335                         shiftDistance= direction*rollTable.QuadrantDirection;
00336                         // For now, just clamp, but may be interesting to shift Back the rolling table !!
00337                         shiftDistance= max(0.f, shiftDistance);
00338                 }
00339 
00340                 // First, setup in our basis.
00341                 shiftDistance*= _OODistStep;
00342 
00343                 // at least, fill OUT with elements of entry 0.
00344                 // For all elements of the entry 0 of , pull them, and insert in result list.
00345                 pulledElements.appendPList(rollTable.getRollTableEntry(0));
00346 
00347                 // shift.
00348                 rollTable.Remainder+= shiftDistance;
00349                 // If Remainder>=1, it means that we must shift the rolling table, and get elements deleted.
00350                 uint    entryShift= (uint)floor(rollTable.Remainder);
00351                 rollTable.Remainder= rollTable.Remainder - entryShift;
00352 
00353                 // shift full array??
00354                 if( entryShift >= _NEntries)
00355                 {
00356                         entryShift= _NEntries;
00357                         // The entire array is pulled, _Remainder should get a good value.
00358                         rollTable.Remainder= 0;
00359                 }
00360 
00361                 // If some real shift, do it.
00362                 rollTable.shiftEntries(entryShift, pulledElements);
00363         }
00364 }

void NL3D::CTessFacePriorityList::shiftAll CTessFacePListNode pulledElements  ) 
 

Same as shift(), but shift all the array.

Definition at line 368 of file tess_face_priority_list.cpp.

References _NEntries, _RollingTables, nlassert, uint, and NL3D::CTessFacePListNode::unlinkInPList().

Referenced by NL3D::CLandscape::refine().

00369 {
00370         // plist must be inited.
00371         nlassert(_NEntries>0);
00372 
00373         pulledElements.unlinkInPList();
00374 
00375         // Do it for all rolling tables.
00376         for(uint i=0;i<_RollingTables.size();i++)
00377         {
00378                 // The entire array is pulled, _Remainder should get a good value.
00379                 uint entryShift= _NEntries;
00380                 _RollingTables[i].Remainder= 0;
00381 
00382                 // shift the entire array.
00383                 _RollingTables[i].shiftEntries(entryShift, pulledElements);
00384         }
00385 }


Field Documentation

uint NL3D::CTessFacePriorityList::_EntryModStart [private]
 

Definition at line 187 of file tess_face_priority_list.h.

Referenced by CTessFacePriorityList(), init(), and insert().

uint NL3D::CTessFacePriorityList::_MaskEntries [private]
 

Definition at line 186 of file tess_face_priority_list.h.

Referenced by CTessFacePriorityList(), init(), and insert().

uint NL3D::CTessFacePriorityList::_MaskQuadrant [private]
 

Definition at line 190 of file tess_face_priority_list.h.

Referenced by init(), and selectQuadrant().

uint NL3D::CTessFacePriorityList::_NEntries [private]
 

Definition at line 185 of file tess_face_priority_list.h.

Referenced by CTessFacePriorityList(), init(), insert(), shift(), and shiftAll().

uint NL3D::CTessFacePriorityList::_NumQuadrant [private]
 

Definition at line 188 of file tess_face_priority_list.h.

Referenced by CTessFacePriorityList(), init(), and selectQuadrant().

float NL3D::CTessFacePriorityList::_OODistStep [private]
 

Definition at line 184 of file tess_face_priority_list.h.

Referenced by CTessFacePriorityList(), init(), insert(), and shift().

uint NL3D::CTessFacePriorityList::_QuarterQuadrantEnd[4] [private]
 

Definition at line 192 of file tess_face_priority_list.h.

Referenced by init(), and selectQuadrant().

uint NL3D::CTessFacePriorityList::_QuarterQuadrantStart[4] [private]
 

Definition at line 191 of file tess_face_priority_list.h.

Referenced by init(), and selectQuadrant().

float NL3D::CTessFacePriorityList::_Remainder [private]
 

Definition at line 183 of file tess_face_priority_list.h.

std::vector<CRollingTable> NL3D::CTessFacePriorityList::_RollingTables [private]
 

Definition at line 243 of file tess_face_priority_list.h.

Referenced by clear(), getQuadrantDirection(), init(), insert(), selectQuadrant(), shift(), and shiftAll().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 07:48:49 2004 for NeL by doxygen 1.3.6