本文整理汇总了C++中dtMin函数的典型用法代码示例。如果您正苦于以下问题:C++ dtMin函数的具体用法?C++ dtMin怎么用?C++ dtMin使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了dtMin函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: addNeighbour
static int addNeighbour(const int idx, const float dist,
dtCrowdNeighbour* neis, const int nneis, const int maxNeis)
{
// Insert neighbour based on the distance.
dtCrowdNeighbour* nei = 0;
if (!nneis)
{
nei = &neis[nneis];
}
else if (dist >= neis[nneis-1].dist)
{
if (nneis >= maxNeis)
return nneis;
nei = &neis[nneis];
}
else
{
int i;
for (i = 0; i < nneis; ++i)
if (dist <= neis[i].dist)
break;
const int tgt = i+1;
const int n = dtMin(nneis-i, maxNeis-tgt);
dtAssert(tgt+n <= maxNeis);
if (n > 0)
memmove(&neis[tgt], &neis[i], sizeof(dtCrowdNeighbour)*n);
nei = &neis[i];
}
memset(nei, 0, sizeof(dtCrowdNeighbour));
nei->idx = idx;
nei->dist = dist;
return dtMin(nneis+1, maxNeis);
}
示例2: normalizeArray
static void normalizeArray(float* arr, const int n)
{
// Normalize penaly range.
float minPen = FLT_MAX;
float maxPen = -FLT_MAX;
for (int i = 0; i < n; ++i)
{
minPen = dtMin(minPen, arr[i]);
maxPen = dtMax(maxPen, arr[i]);
}
const float penRange = maxPen-minPen;
const float s = penRange > 0.001f ? (1.0f / penRange) : 1;
for (int i = 0; i < n; ++i)
arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f);
}
示例3: fixupShortcuts
int fixupShortcuts(dtPolyRef* path, int npath, dtNavMeshQuery* navQuery)
{
if (npath < 3)
return npath;
// Get connected polygons
static const int maxNeis = 16;
dtPolyRef neis[maxNeis];
int nneis = 0;
const dtMeshTile* tile = 0;
const dtPoly* poly = 0;
if (dtStatusFailed(navQuery->getAttachedNavMesh()->getTileAndPolyByRef(path[0], &tile, &poly)))
return npath;
for (unsigned int k = poly->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
{
const dtLink* link = &tile->links[k];
if (link->ref != 0)
{
if (nneis < maxNeis)
neis[nneis++] = link->ref;
}
}
// If any of the neighbour polygons is within the next few polygons
// in the path, short cut to that polygon directly.
static const int maxLookAhead = 6;
int cut = 0;
for (int i = dtMin(maxLookAhead, npath) - 1; i > 1 && cut == 0; i--) {
for (int j = 0; j < nneis; j++)
{
if (path[i] == neis[j]) {
cut = i;
break;
}
}
}
if (cut > 1)
{
int offset = cut - 1;
npath -= offset;
for (int i = 1; i < npath; i++)
path[i] = path[i + offset];
}
return npath;
}
示例4: dtMergeCorridorStartMoved
int dtMergeCorridorStartMoved(dtPolyRef* path, const int npath, const int maxPath,
const dtPolyRef* visited, const int nvisited)
{
int furthestPath = -1;
int furthestVisited = -1;
// Find furthest common polygon.
for (int i = npath-1; i >= 0; --i)
{
bool found = false;
for (int j = nvisited-1; j >= 0; --j)
{
if (path[i] == visited[j])
{
furthestPath = i;
furthestVisited = j;
found = true;
}
}
if (found)
break;
}
// If no intersection found just return current path.
if (furthestPath == -1 || furthestVisited == -1)
return npath;
// Concatenate paths.
// Adjust beginning of the buffer to include the visited.
const int req = nvisited - furthestVisited;
const int orig = dtMin(furthestPath+1, npath);
int size = dtMax(0, npath-orig);
if (req+size > maxPath)
size = maxPath-req;
if (size)
memmove(path+req, path+orig, size*sizeof(dtPolyRef));
// Store visited
for (int i = 0; i < req; ++i)
path[i] = visited[(nvisited-1)-i];
return req+size;
}
示例5: calcSlabEndPoints
int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
const dtMeshTile* tile, int side,
dtPolyRef* con, float* conarea, int maxcon) const
{
if (!tile) return 0;
float amin[2], amax[2];
calcSlabEndPoints(va,vb, amin,amax, side);
// Remove links pointing to 'side' and compact the links array.
float bmin[2], bmax[2];
unsigned short m = DT_EXT_LINK | (unsigned short)side;
int n = 0;
dtPolyRef base = getPolyRefBase(tile);
for (int i = 0; i < tile->header->polyCount; ++i)
{
dtPoly* poly = &tile->polys[i];
const int nv = poly->vertCount;
for (int j = 0; j < nv; ++j)
{
// Skip edges which do not point to the right side.
if (poly->neis[j] != m) continue;
// Check if the segments touch.
const float* vc = &tile->verts[poly->verts[j]*3];
const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3];
calcSlabEndPoints(vc,vd, bmin,bmax, side);
if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue;
// Add return value.
if (n < maxcon)
{
conarea[n*2+0] = dtMax(amin[0], bmin[0]);
conarea[n*2+1] = dtMin(amax[0], bmax[0]);
con[n] = base | (dtPolyRef)i;
n++;
}
break;
}
}
return n;
}
示例6: dtMin
dtStatus dtPathQueue::getPathResult(dtPathQueueRef ref, dtPolyRef* path, int* pathSize, const int maxPath)
{
for (int i = 0; i < MAX_QUEUE; ++i)
{
if (m_queue[i].ref == ref)
{
PathQuery& q = m_queue[i];
// Free request for reuse.
q.ref = DT_PATHQ_INVALID;
q.status = 0;
// Copy path
int n = dtMin(q.npath, maxPath);
memcpy(path, q.path, sizeof(dtPolyRef)*n);
*pathSize = n;
return DT_SUCCESS;
}
}
return DT_FAILURE;
}
示例7: memcpy
dtStatus dtNavMesh::init(const dtNavMeshParams* params)
{
memcpy(&m_params, params, sizeof(dtNavMeshParams));
dtVcopy(m_orig, params->orig);
m_tileWidth = params->tileWidth;
m_tileHeight = params->tileHeight;
// Init tiles
m_maxTiles = params->maxTiles;
m_tileLutSize = dtNextPow2(params->maxTiles/4);
if (!m_tileLutSize) m_tileLutSize = 1;
m_tileLutMask = m_tileLutSize-1;
m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM);
if (!m_tiles)
return DT_FAILURE | DT_OUT_OF_MEMORY;
m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM);
if (!m_posLookup)
return DT_FAILURE | DT_OUT_OF_MEMORY;
memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles);
memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize);
m_nextFree = 0;
for (int i = m_maxTiles-1; i >= 0; --i)
{
m_tiles[i].salt = 1;
m_tiles[i].next = m_nextFree;
m_nextFree = &m_tiles[i];
}
// 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;
}
示例8: dtMin
void SPARSE_SDF::hashTriangle(TRIANGLE& triangle, map<int, vector<TRIANGLE*> >& tempHash)
{
VEC3F mins, maxs;
triangle.boundingBox(mins, maxs);
MyVec3 dtMin(mins[0], mins[1], mins[2]);
MyVec3 dtMax(maxs[0], maxs[1], maxs[2]);
Index iMins[3];
Index iMaxs[3];
_grid->boundingBoxIndices(dtMin, dtMax, iMins, iMaxs);
for(Index z = iMins[2]; z <= iMaxs[2]; z++)
for (Index y = iMins[1]; y <= iMaxs[1]; y++)
for (Index x = iMins[0]; x <= iMaxs[0]; x++){
MyLocator loc;
bool gridExist = _grid->getLocator(x, y, z, &loc);
if(gridExist)
tempHash[loc.iv3D].push_back(&triangle);
}
}
示例9: if
void dtLocalBoundary::addSegment(const float dist, const float* s)
{
// Insert neighbour based on the distance.
Segment* seg = 0;
if (!m_nsegs)
{
// First, trivial accept.
seg = &m_segs[0];
}
else if (dist >= m_segs[m_nsegs-1].d)
{
// Further than the last segment, skip.
if (m_nsegs >= MAX_LOCAL_SEGS)
return;
// Last, trivial accept.
seg = &m_segs[m_nsegs];
}
else
{
// Insert inbetween.
int i;
for (i = 0; i < m_nsegs; ++i)
if (dist <= m_segs[i].d)
break;
const int tgt = i+1;
const int n = dtMin(m_nsegs-i, MAX_LOCAL_SEGS-tgt);
dtAssert(tgt+n <= MAX_LOCAL_SEGS);
if (n > 0)
memmove(&m_segs[tgt], &m_segs[i], sizeof(Segment)*n);
seg = &m_segs[i];
}
seg->d = dist;
memcpy(seg->s, s, sizeof(float)*6);
if (m_nsegs < MAX_LOCAL_SEGS)
m_nsegs++;
}
示例10: dtMergeCorridorEndMoved
int dtMergeCorridorEndMoved(dtPolyRef* path, const int npath, const int maxPath,
const dtPolyRef* visited, const int nvisited)
{
int furthestPath = -1;
int furthestVisited = -1;
// Find furthest common polygon.
for (int i = 0; i < npath; ++i)
{
bool found = false;
for (int j = nvisited-1; j >= 0; --j)
{
if (path[i] == visited[j])
{
furthestPath = i;
furthestVisited = j;
found = true;
}
}
if (found)
break;
}
// If no intersection found just return current path.
if (furthestPath == -1 || furthestVisited == -1)
return npath;
// Concatenate paths.
const int ppos = furthestPath+1;
const int vpos = furthestVisited+1;
const int count = dtMin(nvisited-vpos, maxPath-ppos);
dtAssert(ppos+count <= maxPath);
if (count)
memcpy(path+ppos, visited+vpos, sizeof(dtPolyRef)*count);
return ppos+count;
}
示例11: dtAssert
/**
@par
Inaccurate locomotion or dynamic obstacle avoidance can force the argent position significantly outside the
original corridor. Over time this can result in the formation of a non-optimal corridor. Non-optimal paths can
also form near the corners of tiles.
This function uses an efficient local visibility search to try to optimize the corridor
between the current position and @p next.
The corridor will change only if @p next is visible from the current position and moving directly toward the point
is better than following the existing path.
The more inaccurate the agent movement, the more beneficial this function becomes. Simply adjust the frequency
of the call to match the needs to the agent.
This function is not suitable for long distance searches.
*/
bool dtPathCorridor::optimizePathVisibility(const float* next, const float pathOptimizationRange,
dtNavMeshQuery* navquery, const dtQueryFilter* filter)
{
dtAssert(m_path);
// Clamp the ray to max distance.
float goal[3];
dtVcopy(goal, next);
float dist = dtVdist2D(m_pos, goal);
// If too close to the goal, do not try to optimize.
if (dist < 0.01f)
return true;
// Overshoot a little. This helps to optimize open fields in tiled meshes.
// UE4: changes to ray adjustment - make sure it's not going further than newDist
float newDist = dtMin(dist+0.01f, pathOptimizationRange);
// Adjust ray length.
float delta[3];
dtVsub(delta, goal, m_pos);
dtVmad(goal, m_pos, delta, newDist / dist);
static const int MAX_RES = 32;
dtPolyRef res[MAX_RES];
float t, norm[3];
int nres = 0;
navquery->raycast(m_path[0], m_pos, goal, filter, &t, norm, res, &nres, MAX_RES);
if (nres > 1 && t > 0.99f)
{
m_npath = dtMergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, nres);
return true;
}
return false;
}
示例12: duDebugDrawNavMeshNodes
void CrowdTool::handleRender()
{
DebugDrawGL dd;
const float s = m_sample->getAgentRadius();
dtNavMesh* nmesh = m_sample->getNavMesh();
if (!nmesh)
return;
dtNavMeshQuery* navquery = m_sample->getNavMeshQuery();
if (m_showNodes)
{
if (navquery)
duDebugDrawNavMeshNodes(&dd, *navquery);
}
dd.depthMask(false);
// Draw paths
if (m_showPath)
{
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
{
const Agent* ag = m_crowd.getAgent(i);
if (!ag->active) continue;
const dtPolyRef* path = ag->corridor.getPath();
const int npath = ag->corridor.getPathCount();
for (int i = 0; i < npath; ++i)
duDebugDrawNavMeshPoly(&dd, *nmesh, path[i], duRGBA(0,0,0,32));
}
}
if (m_targetRef)
duDebugDrawCross(&dd, m_targetPos[0],m_targetPos[1]+0.1f,m_targetPos[2], s, duRGBA(255,255,255,192), 2.0f);
// Occupancy grid.
if (m_showGrid)
{
float gridy = -FLT_MAX;
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
{
const Agent* ag = m_crowd.getAgent(i);
if (!ag->active) continue;
const float* pos = ag->corridor.getPos();
gridy = dtMax(gridy, pos[1]);
}
gridy += 1.0f;
dd.begin(DU_DRAW_QUADS);
const ProximityGrid* grid = m_crowd.getGrid();
const int* bounds = grid->getBounds();
const float cs = grid->getCellSize();
for (int y = bounds[1]; y <= bounds[3]; ++y)
{
for (int x = bounds[0]; x <= bounds[2]; ++x)
{
const int count = grid->getItemCountAt(x,y);
if (!count) continue;
unsigned int col = duRGBA(128,0,0,dtMin(count*40,255));
dd.vertex(x*cs, gridy, y*cs, col);
dd.vertex(x*cs, gridy, y*cs+cs, col);
dd.vertex(x*cs+cs, gridy, y*cs+cs, col);
dd.vertex(x*cs+cs, gridy, y*cs, col);
}
}
dd.end();
}
// Trail
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
{
const Agent* ag = m_crowd.getAgent(i);
if (!ag->active) continue;
const float* pos = ag->npos;
dd.begin(DU_DRAW_LINES,3.0f);
float prev[3], preva = 1;
dtVcopy(prev, pos);
for (int j = 0; j < AGENT_MAX_TRAIL-1; ++j)
{
const int idx = (ag->htrail + AGENT_MAX_TRAIL-j) % AGENT_MAX_TRAIL;
const float* v = &ag->trail[idx*3];
float a = 1 - j/(float)AGENT_MAX_TRAIL;
dd.vertex(prev[0],prev[1]+0.1f,prev[2], duRGBA(0,0,0,(int)(128*preva)));
dd.vertex(v[0],v[1]+0.1f,v[2], duRGBA(0,0,0,(int)(128*a)));
preva = a;
dtVcopy(prev, v);
}
dd.end();
}
// Corners & co
for (int i = 0; i < m_crowd.getAgentCount(); ++i)
{
const Agent* ag = m_crowd.getAgent(i);
if (!ag->active) continue;
//.........这里部分代码省略.........
示例13: dtVscale
float dtObstacleAvoidanceQuery::processSample(const float* vcand, const float cs,
const float* pos, const float rad,
const float vmax, const float* vel, const float* dvel,
dtObstacleAvoidanceDebugData* debug)
{
// Find min time of impact and exit amongst all obstacles.
float tmin = m_horizTime;
float side = 0;
int nside = 0;
for (int i = 0; i < m_ncircles; ++i)
{
const dtObstacleCircle* cir = &m_circles[i];
// RVO
float vab[3];
dtVscale(vab, vcand, 2);
dtVsub(vab, vab, vel);
dtVsub(vab, vab, cir->vel);
// Side
side += dtClamp(dtMin(dtVdot2D(cir->dp,vab)*0.5f+0.5f, dtVdot2D(cir->np,vab)*2), 0.0f, 1.0f);
nside++;
float htmin = 0, htmax = 0;
if (!sweepCircleCircle(pos,rad, vab, cir->p,cir->rad, htmin, htmax))
continue;
// Handle overlapping obstacles.
if (htmin < 0.0f && htmax > 0.0f)
{
// Avoid more when overlapped.
htmin = -htmin * 0.5f;
}
if (htmin >= 0.0f)
{
// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
if (htmin < tmin)
tmin = htmin;
}
}
for (int i = 0; i < m_nsegments; ++i)
{
const dtObstacleSegment* seg = &m_segments[i];
float htmin = 0;
if (seg->touch)
{
// Special case when the agent is very close to the segment.
float sdir[3], snorm[3];
dtVsub(sdir, seg->q, seg->p);
snorm[0] = -sdir[2];
snorm[2] = sdir[0];
// If the velocity is pointing towards the segment, no collision.
if (dtVdot2D(snorm, vcand) < 0.0f)
continue;
// Else immediate collision.
htmin = 0.0f;
}
else
{
if (!isectRaySeg(pos, vcand, seg->p, seg->q, htmin))
continue;
}
// Avoid less when facing walls.
htmin *= 2.0f;
// The closest obstacle is somewhere ahead of us, keep track of nearest obstacle.
if (htmin < tmin)
tmin = htmin;
}
// Normalize side bias, to prevent it dominating too much.
if (nside)
side /= nside;
const float ivmax = 1.0f / vmax;
const float vpen = m_weightDesVel * (dtVdist2D(vcand, dvel) * ivmax);
const float vcpen = m_weightCurVel * (dtVdist2D(vcand, vel) * ivmax);
const float spen = m_weightSide * side;
const float tpen = m_weightToi * (1.0f/(0.1f+tmin / m_horizTime));
const float penalty = vpen + vcpen + spen + tpen;
// Store different penalties for debug viewing
if (debug)
debug->addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen);
return penalty;
}
示例14: be
/**
@par
This is the function used to plan local movement within the corridor. One or more corners can be
detected in order to plan movement. It performs essentially the same function as #dtNavMeshQuery::findStraightPath.
Due to internal optimizations, the maximum number of corners returned will be (@p maxCorners - 1)
For example: If the buffers are sized to hold 10 corners, the function will never return more than 9 corners.
So if 10 corners are needed, the buffers should be sized for 11 corners.
If the target is within range, it will be the last corner and have a polygon reference id of zero.
*/
int dtPathCorridor::findCorners(float* cornerVerts, unsigned char* cornerFlags,
dtPolyRef* cornerPolys, const int maxCorners,
dtNavMeshQuery* navquery, const dtQueryFilter* filter,
float radius)
{
dtAssert(m_path);
dtAssert(m_npath);
static const float MIN_TARGET_DIST = 0.01f;
dtQueryResult result;
navquery->findStraightPath(m_pos, m_target, m_path, m_npath, result);
int ncorners = dtMin(result.size(), maxCorners);
result.copyRefs(cornerPolys, maxCorners);
result.copyFlags(cornerFlags, maxCorners);
result.copyPos(cornerVerts, maxCorners);
// Prune points in the beginning of the path which are too close.
while (ncorners)
{
if ((cornerFlags[0] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
dtVdist2DSqr(&cornerVerts[0], m_pos) > dtSqr(MIN_TARGET_DIST))
break;
ncorners--;
if (ncorners)
{
memmove(cornerFlags, cornerFlags+1, sizeof(unsigned char)*ncorners);
memmove(cornerPolys, cornerPolys+1, sizeof(dtPolyRef)*ncorners);
memmove(cornerVerts, cornerVerts+3, sizeof(float)*3*ncorners);
}
}
// Prune points after an off-mesh connection.
for (int i = 0; i < ncorners; ++i)
{
if (cornerFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION)
{
ncorners = i+1;
break;
}
}
// [UE4] Offset path points from corners
const dtNavMesh* nav = navquery->getAttachedNavMesh();
float v1[3], v2[3], dir[3];
for (int i = 0; i < ncorners - 1; i++)
{
int fromIdx = 0;
while (m_path[fromIdx] != cornerPolys[i] && fromIdx < m_npath)
{
fromIdx++;
}
if (m_path[fromIdx] != cornerPolys[i] || fromIdx == 0)
continue;
const dtMeshTile* tile0 = 0;
const dtMeshTile* tile1 = 0;
const dtPoly* poly0 = 0;
const dtPoly* poly1 = 0;
nav->getTileAndPolyByRefUnsafe(m_path[fromIdx - 1], &tile0, &poly0);
nav->getTileAndPolyByRefUnsafe(m_path[fromIdx], &tile1, &poly1);
if (tile0 != tile1)
continue;
float* corner = &cornerVerts[i * 3];
unsigned char dummyT1, dummyT2;
navquery->getPortalPoints(m_path[fromIdx - 1], m_path[fromIdx], v1, v2, dummyT1, dummyT2);
const float edgeLen = dtVdist(v1, v2);
if (edgeLen > 0.001f)
{
const float edgeOffset = dtMin(radius, edgeLen * 0.75f) / edgeLen;
if (dtVequal(corner, v1))
{
dtVsub(dir, v2, v1);
dtVmad(corner, corner, dir, edgeOffset);
}
else
{
dtVsub(dir, v1, v2);
dtVmad(corner, corner, dir, edgeOffset);
//.........这里部分代码省略.........
示例15: dtCreateNavMeshData
/// @par
///
/// The output data array is allocated using the detour allocator (dtAlloc()). The method
/// used to free the memory will be determined by how the tile is added to the navigation
/// mesh.
///
/// @see dtNavMesh, dtNavMesh::addTile()
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize)
{
if (params->nvp > DT_VERTS_PER_POLYGON)
return false;
if (params->vertCount >= 0xffff)
return false;
if (!params->vertCount || !params->verts)
return false;
if (!params->polyCount || !params->polys)
return false;
const int nvp = params->nvp;
// Classify off-mesh connection points. We store only the connections
// whose start point is inside the tile.
unsigned char* offMeshConClass = 0;
int storedOffMeshConCount = 0;
int offMeshConLinkCount = 0;
if (params->offMeshConCount > 0)
{
offMeshConClass = (unsigned char*)dtAlloc(sizeof(unsigned char)*params->offMeshConCount*2, DT_ALLOC_TEMP);
if (!offMeshConClass)
return false;
// Find tight heigh bounds, used for culling out off-mesh start locations.
float hmin = FLT_MAX;
float hmax = -FLT_MAX;
if (params->detailVerts && params->detailVertsCount)
{
for (int i = 0; i < params->detailVertsCount; ++i)
{
const float h = params->detailVerts[i*3+1];
hmin = dtMin(hmin,h);
hmax = dtMax(hmax,h);
}
}
else
{
for (int i = 0; i < params->vertCount; ++i)
{
const unsigned short* iv = ¶ms->verts[i*3];
const float h = params->bmin[1] + iv[1] * params->ch;
hmin = dtMin(hmin,h);
hmax = dtMax(hmax,h);
}
}
hmin -= params->walkableClimb;
hmax += params->walkableClimb;
float bmin[3], bmax[3];
dtVcopy(bmin, params->bmin);
dtVcopy(bmax, params->bmax);
bmin[1] = hmin;
bmax[1] = hmax;
for (int i = 0; i < params->offMeshConCount; ++i)
{
const float* p0 = ¶ms->offMeshConVerts[(i*2+0)*3];
const float* p1 = ¶ms->offMeshConVerts[(i*2+1)*3];
offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax);
offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax);
// Zero out off-mesh start positions which are not even potentially touching the mesh.
if (offMeshConClass[i*2+0] == 0xff)
{
if (p0[1] < bmin[1] || p0[1] > bmax[1])
offMeshConClass[i*2+0] = 0;
}
// Cound how many links should be allocated for off-mesh connections.
if (offMeshConClass[i*2+0] == 0xff)
offMeshConLinkCount++;
if (offMeshConClass[i*2+1] == 0xff)
offMeshConLinkCount++;
if (offMeshConClass[i*2+0] == 0xff)
storedOffMeshConCount++;
}
}
// Off-mesh connectionss are stored as polygons, adjust values.
const int totPolyCount = params->polyCount + storedOffMeshConCount;
const int totVertCount = params->vertCount + storedOffMeshConCount*2;
// Find portal edges which are at tile borders.
int edgeCount = 0;
int portalCount = 0;
for (int i = 0; i < params->polyCount; ++i)
{
const unsigned short* p = ¶ms->polys[i*2*nvp];
for (int j = 0; j < nvp; ++j)
{
//.........这里部分代码省略.........