Take detail mesh into account for creating BV-tree (#231)
In U and A shaped terrain it was possible that polygons extruded their BV-tree nodes significantly. This happened because all points for the polygon (when excluding the detail mesh) were either on the high-level terrain, or on the low-level terrain. This fixes the long-standing todo about this. As a result of this change, findNearestPoly and queryPolygons should return more accurate results. Fix #230
This commit is contained in:
parent
88b8d409a7
commit
15ebb8bd25
@ -168,45 +168,72 @@ static void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int createBVTree(const unsigned short* verts, const int /*nverts*/,
|
static int createBVTree(dtNavMeshCreateParams* params, dtBVNode* nodes, int /*nnodes*/)
|
||||||
const unsigned short* polys, const int npolys, const int nvp,
|
|
||||||
const float cs, const float ch,
|
|
||||||
const int /*nnodes*/, dtBVNode* nodes)
|
|
||||||
{
|
{
|
||||||
// Build tree
|
// Build tree
|
||||||
BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP);
|
float quantFactor = 1 / params->cs;
|
||||||
for (int i = 0; i < npolys; i++)
|
BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*params->polyCount, DT_ALLOC_TEMP);
|
||||||
|
for (int i = 0; i < params->polyCount; i++)
|
||||||
{
|
{
|
||||||
BVItem& it = items[i];
|
BVItem& it = items[i];
|
||||||
it.i = i;
|
it.i = i;
|
||||||
// Calc polygon bounds.
|
// Calc polygon bounds. Use detail meshes if available.
|
||||||
const unsigned short* p = &polys[i*nvp*2];
|
if (params->detailMeshes)
|
||||||
it.bmin[0] = it.bmax[0] = verts[p[0]*3+0];
|
|
||||||
it.bmin[1] = it.bmax[1] = verts[p[0]*3+1];
|
|
||||||
it.bmin[2] = it.bmax[2] = verts[p[0]*3+2];
|
|
||||||
|
|
||||||
for (int j = 1; j < nvp; ++j)
|
|
||||||
{
|
{
|
||||||
if (p[j] == MESH_NULL_IDX) break;
|
int vb = (int)params->detailMeshes[i*4+0];
|
||||||
unsigned short x = verts[p[j]*3+0];
|
int ndv = (int)params->detailMeshes[i*4+1];
|
||||||
unsigned short y = verts[p[j]*3+1];
|
float bmin[3];
|
||||||
unsigned short z = verts[p[j]*3+2];
|
float bmax[3];
|
||||||
|
|
||||||
if (x < it.bmin[0]) it.bmin[0] = x;
|
const float* dv = ¶ms->detailVerts[vb*3];
|
||||||
if (y < it.bmin[1]) it.bmin[1] = y;
|
dtVcopy(bmin, dv);
|
||||||
if (z < it.bmin[2]) it.bmin[2] = z;
|
dtVcopy(bmax, dv);
|
||||||
|
|
||||||
if (x > it.bmax[0]) it.bmax[0] = x;
|
for (int j = 1; j < ndv; j++)
|
||||||
if (y > it.bmax[1]) it.bmax[1] = y;
|
{
|
||||||
if (z > it.bmax[2]) it.bmax[2] = z;
|
dtVmin(bmin, &dv[j * 3]);
|
||||||
|
dtVmax(bmax, &dv[j * 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BV-tree uses cs for all dimensions
|
||||||
|
it.bmin[0] = (unsigned short)dtClamp((int)((bmin[0] - params->bmin[0])*quantFactor), 0, 0xffff);
|
||||||
|
it.bmin[1] = (unsigned short)dtClamp((int)((bmin[1] - params->bmin[1])*quantFactor), 0, 0xffff);
|
||||||
|
it.bmin[2] = (unsigned short)dtClamp((int)((bmin[2] - params->bmin[2])*quantFactor), 0, 0xffff);
|
||||||
|
|
||||||
|
it.bmax[0] = (unsigned short)dtClamp((int)((bmax[0] - params->bmin[0])*quantFactor), 0, 0xffff);
|
||||||
|
it.bmax[1] = (unsigned short)dtClamp((int)((bmax[1] - params->bmin[1])*quantFactor), 0, 0xffff);
|
||||||
|
it.bmax[2] = (unsigned short)dtClamp((int)((bmax[2] - params->bmin[2])*quantFactor), 0, 0xffff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const unsigned short* p = ¶ms->polys[i*params->nvp * 2];
|
||||||
|
it.bmin[0] = it.bmax[0] = params->verts[p[0] * 3 + 0];
|
||||||
|
it.bmin[1] = it.bmax[1] = params->verts[p[0] * 3 + 1];
|
||||||
|
it.bmin[2] = it.bmax[2] = params->verts[p[0] * 3 + 2];
|
||||||
|
|
||||||
|
for (int j = 1; j < params->nvp; ++j)
|
||||||
|
{
|
||||||
|
if (p[j] == MESH_NULL_IDX) break;
|
||||||
|
unsigned short x = params->verts[p[j] * 3 + 0];
|
||||||
|
unsigned short y = params->verts[p[j] * 3 + 1];
|
||||||
|
unsigned short z = params->verts[p[j] * 3 + 2];
|
||||||
|
|
||||||
|
if (x < it.bmin[0]) it.bmin[0] = x;
|
||||||
|
if (y < it.bmin[1]) it.bmin[1] = y;
|
||||||
|
if (z < it.bmin[2]) it.bmin[2] = z;
|
||||||
|
|
||||||
|
if (x > it.bmax[0]) it.bmax[0] = x;
|
||||||
|
if (y > it.bmax[1]) it.bmax[1] = y;
|
||||||
|
if (z > it.bmax[2]) it.bmax[2] = z;
|
||||||
|
}
|
||||||
|
// Remap y
|
||||||
|
it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1] * params->ch / params->cs);
|
||||||
|
it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1] * params->ch / params->cs);
|
||||||
}
|
}
|
||||||
// Remap y
|
|
||||||
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;
|
int curNode = 0;
|
||||||
subdivide(items, npolys, 0, npolys, curNode, nodes);
|
subdivide(items, params->polyCount, 0, params->polyCount, curNode, nodes);
|
||||||
|
|
||||||
dtFree(items);
|
dtFree(items);
|
||||||
|
|
||||||
@ -595,11 +622,9 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store and create BVtree.
|
// Store and create BVtree.
|
||||||
// TODO: take detail mesh into account! use byte per bbox extent?
|
|
||||||
if (params->buildBvTree)
|
if (params->buildBvTree)
|
||||||
{
|
{
|
||||||
createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
|
createBVTree(params, navBvtree, 2*params->polyCount);
|
||||||
nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store Off-Mesh connections.
|
// Store Off-Mesh connections.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user