263 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			263 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #ifndef DETOURTILECACHE_H
 | ||
|  | #define DETOURTILECACHE_H
 | ||
|  | 
 | ||
|  | #include "DetourStatus.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | typedef unsigned int dtObstacleRef; | ||
|  | 
 | ||
|  | typedef unsigned int dtCompressedTileRef; | ||
|  | 
 | ||
|  | /// Flags for addTile
 | ||
|  | enum dtCompressedTileFlags | ||
|  | { | ||
|  | 	DT_COMPRESSEDTILE_FREE_DATA = 0x01,					///< Navmesh owns the tile memory and should free it.
 | ||
|  | }; | ||
|  | 
 | ||
|  | struct dtCompressedTile | ||
|  | { | ||
|  | 	unsigned int salt;						///< Counter describing modifications to the tile.
 | ||
|  | 	struct dtTileCacheLayerHeader* header; | ||
|  | 	unsigned char* compressed; | ||
|  | 	int compressedSize; | ||
|  | 	unsigned char* data; | ||
|  | 	int dataSize; | ||
|  | 	unsigned int flags; | ||
|  | 	dtCompressedTile* next; | ||
|  | }; | ||
|  | 
 | ||
|  | enum ObstacleState | ||
|  | { | ||
|  | 	DT_OBSTACLE_EMPTY, | ||
|  | 	DT_OBSTACLE_PROCESSING, | ||
|  | 	DT_OBSTACLE_PROCESSED, | ||
|  | 	DT_OBSTACLE_REMOVING, | ||
|  | }; | ||
|  | 
 | ||
|  | enum ObstacleType | ||
|  | { | ||
|  | 	DT_OBSTACLE_CYLINDER, | ||
|  | 	DT_OBSTACLE_BOX, // AABB
 | ||
|  | 	DT_OBSTACLE_ORIENTED_BOX, // OBB
 | ||
|  | }; | ||
|  | 
 | ||
|  | struct dtObstacleCylinder | ||
|  | { | ||
|  | 	float pos[ 3 ]; | ||
|  | 	float radius; | ||
|  | 	float height; | ||
|  | }; | ||
|  | 
 | ||
|  | struct dtObstacleBox | ||
|  | { | ||
|  | 	float bmin[ 3 ]; | ||
|  | 	float bmax[ 3 ]; | ||
|  | }; | ||
|  | 
 | ||
|  | struct dtObstacleOrientedBox | ||
|  | { | ||
|  | 	float center[ 3 ]; | ||
|  | 	float halfExtents[ 3 ]; | ||
|  | 	float rotAux[ 2 ]; //{ cos(0.5f*angle)*sin(-0.5f*angle); cos(0.5f*angle)*cos(0.5f*angle) - 0.5 }
 | ||
|  | }; | ||
|  | 
 | ||
|  | static const int DT_MAX_TOUCHED_TILES = 8; | ||
|  | struct dtTileCacheObstacle | ||
|  | { | ||
|  | 	union | ||
|  | 	{ | ||
|  | 		dtObstacleCylinder cylinder; | ||
|  | 		dtObstacleBox box; | ||
|  | 		dtObstacleOrientedBox orientedBox; | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES]; | ||
|  | 	dtCompressedTileRef pending[DT_MAX_TOUCHED_TILES]; | ||
|  | 	unsigned short salt; | ||
|  | 	unsigned char type; | ||
|  | 	unsigned char state; | ||
|  | 	unsigned char ntouched; | ||
|  | 	unsigned char npending; | ||
|  | 	dtTileCacheObstacle* next; | ||
|  | }; | ||
|  | 
 | ||
|  | struct dtTileCacheParams | ||
|  | { | ||
|  | 	float orig[3]; | ||
|  | 	float cs, ch; | ||
|  | 	int width, height; | ||
|  | 	float walkableHeight; | ||
|  | 	float walkableRadius; | ||
|  | 	float walkableClimb; | ||
|  | 	float maxSimplificationError; | ||
|  | 	int maxTiles; | ||
|  | 	int maxObstacles; | ||
|  | }; | ||
|  | 
 | ||
|  | struct dtTileCacheMeshProcess | ||
|  | { | ||
|  | 	virtual ~dtTileCacheMeshProcess() { } | ||
|  | 
 | ||
|  | 	virtual void process(struct dtNavMeshCreateParams* params, | ||
|  | 						 unsigned char* polyAreas, unsigned short* polyFlags) = 0; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | class dtTileCache | ||
|  | { | ||
|  | public: | ||
|  | 	dtTileCache(); | ||
|  | 	~dtTileCache(); | ||
|  | 	 | ||
|  | 	struct dtTileCacheAlloc* getAlloc() { return m_talloc; } | ||
|  | 	struct dtTileCacheCompressor* getCompressor() { return m_tcomp; } | ||
|  | 	const dtTileCacheParams* getParams() const { return &m_params; } | ||
|  | 	 | ||
|  | 	inline int getTileCount() const { return m_params.maxTiles; } | ||
|  | 	inline const dtCompressedTile* getTile(const int i) const { return &m_tiles[i]; } | ||
|  | 	 | ||
|  | 	inline int getObstacleCount() const { return m_params.maxObstacles; } | ||
|  | 	inline const dtTileCacheObstacle* getObstacle(const int i) const { return &m_obstacles[i]; } | ||
|  | 	 | ||
|  | 	const dtTileCacheObstacle* getObstacleByRef(dtObstacleRef ref); | ||
|  | 	 | ||
|  | 	dtObstacleRef getObstacleRef(const dtTileCacheObstacle* obmin) const; | ||
|  | 	 | ||
|  | 	dtStatus init(const dtTileCacheParams* params, | ||
|  | 				  struct dtTileCacheAlloc* talloc, | ||
|  | 				  struct dtTileCacheCompressor* tcomp, | ||
|  | 				  struct dtTileCacheMeshProcess* tmproc); | ||
|  | 	 | ||
|  | 	int getTilesAt(const int tx, const int ty, dtCompressedTileRef* tiles, const int maxTiles) const ; | ||
|  | 	 | ||
|  | 	dtCompressedTile* getTileAt(const int tx, const int ty, const int tlayer); | ||
|  | 	dtCompressedTileRef getTileRef(const dtCompressedTile* tile) const; | ||
|  | 	const dtCompressedTile* getTileByRef(dtCompressedTileRef ref) const; | ||
|  | 	 | ||
|  | 	dtStatus addTile(unsigned char* data, const int dataSize, unsigned char flags, dtCompressedTileRef* result); | ||
|  | 	 | ||
|  | 	dtStatus removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize); | ||
|  | 	 | ||
|  | 	// Cylinder obstacle.
 | ||
|  | 	dtStatus addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result); | ||
|  | 
 | ||
|  | 	// Aabb obstacle.
 | ||
|  | 	dtStatus addBoxObstacle(const float* bmin, const float* bmax, dtObstacleRef* result); | ||
|  | 
 | ||
|  | 	// Box obstacle: can be rotated in Y.
 | ||
|  | 	dtStatus addBoxObstacle(const float* center, const float* halfExtents, const float yRadians, dtObstacleRef* result); | ||
|  | 	 | ||
|  | 	dtStatus removeObstacle(const dtObstacleRef ref); | ||
|  | 	 | ||
|  | 	dtStatus queryTiles(const float* bmin, const float* bmax, | ||
|  | 						dtCompressedTileRef* results, int* resultCount, const int maxResults) const; | ||
|  | 	 | ||
|  | 	/// Updates the tile cache by rebuilding tiles touched by unfinished obstacle requests.
 | ||
|  | 	///  @param[in]		dt			The time step size. Currently not used.
 | ||
|  | 	///  @param[in]		navmesh		The mesh to affect when rebuilding tiles.
 | ||
|  | 	///  @param[out]	upToDate	Whether the tile cache is fully up to date with obstacle requests and tile rebuilds.
 | ||
|  | 	///  							If the tile cache is up to date another (immediate) call to update will have no effect;
 | ||
|  | 	///  							otherwise another call will continue processing obstacle requests and tile rebuilds.
 | ||
|  | 	dtStatus update(const float dt, class dtNavMesh* navmesh, bool* upToDate = 0); | ||
|  | 	 | ||
|  | 	dtStatus buildNavMeshTilesAt(const int tx, const int ty, class dtNavMesh* navmesh); | ||
|  | 	 | ||
|  | 	dtStatus buildNavMeshTile(const dtCompressedTileRef ref, class dtNavMesh* navmesh); | ||
|  | 	 | ||
|  | 	void calcTightTileBounds(const struct dtTileCacheLayerHeader* header, float* bmin, float* bmax) const; | ||
|  | 	 | ||
|  | 	void getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const; | ||
|  | 	 | ||
|  | 
 | ||
|  | 	/// Encodes a tile id.
 | ||
|  | 	inline dtCompressedTileRef encodeTileId(unsigned int salt, unsigned int it) const | ||
|  | 	{ | ||
|  | 		return ((dtCompressedTileRef)salt << m_tileBits) | (dtCompressedTileRef)it; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	/// Decodes a tile salt.
 | ||
|  | 	inline unsigned int decodeTileIdSalt(dtCompressedTileRef ref) const | ||
|  | 	{ | ||
|  | 		const dtCompressedTileRef saltMask = ((dtCompressedTileRef)1<<m_saltBits)-1; | ||
|  | 		return (unsigned int)((ref >> m_tileBits) & saltMask); | ||
|  | 	} | ||
|  | 	 | ||
|  | 	/// Decodes a tile id.
 | ||
|  | 	inline unsigned int decodeTileIdTile(dtCompressedTileRef ref) const | ||
|  | 	{ | ||
|  | 		const dtCompressedTileRef tileMask = ((dtCompressedTileRef)1<<m_tileBits)-1; | ||
|  | 		return (unsigned int)(ref & tileMask); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/// Encodes an obstacle id.
 | ||
|  | 	inline dtObstacleRef encodeObstacleId(unsigned int salt, unsigned int it) const | ||
|  | 	{ | ||
|  | 		return ((dtObstacleRef)salt << 16) | (dtObstacleRef)it; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	/// Decodes an obstacle salt.
 | ||
|  | 	inline unsigned int decodeObstacleIdSalt(dtObstacleRef ref) const | ||
|  | 	{ | ||
|  | 		const dtObstacleRef saltMask = ((dtObstacleRef)1<<16)-1; | ||
|  | 		return (unsigned int)((ref >> 16) & saltMask); | ||
|  | 	} | ||
|  | 	 | ||
|  | 	/// Decodes an obstacle id.
 | ||
|  | 	inline unsigned int decodeObstacleIdObstacle(dtObstacleRef ref) const | ||
|  | 	{ | ||
|  | 		const dtObstacleRef tileMask = ((dtObstacleRef)1<<16)-1; | ||
|  | 		return (unsigned int)(ref & tileMask); | ||
|  | 	} | ||
|  | 	 | ||
|  | 	 | ||
|  | private: | ||
|  | 	// Explicitly disabled copy constructor and copy assignment operator.
 | ||
|  | 	dtTileCache(const dtTileCache&); | ||
|  | 	dtTileCache& operator=(const dtTileCache&); | ||
|  | 
 | ||
|  | 	enum ObstacleRequestAction | ||
|  | 	{ | ||
|  | 		REQUEST_ADD, | ||
|  | 		REQUEST_REMOVE, | ||
|  | 	}; | ||
|  | 	 | ||
|  | 	struct ObstacleRequest | ||
|  | 	{ | ||
|  | 		int action; | ||
|  | 		dtObstacleRef ref; | ||
|  | 	}; | ||
|  | 	 | ||
|  | 	int m_tileLutSize;						///< Tile hash lookup size (must be pot).
 | ||
|  | 	int m_tileLutMask;						///< Tile hash lookup mask.
 | ||
|  | 	 | ||
|  | 	dtCompressedTile** m_posLookup;			///< Tile hash lookup.
 | ||
|  | 	dtCompressedTile* m_nextFreeTile;		///< Freelist of tiles.
 | ||
|  | 	dtCompressedTile* m_tiles;				///< List of tiles.
 | ||
|  | 	 | ||
|  | 	unsigned int m_saltBits;				///< Number of salt bits in the tile ID.
 | ||
|  | 	unsigned int m_tileBits;				///< Number of tile bits in the tile ID.
 | ||
|  | 	 | ||
|  | 	dtTileCacheParams m_params; | ||
|  | 	 | ||
|  | 	dtTileCacheAlloc* m_talloc; | ||
|  | 	dtTileCacheCompressor* m_tcomp; | ||
|  | 	dtTileCacheMeshProcess* m_tmproc; | ||
|  | 	 | ||
|  | 	dtTileCacheObstacle* m_obstacles; | ||
|  | 	dtTileCacheObstacle* m_nextFreeObstacle; | ||
|  | 	 | ||
|  | 	static const int MAX_REQUESTS = 64; | ||
|  | 	ObstacleRequest m_reqs[MAX_REQUESTS]; | ||
|  | 	int m_nreqs; | ||
|  | 	 | ||
|  | 	static const int MAX_UPDATE = 64; | ||
|  | 	dtCompressedTileRef m_update[MAX_UPDATE]; | ||
|  | 	int m_nupdate; | ||
|  | }; | ||
|  | 
 | ||
|  | dtTileCache* dtAllocTileCache(); | ||
|  | void dtFreeTileCache(dtTileCache* tc); | ||
|  | 
 | ||
|  | #endif
 |