khanat-opennel-code/code/nel/include/nel/3d/static_quad_grid.h

281 lines
6.6 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_STATIC_QUAD_GRID_H
#define NL_STATIC_QUAD_GRID_H
#include "nel/misc/common.h"
#include "nel/3d/quad_grid.h"
namespace NL3D
{
// ***************************************************************************
/**
* This class is builded from a CQuadGrid, and is to be used when:
* - sizeof(T) is small (ie a pointer)
* - no dynamic insertion are made (builded from a CQuadGrid)
* - selection is made with a point, not a BBox.
*
* Because elements are duplicated all over cells and only one cell can be selected at a time.
*
* \author Lionel Berenguier
* \author Nevrax France
* \date 2002
*/
template<class T>
class CStaticQuadGrid
{
public:
/// Constructor
CStaticQuadGrid();
/// dtor.
~CStaticQuadGrid();
/// \name Initialization
//@{
/** build from a CQuadGrid. Elements are copied, not referenced
* Elements may be duplicated in all cells they lie into.
* quadGrid selection is cleared
*/
void build(CQuadGrid<T> &quadGrid);
/** Clear all the container. Elements are deleted, and the quadgrid is erased.
*/
void clear();
//@}
/// \name Selection
//@{
/** Select elements at a given point
* Speed is in O(1), because the array of the cell is returned. NULL if size==0.
*
* \param point is the point used to select
* \param numElts number of elements returned
* \return a ptr on array of elements
*/
const T *select(const NLMISC::CVector &point, uint &numElts);
//@}
// ****************************
private:
class CQuadNode
{
public:
T *Nodes;
uint NumNodes;
CQuadNode()
{
Nodes= NULL; NumNodes=0;
}
};
private:// Atttributes.
// The big continous array of list of elements.
std::vector<T> _Elements;
std::vector<CQuadNode> _Grid;
sint _Size;
sint _SizePower;
float _EltSize;
NLMISC::CMatrix _ChangeBasis;
// return the coordinates on the grid of what include the bbox.
void selectPoint(CVector point, sint &x0, sint &y0)
{
point/= _EltSize;
x0= (sint)(floor(point.x));
y0= (sint)(floor(point.y));
x0&= _Size-1;
y0&= _Size-1;
}
};
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// Template CStaticQuadGrid implementation.
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// Init.
// ***************************************************************************
// ***************************************************************************
template<class T>
CStaticQuadGrid<T>::CStaticQuadGrid()
{
_SizePower=4;
_Size=1<<_SizePower;
_EltSize=1;
_ChangeBasis.identity();
_Grid.resize(_Size * _Size);
}
// ***************************************************************************
template<class T>
CStaticQuadGrid<T>::~CStaticQuadGrid()
{
clear();
}
// ***************************************************************************
template<class T>
void CStaticQuadGrid<T>::clear()
{
// Just clear all vectors
_Elements.clear();
_Grid.clear();
// reset
_SizePower=4;
_Size=1<<_SizePower;
_EltSize=1;
_ChangeBasis.identity();
_Grid.resize(_Size * _Size);
}
// ***************************************************************************
template<class T>
void CStaticQuadGrid<T>::build(CQuadGrid<T> &quadGrid)
{
clear();
NLMISC::contReset(_Grid);
// Copy from quadGrid, and init quads
_Size= quadGrid.getSize();
_SizePower= NLMISC::getPowerOf2(_Size);
_EltSize= quadGrid.getEltSize();
_ChangeBasis= quadGrid.getBasis();
_Grid.resize(_Size * _Size);
NLMISC::CMatrix invBasis= _ChangeBasis.inverted();
// Count number of elements per cell, and total copies of elements
uint totalDupElt= 0;
sint x,y;
for(y=0; y<_Size; y++)
{
for(x=0; x<_Size; x++)
{
// Select the center of the case
CVector pos;
pos.x= (x+0.5f)*_EltSize;
pos.y= (y+0.5f)*_EltSize;
pos.z= 0.f;
// mul by invBasis
pos= invBasis * pos;
quadGrid.select(pos, pos);
// Count elements.
uint n= 0;
typename CQuadGrid<T>::CIterator it;
for(it= quadGrid.begin(); it!=quadGrid.end(); it++)
{
n++;
}
// store.
_Grid[y*_Size + x].NumNodes= n;
totalDupElt+= n;
}
}
// Resize array copy.
_Elements.resize(totalDupElt);
// Then reparse all array, filling _Elements and setup quadNodes ptr.
uint curDupElt= 0;
for(y=0; y<_Size; y++)
{
for(x=0; x<_Size; x++)
{
// Select the center of the case
CVector pos;
pos.x= (x+0.5f)*_EltSize;
pos.y= (y+0.5f)*_EltSize;
pos.z= 0.f;
// mul by invBasis
pos= invBasis * pos;
quadGrid.select(pos, pos);
// Setup quadNode ptr.
if (curDupElt < _Elements.size())
_Grid[y*_Size + x].Nodes= &_Elements[curDupElt];
// For all elements.
typename CQuadGrid<T>::CIterator it;
for(it= quadGrid.begin(); it!=quadGrid.end(); it++)
{
// Copy elt in array.
_Elements[curDupElt]= *it;
// Next elt in array.
curDupElt++;
}
}
}
// clean up.
quadGrid.clearSelection();
}
// ***************************************************************************
template<class T>
const T *CStaticQuadGrid<T>::select(const NLMISC::CVector &pointIn, uint &numElts)
{
CVector point= _ChangeBasis * pointIn;
// Select the case.
sint x, y;
selectPoint(point, x, y);
// get ref on the selection
CQuadNode &quadNode= _Grid[y*_Size + x];
numElts= quadNode.NumNodes;
return quadNode.Nodes;
}
} // NL3D
#endif // NL_STATIC_QUAD_GRID_H
/* End of static_quad_grid.h */