forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			195 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
 | |
| //
 | |
| // This software is provided 'as-is', without any express or implied
 | |
| // warranty.  In no event will the authors be held liable for any damages
 | |
| // arising from the use of this software.
 | |
| // Permission is granted to anyone to use this software for any purpose,
 | |
| // including commercial applications, and to alter it and redistribute it
 | |
| // freely, subject to the following restrictions:
 | |
| // 1. The origin of this software must not be misrepresented; you must not
 | |
| //    claim that you wrote the original software. If you use this software
 | |
| //    in a product, an acknowledgment in the product documentation would be
 | |
| //    appreciated but is not required.
 | |
| // 2. Altered source versions must be plainly marked as such, and must not be
 | |
| //    misrepresented as being the original software.
 | |
| // 3. This notice may not be removed or altered from any source distribution.
 | |
| //
 | |
| 
 | |
| #include <string.h>
 | |
| #include <new>
 | |
| #include "DetourProximityGrid.h"
 | |
| #include "DetourCommon.h"
 | |
| #include "DetourMath.h"
 | |
| #include "DetourAlloc.h"
 | |
| #include "DetourAssert.h"
 | |
| 
 | |
| 
 | |
| dtProximityGrid* dtAllocProximityGrid()
 | |
| {
 | |
| 	void* mem = dtAlloc(sizeof(dtProximityGrid), DT_ALLOC_PERM);
 | |
| 	if (!mem) return 0;
 | |
| 	return new(mem) dtProximityGrid;
 | |
| }
 | |
| 
 | |
| void dtFreeProximityGrid(dtProximityGrid* ptr)
 | |
| {
 | |
| 	if (!ptr) return;
 | |
| 	ptr->~dtProximityGrid();
 | |
| 	dtFree(ptr);
 | |
| }
 | |
| 
 | |
| 
 | |
| inline int hashPos2(int x, int y, int n)
 | |
| {
 | |
| 	return ((x*73856093) ^ (y*19349663)) & (n-1);
 | |
| }
 | |
| 
 | |
| 
 | |
| dtProximityGrid::dtProximityGrid() :
 | |
| 	m_cellSize(0),
 | |
| 	m_invCellSize(0),
 | |
| 	m_pool(0),
 | |
| 	m_poolHead(0),
 | |
| 	m_poolSize(0),
 | |
| 	m_buckets(0),
 | |
| 	m_bucketsSize(0)
 | |
| {
 | |
| }
 | |
| 
 | |
| dtProximityGrid::~dtProximityGrid()
 | |
| {
 | |
| 	dtFree(m_buckets);
 | |
| 	dtFree(m_pool);
 | |
| }
 | |
| 
 | |
| bool dtProximityGrid::init(const int poolSize, const float cellSize)
 | |
| {
 | |
| 	dtAssert(poolSize > 0);
 | |
| 	dtAssert(cellSize > 0.0f);
 | |
| 	
 | |
| 	m_cellSize = cellSize;
 | |
| 	m_invCellSize = 1.0f / m_cellSize;
 | |
| 	
 | |
| 	// Allocate hashs buckets
 | |
| 	m_bucketsSize = dtNextPow2(poolSize);
 | |
| 	m_buckets = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_bucketsSize, DT_ALLOC_PERM);
 | |
| 	if (!m_buckets)
 | |
| 		return false;
 | |
| 	
 | |
| 	// Allocate pool of items.
 | |
| 	m_poolSize = poolSize;
 | |
| 	m_poolHead = 0;
 | |
| 	m_pool = (Item*)dtAlloc(sizeof(Item)*m_poolSize, DT_ALLOC_PERM);
 | |
| 	if (!m_pool)
 | |
| 		return false;
 | |
| 	
 | |
| 	clear();
 | |
| 	
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| void dtProximityGrid::clear()
 | |
| {
 | |
| 	memset(m_buckets, 0xff, sizeof(unsigned short)*m_bucketsSize);
 | |
| 	m_poolHead = 0;
 | |
| 	m_bounds[0] = 0xffff;
 | |
| 	m_bounds[1] = 0xffff;
 | |
| 	m_bounds[2] = -0xffff;
 | |
| 	m_bounds[3] = -0xffff;
 | |
| }
 | |
| 
 | |
| void dtProximityGrid::addItem(const unsigned short id,
 | |
| 							  const float minx, const float miny,
 | |
| 							  const float maxx, const float maxy)
 | |
| {
 | |
| 	const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
 | |
| 	const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
 | |
| 	const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
 | |
| 	const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
 | |
| 	
 | |
| 	m_bounds[0] = dtMin(m_bounds[0], iminx);
 | |
| 	m_bounds[1] = dtMin(m_bounds[1], iminy);
 | |
| 	m_bounds[2] = dtMax(m_bounds[2], imaxx);
 | |
| 	m_bounds[3] = dtMax(m_bounds[3], imaxy);
 | |
| 	
 | |
| 	for (int y = iminy; y <= imaxy; ++y)
 | |
| 	{
 | |
| 		for (int x = iminx; x <= imaxx; ++x)
 | |
| 		{
 | |
| 			if (m_poolHead < m_poolSize)
 | |
| 			{
 | |
| 				const int h = hashPos2(x, y, m_bucketsSize);
 | |
| 				const unsigned short idx = (unsigned short)m_poolHead;
 | |
| 				m_poolHead++;
 | |
| 				Item& item = m_pool[idx];
 | |
| 				item.x = (short)x;
 | |
| 				item.y = (short)y;
 | |
| 				item.id = id;
 | |
| 				item.next = m_buckets[h];
 | |
| 				m_buckets[h] = idx;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int dtProximityGrid::queryItems(const float minx, const float miny,
 | |
| 								const float maxx, const float maxy,
 | |
| 								unsigned short* ids, const int maxIds) const
 | |
| {
 | |
| 	const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
 | |
| 	const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
 | |
| 	const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
 | |
| 	const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
 | |
| 	
 | |
| 	int n = 0;
 | |
| 	
 | |
| 	for (int y = iminy; y <= imaxy; ++y)
 | |
| 	{
 | |
| 		for (int x = iminx; x <= imaxx; ++x)
 | |
| 		{
 | |
| 			const int h = hashPos2(x, y, m_bucketsSize);
 | |
| 			unsigned short idx = m_buckets[h];
 | |
| 			while (idx != 0xffff)
 | |
| 			{
 | |
| 				Item& item = m_pool[idx];
 | |
| 				if ((int)item.x == x && (int)item.y == y)
 | |
| 				{
 | |
| 					// Check if the id exists already.
 | |
| 					const unsigned short* end = ids + n;
 | |
| 					unsigned short* i = ids;
 | |
| 					while (i != end && *i != item.id)
 | |
| 						++i;
 | |
| 					// Item not found, add it.
 | |
| 					if (i == end)
 | |
| 					{
 | |
| 						if (n >= maxIds)
 | |
| 							return n;
 | |
| 						ids[n++] = item.id;
 | |
| 					}
 | |
| 				}
 | |
| 				idx = item.next;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| int dtProximityGrid::getItemCountAt(const int x, const int y) const
 | |
| {
 | |
| 	int n = 0;
 | |
| 	
 | |
| 	const int h = hashPos2(x, y, m_bucketsSize);
 | |
| 	unsigned short idx = m_buckets[h];
 | |
| 	while (idx != 0xffff)
 | |
| 	{
 | |
| 		Item& item = m_pool[idx];
 | |
| 		if ((int)item.x == x && (int)item.y == y)
 | |
| 			n++;
 | |
| 		idx = item.next;
 | |
| 	}
 | |
| 	
 | |
| 	return n;
 | |
| }
 |