Add support for AABB shaped obstacles to dtTileCache (#215)
This commit is contained in:
parent
76db7aa47b
commit
9052db45d8
@ -35,13 +35,38 @@ enum ObstacleState
|
|||||||
DT_OBSTACLE_REMOVING,
|
DT_OBSTACLE_REMOVING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ObstacleType
|
||||||
|
{
|
||||||
|
DT_OBSTACLE_CYLINDER,
|
||||||
|
DT_OBSTACLE_BOX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dtObstacleCylinder
|
||||||
|
{
|
||||||
|
float pos[ 3 ];
|
||||||
|
float radius;
|
||||||
|
float height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dtObstacleBox
|
||||||
|
{
|
||||||
|
float bmin[ 3 ];
|
||||||
|
float bmax[ 3 ];
|
||||||
|
};
|
||||||
|
|
||||||
static const int DT_MAX_TOUCHED_TILES = 8;
|
static const int DT_MAX_TOUCHED_TILES = 8;
|
||||||
struct dtTileCacheObstacle
|
struct dtTileCacheObstacle
|
||||||
{
|
{
|
||||||
float pos[3], radius, height;
|
union
|
||||||
|
{
|
||||||
|
dtObstacleCylinder cylinder;
|
||||||
|
dtObstacleBox box;
|
||||||
|
};
|
||||||
|
|
||||||
dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
|
dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
|
||||||
dtCompressedTileRef pending[DT_MAX_TOUCHED_TILES];
|
dtCompressedTileRef pending[DT_MAX_TOUCHED_TILES];
|
||||||
unsigned short salt;
|
unsigned short salt;
|
||||||
|
unsigned char type;
|
||||||
unsigned char state;
|
unsigned char state;
|
||||||
unsigned char ntouched;
|
unsigned char ntouched;
|
||||||
unsigned char npending;
|
unsigned char npending;
|
||||||
@ -106,6 +131,8 @@ public:
|
|||||||
dtStatus removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize);
|
dtStatus removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize);
|
||||||
|
|
||||||
dtStatus addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result);
|
dtStatus addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result);
|
||||||
|
dtStatus addBoxObstacle(const float* bmin, const float* bmax, dtObstacleRef* result);
|
||||||
|
|
||||||
dtStatus removeObstacle(const dtObstacleRef ref);
|
dtStatus removeObstacle(const dtObstacleRef ref);
|
||||||
|
|
||||||
dtStatus queryTiles(const float* bmin, const float* bmax,
|
dtStatus queryTiles(const float* bmin, const float* bmax,
|
||||||
|
@ -127,6 +127,9 @@ void dtFreeTileCachePolyMesh(dtTileCacheAlloc* alloc, dtTileCachePolyMesh* lmesh
|
|||||||
dtStatus dtMarkCylinderArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
|
dtStatus dtMarkCylinderArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
|
||||||
const float* pos, const float radius, const float height, const unsigned char areaId);
|
const float* pos, const float radius, const float height, const unsigned char areaId);
|
||||||
|
|
||||||
|
dtStatus dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
|
||||||
|
const float* bmin, const float* bmax, const unsigned char areaId);
|
||||||
|
|
||||||
dtStatus dtBuildTileCacheRegions(dtTileCacheAlloc* alloc,
|
dtStatus dtBuildTileCacheRegions(dtTileCacheAlloc* alloc,
|
||||||
dtTileCacheLayer& layer,
|
dtTileCacheLayer& layer,
|
||||||
const int walkableClimb);
|
const int walkableClimb);
|
||||||
|
@ -370,9 +370,44 @@ dtStatus dtTileCache::addObstacle(const float* pos, const float radius, const fl
|
|||||||
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
||||||
ob->salt = salt;
|
ob->salt = salt;
|
||||||
ob->state = DT_OBSTACLE_PROCESSING;
|
ob->state = DT_OBSTACLE_PROCESSING;
|
||||||
dtVcopy(ob->pos, pos);
|
ob->type = DT_OBSTACLE_CYLINDER;
|
||||||
ob->radius = radius;
|
dtVcopy(ob->cylinder.pos, pos);
|
||||||
ob->height = height;
|
ob->cylinder.radius = radius;
|
||||||
|
ob->cylinder.height = height;
|
||||||
|
|
||||||
|
ObstacleRequest* req = &m_reqs[m_nreqs++];
|
||||||
|
memset(req, 0, sizeof(ObstacleRequest));
|
||||||
|
req->action = REQUEST_ADD;
|
||||||
|
req->ref = getObstacleRef(ob);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
*result = req->ref;
|
||||||
|
|
||||||
|
return DT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
dtStatus dtTileCache::addBoxObstacle(const float* bmin, const float* bmax, dtObstacleRef* result)
|
||||||
|
{
|
||||||
|
if (m_nreqs >= MAX_REQUESTS)
|
||||||
|
return DT_FAILURE | DT_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
dtTileCacheObstacle* ob = 0;
|
||||||
|
if (m_nextFreeObstacle)
|
||||||
|
{
|
||||||
|
ob = m_nextFreeObstacle;
|
||||||
|
m_nextFreeObstacle = ob->next;
|
||||||
|
ob->next = 0;
|
||||||
|
}
|
||||||
|
if (!ob)
|
||||||
|
return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
unsigned short salt = ob->salt;
|
||||||
|
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
||||||
|
ob->salt = salt;
|
||||||
|
ob->state = DT_OBSTACLE_PROCESSING;
|
||||||
|
ob->type = DT_OBSTACLE_BOX;
|
||||||
|
dtVcopy(ob->box.bmin, bmin);
|
||||||
|
dtVcopy(ob->box.bmax, bmax);
|
||||||
|
|
||||||
ObstacleRequest* req = &m_reqs[m_nreqs++];
|
ObstacleRequest* req = &m_reqs[m_nreqs++];
|
||||||
memset(req, 0, sizeof(ObstacleRequest));
|
memset(req, 0, sizeof(ObstacleRequest));
|
||||||
@ -606,9 +641,17 @@ dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh*
|
|||||||
if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
|
if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
|
||||||
continue;
|
continue;
|
||||||
if (contains(ob->touched, ob->ntouched, ref))
|
if (contains(ob->touched, ob->ntouched, ref))
|
||||||
|
{
|
||||||
|
if (ob->type == DT_OBSTACLE_CYLINDER)
|
||||||
{
|
{
|
||||||
dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
|
dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
|
||||||
ob->pos, ob->radius, ob->height, 0);
|
ob->cylinder.pos, ob->cylinder.radius, ob->cylinder.height, 0);
|
||||||
|
}
|
||||||
|
else if (ob->type == DT_OBSTACLE_BOX)
|
||||||
|
{
|
||||||
|
dtMarkBoxArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
|
||||||
|
ob->box.bmin, ob->box.bmax, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,10 +745,20 @@ void dtTileCache::calcTightTileBounds(const dtTileCacheLayerHeader* header, floa
|
|||||||
|
|
||||||
void dtTileCache::getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const
|
void dtTileCache::getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const
|
||||||
{
|
{
|
||||||
bmin[0] = ob->pos[0] - ob->radius;
|
if (ob->type == DT_OBSTACLE_CYLINDER)
|
||||||
bmin[1] = ob->pos[1];
|
{
|
||||||
bmin[2] = ob->pos[2] - ob->radius;
|
const dtObstacleCylinder &cl = ob->cylinder;
|
||||||
bmax[0] = ob->pos[0] + ob->radius;
|
|
||||||
bmax[1] = ob->pos[1] + ob->height;
|
bmin[0] = cl.pos[0] - cl.radius;
|
||||||
bmax[2] = ob->pos[2] + ob->radius;
|
bmin[1] = cl.pos[1];
|
||||||
|
bmin[2] = cl.pos[2] - cl.radius;
|
||||||
|
bmax[0] = cl.pos[0] + cl.radius;
|
||||||
|
bmax[1] = cl.pos[1] + cl.height;
|
||||||
|
bmax[2] = cl.pos[2] + cl.radius;
|
||||||
|
}
|
||||||
|
else if (ob->type == DT_OBSTACLE_BOX)
|
||||||
|
{
|
||||||
|
dtVcopy(bmin, ob->box.bmin);
|
||||||
|
dtVcopy(bmax, ob->box.bmax);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2002,6 +2002,44 @@ dtStatus dtMarkCylinderArea(dtTileCacheLayer& layer, const float* orig, const fl
|
|||||||
return DT_SUCCESS;
|
return DT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dtStatus dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
|
||||||
|
const float* bmin, const float* bmax, const unsigned char areaId)
|
||||||
|
{
|
||||||
|
const int w = (int)layer.header->width;
|
||||||
|
const int h = (int)layer.header->height;
|
||||||
|
const float ics = 1.0f/cs;
|
||||||
|
const float ich = 1.0f/ch;
|
||||||
|
|
||||||
|
int minx = (int)floorf((bmin[0]-orig[0])*ics);
|
||||||
|
int miny = (int)floorf((bmin[1]-orig[1])*ich);
|
||||||
|
int minz = (int)floorf((bmin[2]-orig[2])*ics);
|
||||||
|
int maxx = (int)floorf((bmax[0]-orig[0])*ics);
|
||||||
|
int maxy = (int)floorf((bmax[1]-orig[1])*ich);
|
||||||
|
int maxz = (int)floorf((bmax[2]-orig[2])*ics);
|
||||||
|
|
||||||
|
if (maxx < 0) return DT_SUCCESS;
|
||||||
|
if (minx >= w) return DT_SUCCESS;
|
||||||
|
if (maxz < 0) return DT_SUCCESS;
|
||||||
|
if (minz >= h) return DT_SUCCESS;
|
||||||
|
|
||||||
|
if (minx < 0) minx = 0;
|
||||||
|
if (maxx >= w) maxx = w-1;
|
||||||
|
if (minz < 0) minz = 0;
|
||||||
|
if (maxz >= h) maxz = h-1;
|
||||||
|
|
||||||
|
for (int z = minz; z <= maxz; ++z)
|
||||||
|
{
|
||||||
|
for (int x = minx; x <= maxx; ++x)
|
||||||
|
{
|
||||||
|
const int y = layer.heights[x+z*w];
|
||||||
|
if (y < miny || y > maxy)
|
||||||
|
continue;
|
||||||
|
layer.areas[x+z*w] = areaId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
dtStatus dtBuildTileCacheLayer(dtTileCacheCompressor* comp,
|
dtStatus dtBuildTileCacheLayer(dtTileCacheCompressor* comp,
|
||||||
dtTileCacheLayerHeader* header,
|
dtTileCacheLayerHeader* header,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user