mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 07:04:36 +00:00
update recast
This commit is contained in:
parent
e079536122
commit
8aa48ff21b
34 changed files with 1138 additions and 407 deletions
|
|
@ -77,6 +77,7 @@ dtTileCache::dtTileCache() :
|
|||
m_nupdate(0)
|
||||
{
|
||||
memset(&m_params, 0, sizeof(m_params));
|
||||
memset(m_reqs, 0, sizeof(ObstacleRequest) * MAX_REQUESTS);
|
||||
}
|
||||
|
||||
dtTileCache::~dtTileCache()
|
||||
|
|
@ -369,9 +370,10 @@ dtStatus dtTileCache::addObstacle(const float* pos, const float radius, const fl
|
|||
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
||||
ob->salt = salt;
|
||||
ob->state = DT_OBSTACLE_PROCESSING;
|
||||
dtVcopy(ob->pos, pos);
|
||||
ob->radius = radius;
|
||||
ob->height = height;
|
||||
ob->type = DT_OBSTACLE_CYLINDER;
|
||||
dtVcopy(ob->cylinder.pos, pos);
|
||||
ob->cylinder.radius = radius;
|
||||
ob->cylinder.height = height;
|
||||
|
||||
ObstacleRequest* req = &m_reqs[m_nreqs++];
|
||||
memset(req, 0, sizeof(ObstacleRequest));
|
||||
|
|
@ -384,6 +386,79 @@ dtStatus dtTileCache::addObstacle(const float* pos, const float radius, const fl
|
|||
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++];
|
||||
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* center, const float* halfExtents, const float yRadians, 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_ORIENTED_BOX;
|
||||
dtVcopy(ob->orientedBox.center, center);
|
||||
dtVcopy(ob->orientedBox.halfExtents, halfExtents);
|
||||
|
||||
float coshalf= cosf(0.5f*yRadians);
|
||||
float sinhalf = sinf(-0.5f*yRadians);
|
||||
ob->orientedBox.rotAux[0] = coshalf*sinhalf;
|
||||
ob->orientedBox.rotAux[1] = coshalf*coshalf - 0.5f;
|
||||
|
||||
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::removeObstacle(const dtObstacleRef ref)
|
||||
{
|
||||
if (!ref)
|
||||
|
|
@ -440,7 +515,8 @@ dtStatus dtTileCache::queryTiles(const float* bmin, const float* bmax,
|
|||
return DT_SUCCESS;
|
||||
}
|
||||
|
||||
dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
||||
dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh,
|
||||
bool* upToDate)
|
||||
{
|
||||
if (m_nupdate == 0)
|
||||
{
|
||||
|
|
@ -499,12 +575,13 @@ dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
|||
m_nreqs = 0;
|
||||
}
|
||||
|
||||
dtStatus status = DT_SUCCESS;
|
||||
// Process updates
|
||||
if (m_nupdate)
|
||||
{
|
||||
// Build mesh
|
||||
const dtCompressedTileRef ref = m_update[0];
|
||||
dtStatus status = buildNavMeshTile(ref, navmesh);
|
||||
status = buildNavMeshTile(ref, navmesh);
|
||||
m_nupdate--;
|
||||
if (m_nupdate > 0)
|
||||
memmove(m_update, m_update+1, m_nupdate*sizeof(dtCompressedTileRef));
|
||||
|
|
@ -547,12 +624,12 @@ dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dtStatusFailed(status))
|
||||
return status;
|
||||
}
|
||||
|
||||
return DT_SUCCESS;
|
||||
if (upToDate)
|
||||
*upToDate = m_nupdate == 0 && m_nreqs == 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -604,8 +681,21 @@ dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh*
|
|||
continue;
|
||||
if (contains(ob->touched, ob->ntouched, ref))
|
||||
{
|
||||
dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
|
||||
ob->pos, ob->radius, ob->height, 0);
|
||||
if (ob->type == DT_OBSTACLE_CYLINDER)
|
||||
{
|
||||
dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
|
||||
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);
|
||||
}
|
||||
else if (ob->type == DT_OBSTACLE_ORIENTED_BOX)
|
||||
{
|
||||
dtMarkBoxArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
|
||||
ob->orientedBox.center, ob->orientedBox.halfExtents, ob->orientedBox.rotAux, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -616,7 +706,7 @@ dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh*
|
|||
|
||||
bc.lcset = dtAllocTileCacheContourSet(m_talloc);
|
||||
if (!bc.lcset)
|
||||
return status;
|
||||
return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||||
status = dtBuildTileCacheContours(m_talloc, *bc.layer, walkableClimbVx,
|
||||
m_params.maxSimplificationError, *bc.lcset);
|
||||
if (dtStatusFailed(status))
|
||||
|
|
@ -624,7 +714,7 @@ dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh*
|
|||
|
||||
bc.lmesh = dtAllocTileCachePolyMesh(m_talloc);
|
||||
if (!bc.lmesh)
|
||||
return status;
|
||||
return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||||
status = dtBuildTileCachePolyMesh(m_talloc, *bc.lcset, *bc.lmesh);
|
||||
if (dtStatusFailed(status))
|
||||
return status;
|
||||
|
|
@ -699,10 +789,32 @@ void dtTileCache::calcTightTileBounds(const dtTileCacheLayerHeader* header, floa
|
|||
|
||||
void dtTileCache::getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const
|
||||
{
|
||||
bmin[0] = ob->pos[0] - ob->radius;
|
||||
bmin[1] = ob->pos[1];
|
||||
bmin[2] = ob->pos[2] - ob->radius;
|
||||
bmax[0] = ob->pos[0] + ob->radius;
|
||||
bmax[1] = ob->pos[1] + ob->height;
|
||||
bmax[2] = ob->pos[2] + ob->radius;
|
||||
if (ob->type == DT_OBSTACLE_CYLINDER)
|
||||
{
|
||||
const dtObstacleCylinder &cl = ob->cylinder;
|
||||
|
||||
bmin[0] = cl.pos[0] - cl.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);
|
||||
}
|
||||
else if (ob->type == DT_OBSTACLE_ORIENTED_BOX)
|
||||
{
|
||||
const dtObstacleOrientedBox &orientedBox = ob->orientedBox;
|
||||
|
||||
float maxr = 1.41f*dtMax(orientedBox.halfExtents[0], orientedBox.halfExtents[2]);
|
||||
bmin[0] = orientedBox.center[0] - maxr;
|
||||
bmax[0] = orientedBox.center[0] + maxr;
|
||||
bmin[1] = orientedBox.center[1] - orientedBox.halfExtents[1];
|
||||
bmax[1] = orientedBox.center[1] + orientedBox.halfExtents[1];
|
||||
bmin[2] = orientedBox.center[2] - maxr;
|
||||
bmax[2] = orientedBox.center[2] + maxr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,7 @@ template<class T> class dtFixedArray
|
|||
dtTileCacheAlloc* m_alloc;
|
||||
T* m_ptr;
|
||||
const int m_size;
|
||||
inline T* operator=(T* p);
|
||||
inline void operator=(dtFixedArray<T>& p);
|
||||
inline dtFixedArray();
|
||||
public:
|
||||
inline dtFixedArray(dtTileCacheAlloc* a, const int s) : m_alloc(a), m_ptr((T*)a->alloc(sizeof(T)*s)), m_size(s) {}
|
||||
inline ~dtFixedArray() { if (m_alloc) m_alloc->free(m_ptr); }
|
||||
|
|
@ -2004,6 +2002,98 @@ dtStatus dtMarkCylinderArea(dtTileCacheLayer& layer, const float* orig, const fl
|
|||
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 dtMarkBoxArea(dtTileCacheLayer& layer, const float* orig, const float cs, const float ch,
|
||||
const float* center, const float* halfExtents, const float* rotAux, 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;
|
||||
|
||||
float cx = (center[0] - orig[0])*ics;
|
||||
float cz = (center[2] - orig[2])*ics;
|
||||
|
||||
float maxr = 1.41f*dtMax(halfExtents[0], halfExtents[2]);
|
||||
int minx = (int)floorf(cx - maxr*ics);
|
||||
int maxx = (int)floorf(cx + maxr*ics);
|
||||
int minz = (int)floorf(cz - maxr*ics);
|
||||
int maxz = (int)floorf(cz + maxr*ics);
|
||||
int miny = (int)floorf((center[1]-halfExtents[1]-orig[1])*ich);
|
||||
int maxy = (int)floorf((center[1]+halfExtents[1]-orig[1])*ich);
|
||||
|
||||
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;
|
||||
|
||||
float xhalf = halfExtents[0]*ics + 0.5f;
|
||||
float zhalf = halfExtents[2]*ics + 0.5f;
|
||||
|
||||
for (int z = minz; z <= maxz; ++z)
|
||||
{
|
||||
for (int x = minx; x <= maxx; ++x)
|
||||
{
|
||||
float x2 = 2.0f*(float(x) - cx);
|
||||
float z2 = 2.0f*(float(z) - cz);
|
||||
float xrot = rotAux[1]*x2 + rotAux[0]*z2;
|
||||
if (xrot > xhalf || xrot < -xhalf)
|
||||
continue;
|
||||
float zrot = rotAux[1]*z2 - rotAux[0]*x2;
|
||||
if (zrot > zhalf || zrot < -zhalf)
|
||||
continue;
|
||||
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,
|
||||
dtTileCacheLayerHeader* header,
|
||||
|
|
@ -2027,7 +2117,11 @@ dtStatus dtBuildTileCacheLayer(dtTileCacheCompressor* comp,
|
|||
const int bufferSize = gridSize*3;
|
||||
unsigned char* buffer = (unsigned char*)dtAlloc(bufferSize, DT_ALLOC_TEMP);
|
||||
if (!buffer)
|
||||
{
|
||||
dtFree(data);
|
||||
return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(buffer, heights, gridSize);
|
||||
memcpy(buffer+gridSize, areas, gridSize);
|
||||
memcpy(buffer+gridSize*2, cons, gridSize);
|
||||
|
|
@ -2038,7 +2132,11 @@ dtStatus dtBuildTileCacheLayer(dtTileCacheCompressor* comp,
|
|||
int compressedSize = 0;
|
||||
dtStatus status = comp->compress(buffer, bufferSize, compressed, maxCompressedSize, &compressedSize);
|
||||
if (dtStatusFailed(status))
|
||||
{
|
||||
dtFree(buffer);
|
||||
dtFree(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
*outData = data;
|
||||
*outDataSize = headerSize + compressedSize;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue