mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-26 14:55:39 +00:00
Updated recast to 1.5.1
This commit is contained in:
parent
630949514a
commit
c7e5b35744
55 changed files with 3277 additions and 1460 deletions
|
|
@ -19,7 +19,7 @@
|
|||
#include <stdlib.h>
|
||||
#include "DetourAlloc.h"
|
||||
|
||||
static void *dtAllocDefault(int size, dtAllocHint)
|
||||
static void *dtAllocDefault(size_t size, dtAllocHint)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc)
|
|||
sFreeFunc = freeFunc ? freeFunc : dtFreeDefault;
|
||||
}
|
||||
|
||||
void* dtAlloc(int size, dtAllocHint hint)
|
||||
void* dtAlloc(size_t size, dtAllocHint hint)
|
||||
{
|
||||
return sAllocFunc(size, hint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,16 +16,11 @@
|
|||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include "DetourCommon.h"
|
||||
#include "DetourMath.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float dtSqrt(float x)
|
||||
{
|
||||
return sqrtf(x);
|
||||
}
|
||||
|
||||
void dtClosestPtPointTriangle(float* closest, const float* p,
|
||||
const float* a, const float* b, const float* c)
|
||||
{
|
||||
|
|
@ -360,7 +355,7 @@ void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
|
|||
acc += dacc;
|
||||
}
|
||||
|
||||
float v = dtSqrt(t);
|
||||
float v = dtMathSqrtf(t);
|
||||
|
||||
const float a = 1 - v;
|
||||
const float b = (1 - u) * v;
|
||||
|
|
@ -374,3 +369,20 @@ void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
|
|||
out[2] = a*pa[2] + b*pb[2] + c*pc[2];
|
||||
}
|
||||
|
||||
inline float vperpXZ(const float* a, const float* b) { return a[0]*b[2] - a[2]*b[0]; }
|
||||
|
||||
bool dtIntersectSegSeg2D(const float* ap, const float* aq,
|
||||
const float* bp, const float* bq,
|
||||
float& s, float& t)
|
||||
{
|
||||
float u[3], v[3], w[3];
|
||||
dtVsub(u,aq,ap);
|
||||
dtVsub(v,bq,bp);
|
||||
dtVsub(w,ap,bp);
|
||||
float d = vperpXZ(u,v);
|
||||
if (fabsf(d) < 1e-6f) return false;
|
||||
s = vperpXZ(v,w) / d;
|
||||
t = vperpXZ(u,w) / d;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "DetourNavMesh.h"
|
||||
#include "DetourNode.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "DetourMath.h"
|
||||
#include "DetourAlloc.h"
|
||||
#include "DetourAssert.h"
|
||||
#include <new>
|
||||
|
|
@ -193,11 +193,13 @@ dtNavMesh::dtNavMesh() :
|
|||
m_tileLutMask(0),
|
||||
m_posLookup(0),
|
||||
m_nextFree(0),
|
||||
m_tiles(0),
|
||||
m_saltBits(0),
|
||||
m_tileBits(0),
|
||||
m_polyBits(0)
|
||||
m_tiles(0)
|
||||
{
|
||||
#ifndef DT_POLYREF64
|
||||
m_saltBits = 0;
|
||||
m_tileBits = 0;
|
||||
m_polyBits = 0;
|
||||
#endif
|
||||
memset(&m_params, 0, sizeof(dtNavMeshParams));
|
||||
m_orig[0] = 0;
|
||||
m_orig[1] = 0;
|
||||
|
|
@ -249,12 +251,15 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
|
|||
}
|
||||
|
||||
// Init ID generator values.
|
||||
#ifndef DT_POLYREF64
|
||||
m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles));
|
||||
m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys));
|
||||
// Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
|
||||
m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits);
|
||||
|
||||
if (m_saltBits < 10)
|
||||
return DT_FAILURE | DT_INVALID_PARAM;
|
||||
#endif
|
||||
|
||||
return DT_SUCCESS;
|
||||
}
|
||||
|
|
@ -345,7 +350,7 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
|
|||
return n;
|
||||
}
|
||||
|
||||
void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
|
||||
void dtNavMesh::unconnectLinks(dtMeshTile* tile, dtMeshTile* target)
|
||||
{
|
||||
if (!tile || !target) return;
|
||||
|
||||
|
|
@ -358,10 +363,9 @@ void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
|
|||
unsigned int pj = DT_NULL_LINK;
|
||||
while (j != DT_NULL_LINK)
|
||||
{
|
||||
if (tile->links[j].side != 0xff &&
|
||||
decodePolyIdTile(tile->links[j].ref) == targetNum)
|
||||
if (decodePolyIdTile(tile->links[j].ref) == targetNum)
|
||||
{
|
||||
// Revove link.
|
||||
// Remove link.
|
||||
unsigned int nj = tile->links[j].next;
|
||||
if (pj == DT_NULL_LINK)
|
||||
poly->firstLink = nj;
|
||||
|
|
@ -612,14 +616,65 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
|
|||
}
|
||||
}
|
||||
|
||||
void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
|
||||
const float* pos, float* closest) const
|
||||
void dtNavMesh::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const
|
||||
{
|
||||
const dtPoly* poly = &tile->polys[ip];
|
||||
const dtMeshTile* tile = 0;
|
||||
const dtPoly* poly = 0;
|
||||
getTileAndPolyByRefUnsafe(ref, &tile, &poly);
|
||||
|
||||
float closestDistSqr = FLT_MAX;
|
||||
// Off-mesh connections don't have detail polygons.
|
||||
if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||||
{
|
||||
const float* v0 = &tile->verts[poly->verts[0]*3];
|
||||
const float* v1 = &tile->verts[poly->verts[1]*3];
|
||||
const float d0 = dtVdist(pos, v0);
|
||||
const float d1 = dtVdist(pos, v1);
|
||||
const float u = d0 / (d0+d1);
|
||||
dtVlerp(closest, v0, v1, u);
|
||||
if (posOverPoly)
|
||||
*posOverPoly = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int ip = (unsigned int)(poly - tile->polys);
|
||||
const dtPolyDetail* pd = &tile->detailMeshes[ip];
|
||||
|
||||
// Clamp point to be inside the polygon.
|
||||
float verts[DT_VERTS_PER_POLYGON*3];
|
||||
float edged[DT_VERTS_PER_POLYGON];
|
||||
float edget[DT_VERTS_PER_POLYGON];
|
||||
const int nv = poly->vertCount;
|
||||
for (int i = 0; i < nv; ++i)
|
||||
dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]);
|
||||
|
||||
dtVcopy(closest, pos);
|
||||
if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget))
|
||||
{
|
||||
// Point is outside the polygon, dtClamp to nearest edge.
|
||||
float dmin = FLT_MAX;
|
||||
int imin = -1;
|
||||
for (int i = 0; i < nv; ++i)
|
||||
{
|
||||
if (edged[i] < dmin)
|
||||
{
|
||||
dmin = edged[i];
|
||||
imin = i;
|
||||
}
|
||||
}
|
||||
const float* va = &verts[imin*3];
|
||||
const float* vb = &verts[((imin+1)%nv)*3];
|
||||
dtVlerp(closest, va, vb, edget[imin]);
|
||||
|
||||
if (posOverPoly)
|
||||
*posOverPoly = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (posOverPoly)
|
||||
*posOverPoly = true;
|
||||
}
|
||||
|
||||
// Find height at the location.
|
||||
for (int j = 0; j < pd->triCount; ++j)
|
||||
{
|
||||
const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
|
||||
|
|
@ -631,13 +686,11 @@ void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip
|
|||
else
|
||||
v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3];
|
||||
}
|
||||
float pt[3];
|
||||
dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]);
|
||||
float d = dtVdistSqr(pos, pt);
|
||||
if (d < closestDistSqr)
|
||||
float h;
|
||||
if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h))
|
||||
{
|
||||
dtVcopy(closest, pt);
|
||||
closestDistSqr = d;
|
||||
closest[1] = h;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -661,12 +714,27 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile,
|
|||
{
|
||||
dtPolyRef ref = polys[i];
|
||||
float closestPtPoly[3];
|
||||
closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly);
|
||||
float d = dtVdistSqr(center, closestPtPoly);
|
||||
float diff[3];
|
||||
bool posOverPoly = false;
|
||||
float d;
|
||||
closestPointOnPoly(ref, center, closestPtPoly, &posOverPoly);
|
||||
|
||||
// If a point is directly over a polygon and closer than
|
||||
// climb height, favor that instead of straight line nearest point.
|
||||
dtVsub(diff, center, closestPtPoly);
|
||||
if (posOverPoly)
|
||||
{
|
||||
d = dtAbs(diff[1]) - tile->header->walkableClimb;
|
||||
d = d > 0 ? d*d : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = dtVlenSqr(diff);
|
||||
}
|
||||
|
||||
if (d < nearestDistanceSqr)
|
||||
{
|
||||
if (nearestPt)
|
||||
dtVcopy(nearestPt, closestPtPoly);
|
||||
dtVcopy(nearestPt, closestPtPoly);
|
||||
nearestDistanceSqr = d;
|
||||
nearest = ref;
|
||||
}
|
||||
|
|
@ -769,6 +837,11 @@ int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, co
|
|||
/// tile will be restored to the same values they were before the tile was
|
||||
/// removed.
|
||||
///
|
||||
/// The nav mesh assumes exclusive access to the data passed and will make
|
||||
/// changes to the dynamic portion of the data. For that reason the data
|
||||
/// should not be reused in other nav meshes until the tile has been successfully
|
||||
/// removed from this nav mesh.
|
||||
///
|
||||
/// @see dtCreateNavMeshData, #removeTile
|
||||
dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||||
dtTileRef lastRef, dtTileRef* result)
|
||||
|
|
@ -1123,25 +1196,24 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
|
|||
}
|
||||
|
||||
// Remove connections to neighbour tiles.
|
||||
// Create connections with neighbour tiles.
|
||||
static const int MAX_NEIS = 32;
|
||||
dtMeshTile* neis[MAX_NEIS];
|
||||
int nneis;
|
||||
|
||||
// Connect with layers in current tile.
|
||||
// Disconnect from other layers in current tile.
|
||||
nneis = getTilesAt(tile->header->x, tile->header->y, neis, MAX_NEIS);
|
||||
for (int j = 0; j < nneis; ++j)
|
||||
{
|
||||
if (neis[j] == tile) continue;
|
||||
unconnectExtLinks(neis[j], tile);
|
||||
unconnectLinks(neis[j], tile);
|
||||
}
|
||||
|
||||
// Connect with neighbour tiles.
|
||||
// Disconnect from neighbour tiles.
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
nneis = getNeighbourTilesAt(tile->header->x, tile->header->y, i, neis, MAX_NEIS);
|
||||
for (int j = 0; j < nneis; ++j)
|
||||
unconnectExtLinks(neis[j], tile);
|
||||
unconnectLinks(neis[j], tile);
|
||||
}
|
||||
|
||||
// Reset tile.
|
||||
|
|
@ -1173,7 +1245,11 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
|
|||
tile->offMeshCons = 0;
|
||||
|
||||
// Update salt, salt should never be zero.
|
||||
#ifdef DT_POLYREF64
|
||||
tile->salt = (tile->salt+1) & ((1<<DT_SALT_BITS)-1);
|
||||
#else
|
||||
tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
|
||||
#endif
|
||||
if (tile->salt == 0)
|
||||
tile->salt++;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
#include "DetourNavMesh.h"
|
||||
#include "DetourCommon.h"
|
||||
#include "DetourMath.h"
|
||||
#include "DetourNavMeshBuilder.h"
|
||||
#include "DetourAlloc.h"
|
||||
#include "DetourAssert.h"
|
||||
|
|
@ -202,8 +202,8 @@ static int createBVTree(const unsigned short* verts, const int /*nverts*/,
|
|||
if (z > it.bmax[2]) it.bmax[2] = z;
|
||||
}
|
||||
// Remap y
|
||||
it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs);
|
||||
it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs);
|
||||
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;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -22,6 +22,19 @@
|
|||
#include "DetourCommon.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DT_POLYREF64
|
||||
// From Thomas Wang, https://gist.github.com/badboy/6267743
|
||||
inline unsigned int dtHashRef(dtPolyRef a)
|
||||
{
|
||||
a = (~a) + (a << 18); // a = (a << 18) - a - 1;
|
||||
a = a ^ (a >> 31);
|
||||
a = a * 21; // a = (a + (a << 2)) + (a << 4);
|
||||
a = a ^ (a >> 11);
|
||||
a = a + (a << 6);
|
||||
a = a ^ (a >> 22);
|
||||
return (unsigned int)a;
|
||||
}
|
||||
#else
|
||||
inline unsigned int dtHashRef(dtPolyRef a)
|
||||
{
|
||||
a += ~(a<<15);
|
||||
|
|
@ -32,6 +45,7 @@ inline unsigned int dtHashRef(dtPolyRef a)
|
|||
a ^= (a>>16);
|
||||
return (unsigned int)a;
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
dtNodePool::dtNodePool(int maxNodes, int hashSize) :
|
||||
|
|
@ -43,7 +57,9 @@ dtNodePool::dtNodePool(int maxNodes, int hashSize) :
|
|||
m_nodeCount(0)
|
||||
{
|
||||
dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize);
|
||||
dtAssert(m_maxNodes > 0);
|
||||
// pidx is special as 0 means "none" and 1 is the first node. For that reason
|
||||
// we have 1 fewer nodes available than the number of values it can contain.
|
||||
dtAssert(m_maxNodes > 0 && m_maxNodes <= DT_NULL_IDX && m_maxNodes <= (1 << DT_NODE_PARENT_BITS) - 1);
|
||||
|
||||
m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
|
||||
m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
|
||||
|
|
@ -70,27 +86,46 @@ void dtNodePool::clear()
|
|||
m_nodeCount = 0;
|
||||
}
|
||||
|
||||
dtNode* dtNodePool::findNode(dtPolyRef id)
|
||||
unsigned int dtNodePool::findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes)
|
||||
{
|
||||
int n = 0;
|
||||
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||||
dtNodeIndex i = m_first[bucket];
|
||||
while (i != DT_NULL_IDX)
|
||||
{
|
||||
if (m_nodes[i].id == id)
|
||||
{
|
||||
if (n >= maxNodes)
|
||||
return n;
|
||||
nodes[n++] = &m_nodes[i];
|
||||
}
|
||||
i = m_next[i];
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
dtNode* dtNodePool::findNode(dtPolyRef id, unsigned char state)
|
||||
{
|
||||
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||||
dtNodeIndex i = m_first[bucket];
|
||||
while (i != DT_NULL_IDX)
|
||||
{
|
||||
if (m_nodes[i].id == id && m_nodes[i].state == state)
|
||||
return &m_nodes[i];
|
||||
i = m_next[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
dtNode* dtNodePool::getNode(dtPolyRef id)
|
||||
dtNode* dtNodePool::getNode(dtPolyRef id, unsigned char state)
|
||||
{
|
||||
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||||
dtNodeIndex i = m_first[bucket];
|
||||
dtNode* node = 0;
|
||||
while (i != DT_NULL_IDX)
|
||||
{
|
||||
if (m_nodes[i].id == id)
|
||||
if (m_nodes[i].id == id && m_nodes[i].state == state)
|
||||
return &m_nodes[i];
|
||||
i = m_next[i];
|
||||
}
|
||||
|
|
@ -107,6 +142,7 @@ dtNode* dtNodePool::getNode(dtPolyRef id)
|
|||
node->cost = 0;
|
||||
node->total = 0;
|
||||
node->id = id;
|
||||
node->state = state;
|
||||
node->flags = 0;
|
||||
|
||||
m_next[i] = m_first[bucket];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue