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;
			}
		}
	}
}
Ejemplo n.º 2
0
void dtNavMesh::queryTiles(const float bmin[3], const float bmax[3], dtTileCallback callback, void * userdata) const 
{
	const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / m_tileWidth);
	const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / m_tileWidth);
	const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / m_tileHeight);
	const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / m_tileHeight);

	for (int ty = ty0; ty <= ty1; ++ty)
	{
		for (int tx = tx0; tx <= tx1; ++tx)
		{
			enum { MaxTiles = 32 };
			const dtMeshTile * tmpTiles[ MaxTiles ];

			const int ntiles = getTilesAt(tx,ty,tmpTiles,MaxTiles);
			for (int i = 0; i < ntiles; ++i)
			{
				if (dtOverlapBounds(bmin,bmax, tmpTiles[ i ]->header->bmin, tmpTiles[ i ]->header->bmax))
				{
					callback( tmpTiles[i], userdata );
				}
			}
		}
	}
}
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;
}
dtStatus dtTileCache::queryTiles(const float* bmin, const float* bmax,
								 dtCompressedTileRef* results, int* resultCount, const int maxResults) const 
{
	const int MAX_TILES = 32;
	dtCompressedTileRef tiles[MAX_TILES];
	
	int n = 0;
	
	const float tw = m_params.width * m_params.cs;
	const float th = m_params.height * m_params.cs;
	const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / tw);
	const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / tw);
	const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / th);
	const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / th);
	
	for (int ty = ty0; ty <= ty1; ++ty)
	{
		for (int tx = tx0; tx <= tx1; ++tx)
		{
			const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
			
			for (int i = 0; i < ntiles; ++i)
			{
				const dtCompressedTile* tile = &m_tiles[decodeTileIdTile(tiles[i])];
				float tbmin[3], tbmax[3];
				calcTightTileBounds(tile->header, tbmin, tbmax);
				
				if (dtOverlapBounds(bmin,bmax, tbmin,tbmax))
				{
					if (n < maxResults)
						results[n++] = tiles[i];
				}
			}
		}
	}
	
	*resultCount = n;
	
	return DT_SUCCESS;
}
Ejemplo n.º 5
0
static int createBVTree(const unsigned short* verts, const int /*nverts*/,
						const unsigned short* polys, const int npolys, const int nvp,
						const float cs, const float ch,
						const int /*nnodes*/, dtBVNode* nodes)
{
	// Build tree
	BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP);
	for (int i = 0; i < npolys; i++)
	{
		BVItem& it = items[i];
		it.i = i;
		// Calc polygon bounds.
		const unsigned short* p = &polys[i*nvp*2];
		it.bmin[0] = it.bmax[0] = verts[p[0]*3+0];
		it.bmin[1] = it.bmax[1] = verts[p[0]*3+1];
		it.bmin[2] = it.bmax[2] = verts[p[0]*3+2];
		
		for (int j = 1; j < nvp; ++j)
		{
			if (p[j] == MESH_NULL_IDX) break;
			unsigned short x = verts[p[j]*3+0];
			unsigned short y = verts[p[j]*3+1];
			unsigned short z = verts[p[j]*3+2];
			
			if (x < it.bmin[0]) it.bmin[0] = x;
			if (y < it.bmin[1]) it.bmin[1] = y;
			if (z < it.bmin[2]) it.bmin[2] = z;
			
			if (x > it.bmax[0]) it.bmax[0] = x;
			if (y > it.bmax[1]) it.bmax[1] = y;
			if (z > it.bmax[2]) it.bmax[2] = z;
		}
		// Remap y
		it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs);
		it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs);
	}
	
	int curNode = 0;
	subdivide(items, npolys, 0, npolys, curNode, nodes);
	
	dtFree(items);
	
	return curNode;
}
Ejemplo n.º 6
0
//-----------------------------------------------------------------------------
// Purpose: Partial rebuild. Destroys tiles at bounds touching the mesh and 
//			rebuilds those tiles.
//-----------------------------------------------------------------------------
bool CRecastMesh::RebuildPartial( CMapMesh *pMapMesh, const Vector &vMins, const Vector &vMaxs )
{
	double fStartTime = Plat_FloatTime();

	BuildContext ctx;
	dtStatus status;

	const dtTileCacheParams &tcparams = *m_tileCache->getParams();

	float bmin[3];
	float bmax[3];
	
	bmin[0] = vMins.x;
	bmin[1] = vMins.z;
	bmin[2] = vMins.y;
	bmax[0] = vMaxs.x;
	bmax[1] = vMaxs.z;
	bmax[2] = vMaxs.y;

	const float tw = tcparams.width * tcparams.cs;
	const float th = tcparams.height * tcparams.cs;
	const int tx0 = (int)dtMathFloorf((bmin[0]-tcparams.orig[0]) / tw);
	const int tx1 = (int)dtMathFloorf((bmax[0]-tcparams.orig[0]) / tw);
	const int ty0 = (int)dtMathFloorf((bmin[2]-tcparams.orig[2]) / th);
	const int ty1 = (int)dtMathFloorf((bmax[2]-tcparams.orig[2]) / th);
	
	TileCacheData tiles[MAX_LAYERS];
	int ntiles;
	dtCompressedTileRef results[128];

	for (int ty = ty0; ty <= ty1; ++ty)
	{
		for (int tx = tx0; tx <= tx1; ++tx)
		{
			int nCount = m_tileCache->getTilesAt( tx, ty, results, 128 );
			for( int i = 0; i < nCount; i++ )
			{
				unsigned char* data; 
				int dataSize;
				m_tileCache->removeTile( results[i], &data, &dataSize );
			}

			memset(tiles, 0, sizeof(tiles));
			ntiles = rasterizeTileLayers(&ctx, pMapMesh, tx, ty, m_cfg, tiles, MAX_LAYERS);

			for (int i = 0; i < ntiles; ++i)
			{
				TileCacheData* tile = &tiles[i];
				status = m_tileCache->addTile(tile->data, tile->dataSize, DT_COMPRESSEDTILE_FREE_DATA, 0);
				if (dtStatusFailed(status))
				{
					dtFree(tile->data);
					tile->data = 0;
					continue;
				}
			}
		}
	}

	// Build initial meshes
	for (int ty = ty0; ty <= ty1; ++ty)
	{
		for (int tx = tx0; tx <= tx1; ++tx)
		{
			m_tileCache->buildNavMeshTilesAt(tx,ty, m_navMesh);
		}
	}

	if( recast_build_partial_debug.GetBool() )
		DevMsg( "CRecastMesh: Generated partial mesh update %s in %f seconds\n", m_Name.Get(), Plat_FloatTime() - fStartTime );

	return true;
}