123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- //
- // 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;
- }
|