1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef RYAI_ENTITY_MATRIX_H
20 #define RYAI_ENTITY_MATRIX_H
22 #include "nel/misc/types_nl.h"
23 #include "nel/misc/common.h"
24 #include "nel/misc/debug.h"
25 #include "nel/misc/command.h"
31 #include "ai_share/ai_entity_physical_list_link.h"
34 //--------------------------------------------------------------------------
35 // The CAIEntityMatrixIteratorTblLinear class
36 //--------------------------------------------------------------------------
37 // This class uses a vector of horizontal run lengths to represent
38 // the aea to be scanned.
39 // The form represented by the data is assumed to be symetrical in both x and y.
40 // Linear tables use a better RAM access patern than random access tables
41 // and should be used whenever possible
43 class CAIEntityMatrixIteratorTblLinear
49 STblEntry(uint32 runLength
, sint32 previousRunLength
)
51 RunLength
=(uint16
)(runLength
-1); // we assume all runs are at least 1 unit long - this is the excess
52 StartDx
=(sint16
)(-(previousRunLength
/2)-(((sint32
)runLength
)/2));
55 nlassert(runLength
>0); // runs must be at least 1 unit long
56 nlassert(runLength
<32768); // this is the limit where StartDx runs out of bits
57 nlassert(previousRunLength
>=0);
58 nlassert(previousRunLength
<32768);
65 typedef std::vector
<STblEntry
> TTbl
;
66 typedef TTbl::iterator iterator
;
68 inline CAIEntityMatrixIteratorTblLinear();
69 inline CAIEntityMatrixIteratorTblLinear(uint32
*runLengths
,uint32 count
);
71 inline void push_back(uint32 runLength
, sint32 previousRunLength
);
72 inline const STblEntry
&operator[](uint32 idx
) const;
73 inline const iterator
begin() const;
74 inline const iterator
end() const;
75 inline uint32
size() const;
82 //--------------------------------------------------------------------------
83 // The CAIEntityMatrixIteratorTblRandom class
84 //--------------------------------------------------------------------------
85 // This class uses a vector of xy offsets to apply to the 'read position' ptr
86 // as it iterates across the grid.
87 // The first xy offset is applied at initalisation time in order to allow for
88 // the use of tables that do not scan the '0,0' cell.
89 // These tables use a less efficient RAM access pattern than Linear tables but
90 // benefit from a higher degree of control over the area scanned and the order
93 class CAIEntityMatrixIteratorTblRandom
99 STblEntry(sint32 dxdy
) { dxdy
=dxdy
; }
100 STblEntry(sint16 dx
, sint16 dy
) { dx
=dx
; dy
=dy
; }
103 struct { sint16 dx
, dy
; };
107 typedef std::vector
<STblEntry
> TTbl
;
108 typedef TTbl::iterator iterator
;
110 inline CAIEntityMatrixIteratorTblRandom();
112 inline void push_back(sint16 dx
,sint16 dy
);
113 inline const STblEntry
&operator[](uint32 idx
) const;
114 inline const iterator
begin() const;
115 inline const iterator
end() const;
116 inline uint32
size() const;
123 //--------------------------------------------------------------------------
124 // The CAIEntityMatrix class
125 //--------------------------------------------------------------------------
128 class CAIEntityMatrix
:
129 public NLMISC::CDbgRefCount
<CAIEntityMatrix
<T
> >
133 -----------------------------------------------------------------------------------------------------
134 class CAIEntityMatrix<T>::CCellTblIteratorRandom
136 This class provides an iterator for iterating across the cells of a matrix '_matrix' following the
137 pattern described by a cell iteration table '_tbl'
139 An iterator '_it' refferences the current position in '_tbl'
141 A compact coordinate pair '_xy' reffernces the current position in '_matrix'
142 Note that because the matrix super imposes coordinates with the same low byte, the upper bytes of
143 the '_xy' coordinates is needed for position proximity tests
144 -----------------------------------------------------------------------------------------------------
146 class CCellTblIteratorRandom
150 inline CCellTblIteratorRandom():
151 _matrix(NULL
), _tbl(NULL
), _x(0), _y(0)
155 inline CCellTblIteratorRandom(const CAIEntityMatrix
<T
> *matrix
,const CAIEntityMatrixIteratorTblRandom
*tbl
,const CAIVector
&pos
):
156 _matrix(matrix
), _tbl(tbl
), _x((uint16
)pos
.x().asInt16Meters()), _y((uint16
)pos
.y().asInt16Meters())
159 // apply the first entry in the iterator table in order to setup the start position correctly
163 inline const CEntityListLink
<T
> * operator*() const
165 const typename CAIEntityMatrix
<T
>::SMatrixLine
&line
=(*_matrix
)[_yl
];
166 const CEntityListLink
<T
> &cellEntityListLink
=line
[_xl
];
167 return &cellEntityListLink
;
170 inline const CCellTblIteratorRandom
&operator++()
173 // make sure we aren't trying to access an uninitialised iterator
174 nlassert(_it
!=_tbl
->end());
184 inline const CCellTblIteratorRandom
&operator=(const CCellTblIteratorRandom
&other
)
187 _matrix
= other
._matrix
;
194 inline bool end() const
196 return _it
==_tbl
->end();
199 inline const uint32
&xy() const { return _xy
; }
200 inline const uint16
&x() const { return _x
; }
201 inline const uint16
&y() const { return _y
; }
202 inline const uint8
&xl() const { return _xl
; }
203 inline const uint8
&xh() const { return _xh
; }
204 inline const uint8
&yl() const { return _yl
; }
205 inline const uint8
&yh() const { return _yh
; }
207 inline const CAIEntityMatrix
<T
> *matrix() const
216 struct { uint16 _x
, _y
; };
217 struct { uint8 _xl
, _xh
, _yl
, _yh
; };
219 const CAIEntityMatrix
<T
> *_matrix
;
220 const CAIEntityMatrixIteratorTblRandom
*_tbl
;
221 CAIEntityMatrixIteratorTblRandom::iterator _it
;
225 -----------------------------------------------------------------------------------------------------
226 class CAIEntityMatrix<T>::CCellTblIteratorLinear
228 This class provides an iterator for iterating across the cells of a matrix '_matrix' following the
229 pattern described by a cell iteration table '_tbl'
231 An iterator '_it' refferences the current position in '_tbl'
232 The _runLengthRemaining property is setup each time the iterator _it is advanced by the ++operator.
233 Subsequent calls to operator++() will only increment _it if _runLengthRemaining==0
235 A compact coordinate pair '_xy' reffernces the current position in '_matrix'
236 Note that because the matrix super imposes coordinates with the same low byte, the upper bytes of
237 the '_xy' coordinates is needed for position proximity tests
238 -----------------------------------------------------------------------------------------------------
240 class CCellTblIteratorLinear
243 inline CCellTblIteratorLinear():
244 _x(0), _y(0), _matrix(NULL
), _tbl(NULL
), _runLengthRemaining(0)
248 inline CCellTblIteratorLinear(const CAIEntityMatrix
<T
> *matrix
,const CAIEntityMatrixIteratorTblLinear
*tbl
,const CAIVector
&pos
):
249 _x((uint16
)pos
.x().asInt16Meters()), _y((uint16
)pos
.y().asInt16Meters()), _matrix(matrix
), _tbl(tbl
)
252 nlassert(_tbl
!=NULL
);
253 nlassert(_tbl
->size()>0);
254 nlassert(_tbl
->size()<32768); // a numeric over-run limit
255 nlassert(_matrix
!=NULL
);
258 // setup the iterator to point to the strat of the iterator table and setup properties accordingly
260 _runLengthRemaining
=(*_tbl
)[0].RunLength
;
261 _x
-=(sint16
)(_runLengthRemaining
/2);
262 _y
-=(sint16
)(_tbl
->size()/2);
265 inline const CEntityListLink
<T
> *operator*() const
267 return &(*_matrix
)[_yl
][_xl
];
270 inline const CCellTblIteratorLinear
&operator++()
273 // make sure we aren't trying to access an uninitialised iterator
274 nlassert(_it
!=_tbl
->end());
277 // if we're not at the end of the current run continue run else move on to next line
278 if (_runLengthRemaining
!=0)
280 --_runLengthRemaining
;
286 if (_it
==_tbl
->end())
289 _runLengthRemaining
=(*_it
).RunLength
;
297 inline const CCellTblIteratorLinear
&operator=(const CCellTblIteratorLinear
&other
)
300 _matrix
= other
._matrix
;
303 _runLengthRemaining
= other
._runLengthRemaining
;
308 inline bool end() const
310 return _it
==_tbl
->end();
313 inline const uint32
&xy() const { return _xy
; }
314 inline const uint16
&x() const { return _x
; }
315 inline const uint16
&y() const { return _y
; }
316 inline const uint8
&xl() const { return _xl
; }
317 inline const uint8
&xh() const { return _xh
; }
318 inline const uint8
&yl() const { return _yl
; }
319 inline const uint8
&yh() const { return _yh
; }
321 inline const CAIEntityMatrix
<T
> *matrix() const
330 struct { uint16 _x
, _y
; };
331 struct { uint8 _xl
, _xh
, _yl
, _yh
; };
333 const CAIEntityMatrix
<T
> *_matrix
;
334 const CAIEntityMatrixIteratorTblLinear
*_tbl
;
335 CAIEntityMatrixIteratorTblLinear::iterator _it
;
336 uint32 _runLengthRemaining
;
340 -----------------------------------------------------------------------------------------------------
341 class CAIEntityMatrix<T>::CEntityIteratorTemplate
342 class CAIEntityMatrix<T>::CEntityIteratorLinear
343 class CAIEntityMatrix<T>::CEntityIteratorRandom
345 This class provides an iterator for iterating across the entities listed in the cells of a matrix
346 '_matrix' following the pattern described by a cell iteration table '_tbl'
348 The class is composed of a CCellTblIteratorLinear '_cellIt' responsible for iterating across the matrix
349 and an entity pointer '_entity' used for iterating over the entities in each matrix cell
351 Note that unlinking, moving or deleting the entity refferenced by a CEntityIteratorLinear iterator
353 -----------------------------------------------------------------------------------------------------
356 template <class CIt
,class CTbl
>
357 class CEntityIteratorTemplate
361 inline CEntityIteratorTemplate() : _cellIt()
366 inline CEntityIteratorTemplate(const CAIEntityMatrix
<T
> *matrix
,const CTbl
*tbl
,const CAIVector
&pos
) : _cellIt(matrix
,tbl
,pos
)
368 // get a pointer to the list link for the first entity in the cell
369 // _entity=(*_cellIt)->next();
374 // if the cell is empty then start iterating to find a non-empty cell
375 // if (_entity->unlinked())
379 inline CEntityIteratorTemplate(const CAIEntityMatrix
<T
> *matrix
,const CTbl
*tbl
,const T
*entity
) : _cellIt(matrix
,tbl
,entity
->pos())
381 // get a poniter to the list link for the first entity in the same cell as the given entity
382 // _entity=(*_cellIt)->next();
388 inline T
&operator*()
391 // make sure we aren't trying to access passed the end of list
395 return *NLMISC::safe_cast
<T
*>(_entity
->entity());
398 inline const CEntityIteratorTemplate
&operator++()
402 // if you are on a breakpoint here it is because you've tried to do a ++ on an iterator
403 // that has reached its end marker
404 nlassert(!_cellIt
.end());
406 // make sure the entity is in the cell that the iterator reffers to
407 // if you are on a breakpoint here it is because you've moved or removed an entity
408 // and have invalidated this iterator
409 // nlassert(_entity->xyCellAsInt()==_cellIt.xy());
411 // repeat the following loop until either we come to the end of the cell iterator or we find an entity with
412 // xy coords that match our own
415 // try to get the next entity in the cell
416 _entity
=_entity
->next();
417 if (_entity
==*_cellIt
)
419 // we're at the end of the entity list for this cell so try to find another cell with a valid entity
424 while ( !_cellIt
.end()
425 && (*_cellIt
)->unlinked());
429 _entity
=(*_cellIt
)->next();
433 while ( !_cellIt
.end()
434 && ( _entity
->unlinked()
435 || !_entity
->entity()->isAt16MetersPos(_cellIt
.x(),_cellIt
.y())) );
436 // as cells are tiled over the world, we need to check if our entity have a real good match with the scanned position.
440 inline const CEntityIteratorTemplate
<CIt
,CTbl
> &operator=(const CEntityIteratorTemplate
<CIt
,CTbl
> & other
)
442 _cellIt
= other
._cellIt
;
443 _entity
= other
._entity
;
447 // method for testing iterator for end of current sequence
450 // the following can only happen if there are no more entites in cell and no more deltas in cell iterator tbl
451 return _cellIt
.end();
455 CIt _cellIt
; // the cell iterator
456 const CEntityListLink
<T
> *_entity
; // which entity are we pointing at (within the cell)
459 typedef CEntityIteratorTemplate
<CCellTblIteratorLinear
,CAIEntityMatrixIteratorTblLinear
> CEntityIteratorLinear
;
460 typedef CEntityIteratorTemplate
<CCellTblIteratorRandom
,CAIEntityMatrixIteratorTblRandom
> CEntityIteratorRandom
;
464 -----------------------------------------------------------------------------------------------------
465 class CAIEntityMatrix<T>::SMatrixLine
467 The class used to represent a matrix row
468 -----------------------------------------------------------------------------------------------------
474 CEntityListLink
<T
> Line
[256];
476 // one and only accessor
477 inline CEntityListLink
<T
> &operator[](uint8 x
) const { return const_cast<CEntityListLink
<T
> &>(Line
[x
]); }
481 -----------------------------------------------------------------------------------------------------
482 class CAIEntityMatrix methods
483 -----------------------------------------------------------------------------------------------------
488 inline CAIEntityMatrix();
490 // table lookup operator - should be used as myMatrix[y][x]
491 inline SMatrixLine
&operator[](uint8 y
) const;
493 // methods for initialising iterators
494 inline const typename CAIEntityMatrix
<T
>::CCellTblIteratorRandom
beginCells(const CAIEntityMatrixIteratorTblRandom
*tbl
,const CAIVector
&pos
) const;
495 inline const typename CAIEntityMatrix
<T
>::CEntityIteratorRandom
beginEntities(const CAIEntityMatrixIteratorTblRandom
*tbl
,const CAIVector
&pos
) const;
497 inline const typename CAIEntityMatrix
<T
>::CCellTblIteratorLinear
beginCells(const CAIEntityMatrixIteratorTblLinear
*tbl
,const CAIVector
&pos
) const;
498 inline const typename CAIEntityMatrix
<T
>::CEntityIteratorLinear
beginEntities(const CAIEntityMatrixIteratorTblLinear
*tbl
,const CAIVector
&pos
) const;
503 -----------------------------------------------------------------------------------------------------
504 class CAIEntityMatrix data
505 -----------------------------------------------------------------------------------------------------
508 SMatrixLine _matrix
[256];
511 //--------------------------------------------------------------------------
512 // The CAIEntityMatrix inlines
513 //--------------------------------------------------------------------------
515 inline CAIEntityMatrix
<T
>::CAIEntityMatrix()
520 inline typename CAIEntityMatrix
<T
>::SMatrixLine
&CAIEntityMatrix
<T
>::operator[](uint8 y
) const
522 return const_cast<typename CAIEntityMatrix
<T
>::SMatrixLine
&>(_matrix
[y
]);
526 inline const typename CAIEntityMatrix
<T
>::CCellTblIteratorRandom CAIEntityMatrix
<T
>::beginCells(const CAIEntityMatrixIteratorTblRandom
*tbl
, const CAIVector
&pos
) const
528 return CCellTblIteratorRandom(this,tbl
,pos
);
532 inline const typename CAIEntityMatrix
<T
>::CEntityIteratorRandom CAIEntityMatrix
<T
>::beginEntities(const CAIEntityMatrixIteratorTblRandom
*tbl
, const CAIVector
&pos
) const
534 CEntityIteratorRandom
newIt(this,tbl
,pos
);
539 inline const typename CAIEntityMatrix
<T
>::CCellTblIteratorLinear CAIEntityMatrix
<T
>::beginCells(const CAIEntityMatrixIteratorTblLinear
*tbl
, const CAIVector
&pos
) const
541 return CCellTblIteratorLinear(this,tbl
,pos
);
545 inline const typename CAIEntityMatrix
<T
>::CEntityIteratorLinear CAIEntityMatrix
<T
>::beginEntities(const CAIEntityMatrixIteratorTblLinear
*tbl
, const CAIVector
&pos
) const
547 CEntityIteratorLinear
newIt(this,tbl
,pos
);
552 //--------------------------------------------------------------------------
553 // The CAIEntityMatrixIteratorTblRandom inlines
554 //--------------------------------------------------------------------------
556 inline CAIEntityMatrixIteratorTblRandom::CAIEntityMatrixIteratorTblRandom()
560 inline void CAIEntityMatrixIteratorTblRandom::push_back(sint16 dx
,sint16 dy
)
562 _tbl
.push_back(CAIEntityMatrixIteratorTblRandom::STblEntry(dx
,dy
));
565 inline const CAIEntityMatrixIteratorTblRandom::STblEntry
&CAIEntityMatrixIteratorTblRandom::operator[](uint32 idx
) const
568 nlassert(idx
<_tbl
.size());
574 inline const CAIEntityMatrixIteratorTblRandom::iterator
CAIEntityMatrixIteratorTblRandom::begin() const
576 return const_cast<TTbl
&>(_tbl
).begin();
579 inline const CAIEntityMatrixIteratorTblRandom::iterator
CAIEntityMatrixIteratorTblRandom::end() const
581 return const_cast<TTbl
&>(_tbl
).end();
584 inline uint32
CAIEntityMatrixIteratorTblRandom::size() const
586 return (uint32
)_tbl
.size();
590 //--------------------------------------------------------------------------
591 // The CAIEntityMatrixIteratorTblLinear inlines
592 //--------------------------------------------------------------------------
594 inline CAIEntityMatrixIteratorTblLinear::CAIEntityMatrixIteratorTblLinear()
598 inline CAIEntityMatrixIteratorTblLinear::CAIEntityMatrixIteratorTblLinear(uint32
*runLengths
,uint32 count
)
601 for(uint i
=0;i
<count
;++i
)
603 push_back(runLengths
[i
],lastRun
);
604 lastRun
=runLengths
[i
];
608 inline void CAIEntityMatrixIteratorTblLinear::push_back(uint32 runLength
, sint32 previousRunLength
)
610 _tbl
.push_back(CAIEntityMatrixIteratorTblLinear::STblEntry(runLength
,previousRunLength
));
613 inline const CAIEntityMatrixIteratorTblLinear::STblEntry
&CAIEntityMatrixIteratorTblLinear::operator[](uint32 idx
) const
616 nlassert(idx
<_tbl
.size());
622 inline const CAIEntityMatrixIteratorTblLinear::iterator
CAIEntityMatrixIteratorTblLinear::begin() const
624 return const_cast<TTbl
&>(_tbl
).begin();
627 inline const CAIEntityMatrixIteratorTblLinear::iterator
CAIEntityMatrixIteratorTblLinear::end() const
629 return const_cast<TTbl
&>(_tbl
).end();
632 inline uint32
CAIEntityMatrixIteratorTblLinear::size() const
634 return (uint32
)_tbl
.size();
638 //--------------------------------------------------------------------------