- (too) large refactoring of the generation and demo code to support tiled preprocessing
- added rcFixupAdjacentContours which adjust adjacent contour sets so that that they share all vertices (still buggy!) - changed the demo stucture to handle tiled navmesh generation process (still ugly) - the performance results are put into a struct instead of logged immediatelly - added ChunkyTriMesh class which allows to partiotion a trimesh to smaller pieces using AABB tree
This commit is contained in:
parent
dac9bc0f64
commit
c56ebb7e77
@ -61,8 +61,8 @@ static int compareItemZ(const void* va, const void* vb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void calcExtends(BVItem* items, int nitems, int imin, int imax,
|
||||
unsigned short* bmin, unsigned short* bmax)
|
||||
static void calcExtends(BVItem* items, int nitems, int imin, int imax,
|
||||
unsigned short* bmin, unsigned short* bmax)
|
||||
{
|
||||
bmin[0] = items[imin].bmin[0];
|
||||
bmin[1] = items[imin].bmin[1];
|
||||
@ -160,21 +160,10 @@ void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNode, dtBV
|
||||
}
|
||||
}
|
||||
|
||||
/*struct rcPolyMesh
|
||||
{
|
||||
inline rcPolyMesh() : verts(0), polys(0), nverts(0), npolys(0), nvp(3) {}
|
||||
inline ~rcPolyMesh() { delete [] verts; delete [] polys; }
|
||||
unsigned short* verts;
|
||||
unsigned short* polys;
|
||||
int nverts;
|
||||
int npolys;
|
||||
int nvp;
|
||||
};*/
|
||||
|
||||
int createBVTree(const unsigned short* verts, const int nverts,
|
||||
const unsigned short* polys, const int npolys, const int nvp,
|
||||
float cs, float ch,
|
||||
int nnodes, dtBVNode* nodes)
|
||||
static int createBVTree(const unsigned short* verts, const int nverts,
|
||||
const unsigned short* polys, const int npolys, const int nvp,
|
||||
float cs, float ch,
|
||||
int nnodes, dtBVNode* nodes)
|
||||
{
|
||||
// Build tree
|
||||
BVItem* items = new BVItem[npolys];
|
||||
@ -224,6 +213,11 @@ bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
|
||||
{
|
||||
if (nvp != DT_VERTS_PER_POLYGON)
|
||||
return false;
|
||||
|
||||
if (!nverts)
|
||||
return false;
|
||||
if (!npolys)
|
||||
return false;
|
||||
|
||||
// Calculate data size
|
||||
const int headerSize = sizeof(dtStatNavMeshHeader);
|
||||
|
@ -22,6 +22,8 @@
|
||||
struct rcConfig
|
||||
{
|
||||
int width, height; // Dimensions of the rasterized heighfield
|
||||
int tileSize; // Size if a tile.
|
||||
int borderSize; // Non-navigable Border around the heightfield.
|
||||
float cs, ch; // Grid cell size and height.
|
||||
float bmin[3], bmax[3]; // Grid bounds.
|
||||
float walkableSlopeAngle; // Maximum walkble slope angle in degrees.
|
||||
@ -43,6 +45,8 @@ struct rcSpan
|
||||
rcSpan* next;
|
||||
};
|
||||
|
||||
static const int RC_SPANS_PER_POOL = 2048;
|
||||
|
||||
struct rcSpanPool
|
||||
{
|
||||
rcSpanPool* next;
|
||||
@ -93,8 +97,7 @@ struct rcCompactHeightfield
|
||||
int walkableHeight, walkableClimb;
|
||||
unsigned short maxDistance;
|
||||
unsigned short maxRegions;
|
||||
float minx, miny, minz;
|
||||
float maxx, maxy, maxz;
|
||||
float bmin[3], bmax[3];
|
||||
float cs, ch;
|
||||
rcCompactCell* cells;
|
||||
rcCompactSpan* spans;
|
||||
@ -102,13 +105,12 @@ struct rcCompactHeightfield
|
||||
|
||||
struct rcContour
|
||||
{
|
||||
inline rcContour() : verts(0), nverts(0), rverts(0), nrverts(0), cx(0), cy(0), cz(0) { }
|
||||
inline rcContour() : verts(0), nverts(0), rverts(0), nrverts(0) { }
|
||||
inline ~rcContour() { delete [] verts; delete [] rverts; }
|
||||
int* verts;
|
||||
int nverts;
|
||||
int* rverts;
|
||||
int nrverts;
|
||||
int cx,cy,cz;
|
||||
unsigned short reg;
|
||||
};
|
||||
|
||||
@ -129,6 +131,8 @@ struct rcPolyMesh
|
||||
int nverts;
|
||||
int npolys;
|
||||
int nvp;
|
||||
float bmin[3], bmax[3];
|
||||
float cs, ch;
|
||||
};
|
||||
|
||||
class rcIntArray
|
||||
@ -257,7 +261,7 @@ void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax);
|
||||
// cs - (in) grid cell size
|
||||
// w - (out) grid width
|
||||
// h - (out) grid height
|
||||
void rcCalcGridSize(float* bmin, float* bmax, float cs, int* w, int* h);
|
||||
void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h);
|
||||
|
||||
// Creates and initializes new heightfield.
|
||||
// Params:
|
||||
@ -270,12 +274,14 @@ bool rcCreateHeightfield(rcHeightfield& hf, int width, int height);
|
||||
// the maximun walkable slope angle.
|
||||
// Params:
|
||||
// walkableSlopeAngle - (in) maximun slope angle in degrees.
|
||||
// verts - (in) array of vertices
|
||||
// nv - (in) vertex count
|
||||
// tris - (in) array of triangle vertex indices
|
||||
// norms - (in) array of triangle normals
|
||||
// nt - (in) triangle count
|
||||
// flags - (out) array of triangle flags
|
||||
void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
const int* tris, const float* norms, int nt,
|
||||
const float* verts, int nv,
|
||||
const int* tris, int nt,
|
||||
unsigned char* flags);
|
||||
|
||||
// Rasterizes the triangles into heightfield spans.
|
||||
@ -356,7 +362,7 @@ bool rcBuildDistanceField(rcCompactHeightfield& chf);
|
||||
// maxMergeRegionSize - (in) the largest allowed regions size which can be merged.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildRegions(rcCompactHeightfield& chf,
|
||||
int walkableRadius, int minRegionSize, int mergeRegionSize);
|
||||
int walkableRadius, int borderSize, int minRegionSize, int mergeRegionSize);
|
||||
|
||||
// Builds simplified contours from the regions outlines.
|
||||
// Params:
|
||||
@ -369,14 +375,36 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
float maxError, int maxEdgeLen,
|
||||
rcContourSet& cset);
|
||||
|
||||
// Ensures that connected contour sets A and B share the same vertices at the shared edges.
|
||||
// Params:
|
||||
// cseta - (in) contour set A.
|
||||
// csetb - (in) contour set B.
|
||||
// edge - (in) which edge to conform: 1) B is left of A 2) B is top of A
|
||||
// borderSize - (in) the border which was used when the contours were generated.
|
||||
// tileSize - (in) the tile size which was used when the contours were generated.
|
||||
// orig - (in) origin of the contour set A.
|
||||
// cs - (in) grid cell size
|
||||
// ch - (in) grid cell height
|
||||
bool rcFixupAdjacentContours(rcContourSet* cseta, rcContourSet* csetb, int edge, int edgePos);
|
||||
|
||||
// Translates the cordinates of the contour set.
|
||||
// Params:
|
||||
// cset - (in) contour set to translate.
|
||||
// dx - (in) delta X.
|
||||
// dy - (in) delta Y.
|
||||
// dz - (in) delta Z.
|
||||
void rcTranslateContours(rcContourSet* cset, int dx, int dy, int dz);
|
||||
|
||||
// Builds connected convex polygon mesh from contour polygons.
|
||||
// Params:
|
||||
// cset - (in) contour set.
|
||||
// mesh - (out) poly mesh.
|
||||
// nvp - (int) maximum number of vertices per polygon.
|
||||
// Returns false if operation ran out of memory.
|
||||
bool rcBuildPolyMesh(rcContourSet& cset, rcPolyMesh& mesh, int nvp);
|
||||
|
||||
bool rcBuildPolyMesh(rcContourSet& cset,
|
||||
const float* bmin, const float* bmax,
|
||||
const float cs, const float ch, int nvp,
|
||||
rcPolyMesh& mesh);
|
||||
|
||||
bool rcBuildNavMesh(const rcConfig& cfg,
|
||||
const float* verts, const int nverts,
|
||||
|
@ -48,7 +48,7 @@ void rcDebugDrawCompactHeightfieldDistance(const struct rcCompactHeightfield& ch
|
||||
|
||||
void rcDebugDrawRawContours(const struct rcContourSet& cset, const float* orig, float cs, float ch);
|
||||
void rcDebugDrawContours(const struct rcContourSet& cset, const float* orig, float cs, float ch);
|
||||
void rcDebugDrawPolyMesh(const struct rcPolyMesh& mesh, const float* orig, float cs, float ch);
|
||||
void rcDebugDrawPolyMesh(const struct rcPolyMesh& mesh);
|
||||
|
||||
void rcDebugDrawCylinderWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, const float* col);
|
||||
void rcDebugDrawBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, const float* col);
|
||||
|
@ -47,7 +47,32 @@ private:
|
||||
int m_textPoolSize;
|
||||
};
|
||||
|
||||
struct rcBuildTimes
|
||||
{
|
||||
int rasterizeTriangles;
|
||||
int buildCompact;
|
||||
int buildContours;
|
||||
int buildContoursTrace;
|
||||
int buildContoursSimplify;
|
||||
int filterBorder;
|
||||
int filterWalkable;
|
||||
int filterMarkReachable;
|
||||
int buildPolymesh;
|
||||
int buildDistanceField;
|
||||
int buildDistanceFieldDist;
|
||||
int buildDistanceFieldBlur;
|
||||
int buildRegions;
|
||||
int buildRegionsReg;
|
||||
int buildRegionsExp;
|
||||
int buildRegionsFlood;
|
||||
int buildRegionsFilter;
|
||||
int fixupContours;
|
||||
};
|
||||
|
||||
void rcSetLog(rcLog* log);
|
||||
rcLog* rcGetLog();
|
||||
|
||||
void rcSetBuildTimes(rcBuildTimes* btimes);
|
||||
rcBuildTimes* rcGetBuildTimes();
|
||||
|
||||
#endif // RECAST_LOG_H
|
||||
|
@ -54,7 +54,7 @@ void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
|
||||
}
|
||||
}
|
||||
|
||||
void rcCalcGridSize(float* bmin, float* bmax, float cs, int* w, int* h)
|
||||
void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h)
|
||||
{
|
||||
*w = (int)((bmax[0] - bmin[0])/cs+0.5f);
|
||||
*h = (int)((bmax[2] - bmin[2])/cs+0.5f);
|
||||
@ -71,7 +71,7 @@ bool rcCreateHeightfield(rcHeightfield& hf, int width, int height)
|
||||
return true;
|
||||
}
|
||||
|
||||
void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
/*void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
const int* tris, const float* norms, int nt,
|
||||
unsigned char* flags)
|
||||
{
|
||||
@ -83,6 +83,34 @@ void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
if (norms[i*3+1] > walkableThr)
|
||||
flags[i] |= RC_WALKABLE;
|
||||
}
|
||||
}*/
|
||||
|
||||
static void calcTriNormal(const float* v0, const float* v1, const float* v2, float* norm)
|
||||
{
|
||||
float e0[3], e1[3];
|
||||
vsub(e0, v1, v0);
|
||||
vsub(e1, v2, v0);
|
||||
vcross(norm, e0, e1);
|
||||
vnormalize(norm);
|
||||
}
|
||||
|
||||
void rcMarkWalkableTriangles(const float walkableSlopeAngle,
|
||||
const float* verts, int nv,
|
||||
const int* tris, int nt,
|
||||
unsigned char* flags)
|
||||
{
|
||||
const float walkableThr = cosf(walkableSlopeAngle/180.0f*(float)M_PI);
|
||||
|
||||
float norm[3];
|
||||
|
||||
for (int i = 0; i < nt; ++i)
|
||||
{
|
||||
const int* tri = &tris[i*3];
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] > walkableThr)
|
||||
flags[i] |= RC_WALKABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static int getSpanCount(unsigned char flags, rcHeightfield& hf)
|
||||
@ -129,12 +157,9 @@ bool rcBuildCompactHeightfield(const float* bmin, const float* bmax,
|
||||
chf.walkableHeight = walkableHeight;
|
||||
chf.walkableClimb = walkableClimb;
|
||||
chf.maxRegions = 0;
|
||||
chf.minx = bmin[0];
|
||||
chf.miny = bmin[1];
|
||||
chf.minz = bmin[2];
|
||||
chf.maxx = bmax[0];
|
||||
chf.maxy = bmax[1] + walkableHeight*ch;
|
||||
chf.maxz = bmax[2];
|
||||
vcopy(chf.bmin, bmin);
|
||||
vcopy(chf.bmax, bmax);
|
||||
chf.bmax[1] += walkableHeight*ch;
|
||||
chf.cs = cs;
|
||||
chf.ch = ch;
|
||||
chf.cells = new rcCompactCell[w*h];
|
||||
@ -226,12 +251,38 @@ bool rcBuildCompactHeightfield(const float* bmin, const float* bmax,
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Build compact: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Build compact: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->buildCompact += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int getHeightfieldMemoryUsage(const rcHeightfield& hf)
|
||||
{
|
||||
int size = 0;
|
||||
size += sizeof(hf);
|
||||
size += hf.width * hf.height * sizeof(rcSpan*);
|
||||
|
||||
rcSpanPool* pool = hf.pools;
|
||||
while (pool)
|
||||
{
|
||||
size += (sizeof(rcSpanPool) - sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL;
|
||||
pool = pool->next;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf)
|
||||
{
|
||||
int size = 0;
|
||||
size += sizeof(rcCompactHeightfield);
|
||||
size += sizeof(rcCompactSpan) * chf.spanCount;
|
||||
size += sizeof(rcCompactCell) * chf.width * chf.height;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool rcBuildNavMesh(const rcConfig& cfg,
|
||||
const float* verts, const int nverts,
|
||||
const int* tris, const unsigned char* tflags, const int ntris,
|
||||
@ -253,23 +304,23 @@ bool rcBuildNavMesh(const rcConfig& cfg,
|
||||
rcFilterWalkableBorderSpans(cfg.walkableHeight, cfg.walkableClimb, solid);
|
||||
|
||||
rcFilterWalkableLowHeightSpans(cfg.walkableHeight, solid);
|
||||
|
||||
if (!rcMarkReachableSpans(cfg.walkableHeight, cfg.walkableClimb, solid))
|
||||
|
||||
/* if (!rcMarkReachableSpans(cfg.walkableHeight, cfg.walkableClimb, solid))
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildNavMesh: Could not build navigable heightfield.");
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!rcBuildCompactHeightfield(cfg.bmin, cfg.bmax, cfg.cs, cfg.ch,
|
||||
cfg.walkableHeight, cfg.walkableClimb,
|
||||
RC_WALKABLE|RC_REACHABLE, solid, chf))
|
||||
RC_WALKABLE/*|RC_REACHABLE*/, solid, chf))
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildNavMesh: Could not build compact data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!rcBuildDistanceField(chf))
|
||||
{
|
||||
if (rcGetLog())
|
||||
@ -277,7 +328,7 @@ bool rcBuildNavMesh(const rcConfig& cfg,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rcBuildRegions(chf, cfg.walkableRadius, cfg.minRegionSize, cfg.mergeRegionSize))
|
||||
if (!rcBuildRegions(chf, cfg.walkableRadius, cfg.borderSize, cfg.minRegionSize, cfg.mergeRegionSize))
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildNavMesh: Could not build regions.");
|
||||
@ -291,7 +342,8 @@ bool rcBuildNavMesh(const rcConfig& cfg,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rcBuildPolyMesh(cset, polyMesh, cfg.maxVertsPerPoly))
|
||||
if (!rcBuildPolyMesh(cset, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch,
|
||||
cfg.maxVertsPerPoly, polyMesh))
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "rcBuildNavMesh: Could not triangulate contours.");
|
||||
|
@ -501,7 +501,7 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
return false;
|
||||
}
|
||||
|
||||
rcTimeVal boundaryStartTime = rcGetPerformanceTimer();
|
||||
rcTimeVal traceStartTime = rcGetPerformanceTimer();
|
||||
|
||||
// Mark boundaries.
|
||||
for (int y = 0; y < h; ++y)
|
||||
@ -513,7 +513,7 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
{
|
||||
unsigned char res = 0;
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
if (s.reg == 0)
|
||||
if (!s.reg || (s.reg & 0x8000))
|
||||
{
|
||||
flags[i] = 0;
|
||||
continue;
|
||||
@ -537,9 +537,9 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal boundaryEndTime = rcGetPerformanceTimer();
|
||||
rcTimeVal traceEndTime = rcGetPerformanceTimer();
|
||||
|
||||
rcTimeVal contourStartTime = rcGetPerformanceTimer();
|
||||
rcTimeVal simplifyStartTime = rcGetPerformanceTimer();
|
||||
|
||||
rcIntArray verts(256);
|
||||
rcIntArray simplified(64);
|
||||
@ -556,6 +556,9 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
flags[i] = 0;
|
||||
continue;
|
||||
}
|
||||
unsigned short reg = chf.spans[i].reg;
|
||||
if (!reg || (reg & 0x8000))
|
||||
continue;
|
||||
|
||||
verts.resize(0);
|
||||
simplified.resize(0);
|
||||
@ -564,7 +567,6 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
removeDegenerateSegments(simplified);
|
||||
|
||||
// Store region->contour remap info.
|
||||
unsigned short reg = chf.spans[i].reg;
|
||||
// Create contour.
|
||||
if (simplified.size()/4 >= 3)
|
||||
{
|
||||
@ -585,7 +587,7 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
cont->rverts = new int[cont->nrverts*4];
|
||||
memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4);
|
||||
|
||||
cont->cx = cont->cy = cont->cz = 0;
|
||||
/* cont->cx = cont->cy = cont->cz = 0;
|
||||
for (int i = 0; i < cont->nverts; ++i)
|
||||
{
|
||||
cont->cx += cont->verts[i*4+0];
|
||||
@ -594,7 +596,7 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
}
|
||||
cont->cx /= cont->nverts;
|
||||
cont->cy /= cont->nverts;
|
||||
cont->cz /= cont->nverts;
|
||||
cont->cz /= cont->nverts;*/
|
||||
|
||||
cont->reg = reg;
|
||||
}
|
||||
@ -647,19 +649,305 @@ bool rcBuildContours(rcCompactHeightfield& chf,
|
||||
}
|
||||
|
||||
|
||||
rcTimeVal contourEndTime = rcGetPerformanceTimer();
|
||||
|
||||
// Delete vertices.
|
||||
delete [] flags;
|
||||
|
||||
rcTimeVal simplifyEndTime = rcGetPerformanceTimer();
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
// if (rcGetLog())
|
||||
// {
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Create contours: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, " - boundary: %.3f ms", rcGetDeltaTimeUsec(boundaryStartTime, boundaryEndTime)/1000.0f);
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, " - contour: %.3f ms", rcGetDeltaTimeUsec(contourStartTime, contourEndTime)/1000.0f);
|
||||
// }
|
||||
|
||||
if (rcGetBuildTimes())
|
||||
{
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Create contours: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - boundary: %.3f ms", rcGetDeltaTimeUsec(boundaryStartTime, boundaryEndTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - contour: %.3f ms", rcGetDeltaTimeUsec(contourStartTime, contourEndTime)/1000.0f);
|
||||
rcGetBuildTimes()->buildContours += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
rcGetBuildTimes()->buildContoursTrace += rcGetDeltaTimeUsec(traceStartTime, traceEndTime);
|
||||
rcGetBuildTimes()->buildContoursSimplify += rcGetDeltaTimeUsec(simplifyStartTime, simplifyEndTime);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct EdgeSegment
|
||||
{
|
||||
int i0, i1;
|
||||
int v0[3], v1[3];
|
||||
};
|
||||
|
||||
static int findEdgeSegments(rcContourSet* cset, int x, int z, EdgeSegment* segs, const int maxSegs)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (int i = 0; i < cset->nconts; ++i)
|
||||
{
|
||||
const rcContour* c = &cset->conts[i];
|
||||
const int nc = n;
|
||||
for (int j = 0, k = c->nverts-1; j < c->nverts; k=j++)
|
||||
{
|
||||
const int* v0 = &c->verts[k*4];
|
||||
const int* v1 = &c->verts[j*4];
|
||||
if ((v0[0] == x && v1[0] == x) || (v0[2] == z && v1[2] == z))
|
||||
{
|
||||
if (n && segs[n-1].i1 == k)
|
||||
{
|
||||
// Merge with previous
|
||||
segs[n-1].i1 = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new
|
||||
if (n >= maxSegs)
|
||||
return n;
|
||||
segs[n].i0 = k;
|
||||
segs[n].i1 = j;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if first and last should be merged.
|
||||
if (n && n && segs[n-1].v1 == segs[nc].v0)
|
||||
{
|
||||
segs[nc].i0 = segs[n-1].i0;
|
||||
n--;
|
||||
}
|
||||
// Copy vertices
|
||||
for (int j = nc; j < n; ++j)
|
||||
{
|
||||
segs[j].v0[0] = c->verts[segs[j].i0*4+0];
|
||||
segs[j].v0[1] = c->verts[segs[j].i0*4+1];
|
||||
segs[j].v0[2] = c->verts[segs[j].i0*4+2];
|
||||
segs[j].v1[0] = c->verts[segs[j].i1*4+0];
|
||||
segs[j].v1[1] = c->verts[segs[j].i1*4+1];
|
||||
segs[j].v1[2] = c->verts[segs[j].i1*4+2];
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static bool pointOnEdgeSegment(const int* v0, const int* v1, int x, int z)
|
||||
{
|
||||
const int dx = v1[0] - v0[0];
|
||||
const int dz = v1[2] - v0[2];
|
||||
if (rcAbs(dx) > rcAbs(dz))
|
||||
{
|
||||
const int d = x - v0[0];
|
||||
if (dx < 0)
|
||||
return d < 0 && d > dx;
|
||||
else
|
||||
return d > 0 && d < dx;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int d = z - v0[2];
|
||||
if (dz < 0)
|
||||
return d < 0 && d > dz;
|
||||
else
|
||||
return d > 0 && d < dz;
|
||||
}
|
||||
}
|
||||
|
||||
static bool insertPoint(rcContour* c, int idx, const int* v)
|
||||
{
|
||||
int* newVerts = new int[(c->nverts+1)*4];
|
||||
if (!newVerts)
|
||||
{
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "insertPoint: Out of memory 'newVerts'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idx > 0)
|
||||
memcpy(newVerts, c->verts, sizeof(int)*4*idx);
|
||||
|
||||
newVerts[idx*4+0] = v[0];
|
||||
newVerts[idx*4+1] = v[1];
|
||||
newVerts[idx*4+2] = v[2];
|
||||
newVerts[idx*4+3] = 0;
|
||||
|
||||
if (c->nverts - idx > 0)
|
||||
memcpy(&newVerts[(idx+1)*4], &c->verts[idx*4], sizeof(int)*4*(c->nverts - idx));
|
||||
|
||||
delete [] c->verts;
|
||||
|
||||
c->verts = newVerts;
|
||||
c->nverts++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ptsEqual(const int* a, const int* b)
|
||||
{
|
||||
return a[0] == b[0] && a[1] == b[1] && a[2] == b[2];
|
||||
}
|
||||
|
||||
static bool conformEdge(rcContourSet* cset, int ex, int ez, const int* v0, const int* v1)
|
||||
{
|
||||
for (int i = 0; i < cset->nconts; ++i)
|
||||
{
|
||||
rcContour* c = &cset->conts[i];
|
||||
const int nv = c->nverts;
|
||||
for (int j = 0; j < nv; ++j)
|
||||
{
|
||||
const int* v = &c->verts[j*4];
|
||||
if (ptsEqual(v, v0))
|
||||
{
|
||||
const int jn = (j+1) % nv;
|
||||
const int* vn = &c->verts[jn*4];
|
||||
|
||||
// Check if the segment is edge segment.
|
||||
if ((v[0] == ex && vn[0] == ex) || (v[2] == ez && vn[2] == ez))
|
||||
{
|
||||
if (ptsEqual(vn, v1))
|
||||
{
|
||||
// Valid!
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new vertex
|
||||
if (pointOnEdgeSegment(v, vn, v1[0], v1[2]))
|
||||
{
|
||||
if (!insertPoint(c, jn, v1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ptsEqual(v, v1))
|
||||
{
|
||||
const int jp = (j+nv-1) % nv;
|
||||
const int* vp = &c->verts[jp*4];
|
||||
// Check if the segment is edge segment.
|
||||
if ((v[0] == ex && vp[0] == ex) || (v[2] == ez && vp[2] == ez))
|
||||
{
|
||||
if (ptsEqual(vp, v0))
|
||||
{
|
||||
// Valid!
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new vertex
|
||||
if (pointOnEdgeSegment(vp, v, v0[0], v0[2]))
|
||||
{
|
||||
if (!insertPoint(c, j, v0))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool rcFixupAdjacentContours(rcContourSet* cseta, rcContourSet* csetb,
|
||||
int edge, int edgePos)
|
||||
{
|
||||
if (!cseta || !csetb)
|
||||
return true;
|
||||
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
|
||||
if (edge == 1)
|
||||
{
|
||||
// x+1
|
||||
// Find edge segment
|
||||
static const int MAX_SEGS = 512; // TODO: Do not hardcode.
|
||||
EdgeSegment sa[MAX_SEGS], sb[MAX_SEGS];
|
||||
int nsa = findEdgeSegments(cseta, edgePos, -1, sa, MAX_SEGS);
|
||||
int nsb = findEdgeSegments(csetb, edgePos, -1, sb, MAX_SEGS);
|
||||
|
||||
// Conform set A to set B
|
||||
for (int i = 0; i < nsb; ++i)
|
||||
{
|
||||
const int* v0 = sb[i].v0;
|
||||
const int* v1 = sb[i].v1;
|
||||
if (!conformEdge(cseta, edgePos, -1, v1, v0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Conform set B to set A
|
||||
for (int i = 0; i < nsa; ++i)
|
||||
{
|
||||
const int* v0 = sa[i].v0;
|
||||
const int* v1 = sa[i].v1;
|
||||
if (!conformEdge(csetb, edgePos, -1, v1, v0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (edge == 2)
|
||||
{
|
||||
// y+1
|
||||
// Find edge segment
|
||||
static const int MAX_SEGS = 512; // TODO: Do not hardcode.
|
||||
EdgeSegment sa[MAX_SEGS], sb[MAX_SEGS];
|
||||
int nsa = findEdgeSegments(cseta, -1, edgePos, sa, MAX_SEGS);
|
||||
int nsb = findEdgeSegments(csetb, -1, edgePos, sb, MAX_SEGS);
|
||||
|
||||
// Conform set A to set B
|
||||
for (int i = 0; i < nsb; ++i)
|
||||
{
|
||||
const int* v0 = sb[i].v0;
|
||||
const int* v1 = sb[i].v1;
|
||||
if (!conformEdge(cseta, -1, edgePos, v1, v0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Conform set B to set A
|
||||
for (int i = 0; i < nsa; ++i)
|
||||
{
|
||||
const int* v0 = sa[i].v0;
|
||||
const int* v1 = sa[i].v1;
|
||||
if (!conformEdge(csetb, -1, edgePos, v1, v0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->fixupContours += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rcTranslateContours(rcContourSet* cset, int dx, int dy, int dz)
|
||||
{
|
||||
if (!cset) return;
|
||||
|
||||
for (int i = 0; i < cset->nconts; ++i)
|
||||
{
|
||||
rcContour& cont = cset->conts[i];
|
||||
for (int i = 0; i < cont.nverts; ++i)
|
||||
{
|
||||
int* v = &cont.verts[i*4];
|
||||
v[0] += dx;
|
||||
v[1] += dy;
|
||||
v[2] += dz;
|
||||
}
|
||||
for (int i = 0; i < cont.nrverts; ++i)
|
||||
{
|
||||
int* v = &cont.rverts[i*4];
|
||||
v[0] += dx;
|
||||
v[1] += dy;
|
||||
v[2] += dz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,14 +240,14 @@ void rcDebugDrawCompactHeightfieldSolid(const rcCompactHeightfield& chf)
|
||||
{
|
||||
for (int x = 0; x < chf.width; ++x)
|
||||
{
|
||||
const float fx = chf.minx + x*cs;
|
||||
const float fz = chf.minz + y*cs;
|
||||
const float fx = chf.bmin[0] + x*cs;
|
||||
const float fz = chf.bmin[2] + y*cs;
|
||||
const rcCompactCell& c = chf.cells[x+y*chf.width];
|
||||
|
||||
for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
const float fy = chf.miny + (s.y+1)*ch;
|
||||
const float fy = chf.bmin[1] + (s.y+1)*ch;
|
||||
glVertex3f(fx, fy, fz);
|
||||
glVertex3f(fx, fy, fz+cs);
|
||||
glVertex3f(fx+cs, fy, fz+cs);
|
||||
@ -270,8 +270,8 @@ void rcDebugDrawCompactHeightfieldRegions(const rcCompactHeightfield& chf)
|
||||
{
|
||||
for (int x = 0; x < chf.width; ++x)
|
||||
{
|
||||
const float fx = chf.minx + x*cs;
|
||||
const float fz = chf.minz + y*cs;
|
||||
const float fx = chf.bmin[0] + x*cs;
|
||||
const float fz = chf.bmin[2] + y*cs;
|
||||
const rcCompactCell& c = chf.cells[x+y*chf.width];
|
||||
|
||||
for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
|
||||
@ -284,7 +284,7 @@ void rcDebugDrawCompactHeightfieldRegions(const rcCompactHeightfield& chf)
|
||||
}
|
||||
else
|
||||
glColor4ub(0,0,0,128);
|
||||
const float fy = chf.miny + (s.y+1)*ch;
|
||||
const float fy = chf.bmin[1] + (s.y+1)*ch;
|
||||
glVertex3f(fx, fy, fz);
|
||||
glVertex3f(fx, fy, fz+cs);
|
||||
glVertex3f(fx+cs, fy, fz+cs);
|
||||
@ -310,14 +310,14 @@ void rcDebugDrawCompactHeightfieldDistance(const rcCompactHeightfield& chf)
|
||||
{
|
||||
for (int x = 0; x < chf.width; ++x)
|
||||
{
|
||||
const float fx = chf.minx + x*cs;
|
||||
const float fz = chf.minz + y*cs;
|
||||
const float fx = chf.bmin[0] + x*cs;
|
||||
const float fz = chf.bmin[2] + y*cs;
|
||||
const rcCompactCell& c = chf.cells[x+y*chf.width];
|
||||
|
||||
for (unsigned i = c.index, ni = c.index+c.count; i < ni; ++i)
|
||||
{
|
||||
const rcCompactSpan& s = chf.spans[i];
|
||||
const float fy = chf.miny + (s.y+1)*ch;
|
||||
const float fy = chf.bmin[1] + (s.y+1)*ch;
|
||||
float cd = (float)s.dist * dscale;
|
||||
glColor3f(cd, cd, cd);
|
||||
glVertex3f(fx, fy, fz);
|
||||
@ -363,6 +363,7 @@ void rcDebugDrawContours(const rcContourSet& cset, const float* orig, float cs,
|
||||
const rcContour& c = cset.conts[i];
|
||||
intToCol(c.reg, col);
|
||||
glColor4fv(col);
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (int j = 0; j < c.nverts; ++j)
|
||||
{
|
||||
@ -373,6 +374,7 @@ void rcDebugDrawContours(const rcContourSet& cset, const float* orig, float cs,
|
||||
glVertex3f(fx,fy,fz);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glColor4ub(0,0,0,128);
|
||||
glBegin(GL_POINTS);
|
||||
for (int j = 0; j < c.nverts; ++j)
|
||||
@ -389,9 +391,12 @@ void rcDebugDrawContours(const rcContourSet& cset, const float* orig, float cs,
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
|
||||
void rcDebugDrawPolyMesh(const struct rcPolyMesh& mesh, const float* orig, float cs, float ch)
|
||||
void rcDebugDrawPolyMesh(const struct rcPolyMesh& mesh)
|
||||
{
|
||||
const int nvp = mesh.nvp;
|
||||
const float cs = mesh.cs;
|
||||
const float ch = mesh.ch;
|
||||
const float* orig = mesh.bmin;
|
||||
glColor4ub(0,196,255,64);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int i = 0; i < mesh.npolys; ++i)
|
||||
|
@ -81,8 +81,10 @@ void rcFilterWalkableBorderSpans(const int walkableHeight,
|
||||
}
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Filter border: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Filter border: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->filterBorder += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
}
|
||||
|
||||
void rcFilterWalkableLowHeightSpans(int walkableHeight,
|
||||
@ -112,10 +114,13 @@ void rcFilterWalkableLowHeightSpans(int walkableHeight,
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Filter walkable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Filter walkable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->filterWalkable += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
}
|
||||
|
||||
|
||||
struct rcReachableSeed
|
||||
{
|
||||
inline void set(int ix, int iy, rcSpan* is)
|
||||
@ -225,8 +230,10 @@ bool rcMarkReachableSpans(const int walkableHeight,
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Mark reachable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Mark reachable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->filterMarkReachable += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
static rcLog* g_log = 0;
|
||||
static rcBuildTimes* g_btimes = 0;
|
||||
|
||||
rcLog::rcLog() :
|
||||
m_messageCount(0),
|
||||
@ -64,3 +65,13 @@ rcLog* rcGetLog()
|
||||
{
|
||||
return g_log;
|
||||
}
|
||||
|
||||
void rcSetBuildTimes(rcBuildTimes* btimes)
|
||||
{
|
||||
g_btimes = btimes;
|
||||
}
|
||||
|
||||
rcBuildTimes* rcGetBuildTimes()
|
||||
{
|
||||
return g_btimes;
|
||||
}
|
||||
|
@ -474,9 +474,17 @@ static void mergePolys(unsigned short* pa, unsigned short* pb,
|
||||
memcpy(pa, tmp, sizeof(unsigned short)*nvp);
|
||||
}
|
||||
|
||||
bool rcBuildPolyMesh(rcContourSet& cset, rcPolyMesh& mesh, const int nvp)
|
||||
bool rcBuildPolyMesh(rcContourSet& cset,
|
||||
const float* bmin, const float* bmax,
|
||||
const float cs, const float ch, int nvp,
|
||||
rcPolyMesh& mesh)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
|
||||
vcopy(mesh.bmin, bmin);
|
||||
vcopy(mesh.bmax, bmax);
|
||||
mesh.cs = cs;
|
||||
mesh.ch = ch;
|
||||
|
||||
int maxVertices = 0;
|
||||
int maxTris = 0;
|
||||
@ -692,8 +700,10 @@ bool rcBuildPolyMesh(rcContourSet& cset, rcPolyMesh& mesh, const int nvp)
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_ERROR, "Build polymesh: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Build polymesh: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->buildPolymesh += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -43,13 +43,12 @@ inline bool overlapInterval(unsigned short amin, unsigned short amax,
|
||||
|
||||
static rcSpan* allocSpan(rcHeightfield& hf)
|
||||
{
|
||||
static const int SPANS_PER_POOL = 2048;
|
||||
// If running out of memory, allocate new page and update the freelist.
|
||||
if (!hf.freelist || !hf.freelist->next)
|
||||
{
|
||||
// Create new page.
|
||||
// Allocate memory for the new pool.
|
||||
const int size = (sizeof(rcSpanPool)-sizeof(rcSpan)) + sizeof(rcSpan)*SPANS_PER_POOL;
|
||||
const int size = (sizeof(rcSpanPool)-sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL;
|
||||
rcSpanPool* pool = reinterpret_cast<rcSpanPool*>(new unsigned char[size]);
|
||||
if (!pool) return 0;
|
||||
pool->next = 0;
|
||||
@ -59,7 +58,7 @@ static rcSpan* allocSpan(rcHeightfield& hf)
|
||||
// Add new items to the free list.
|
||||
rcSpan* freelist = hf.freelist;
|
||||
rcSpan* head = &pool->items[0];
|
||||
rcSpan* it = &pool->items[SPANS_PER_POOL];
|
||||
rcSpan* it = &pool->items[RC_SPANS_PER_POOL];
|
||||
do
|
||||
{
|
||||
--it;
|
||||
@ -290,6 +289,9 @@ void rcRasterizeTriangles(const float* bmin, const float* bmax, const float cs,
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Rasterize: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
// if (rcGetLog())
|
||||
// rcGetLog()->log(RC_LOG_PROGRESS, "Rasterize: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
|
||||
if (rcGetBuildTimes())
|
||||
rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
|
||||
const int ax = x + rcGetDirOffsetX(dir);
|
||||
const int ay = y + rcGetDirOffsetY(dir);
|
||||
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||||
if (src[ai*2])
|
||||
if (src[ai*2] > 0 && (src[ai*2] & 0x8000) == 0)
|
||||
{
|
||||
if ((int)src[ai*2+1]+2 < (int)d2)
|
||||
{
|
||||
@ -420,10 +420,11 @@ static unsigned short* expandRegions(int maxIter, unsigned short level,
|
||||
|
||||
struct rcRegion
|
||||
{
|
||||
inline rcRegion() : count(0), id(0) {}
|
||||
inline rcRegion() : count(0), id(0), remap(false) {}
|
||||
|
||||
int count;
|
||||
unsigned short id;
|
||||
bool remap;
|
||||
rcIntArray connections;
|
||||
rcIntArray floors;
|
||||
};
|
||||
@ -741,7 +742,7 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize,
|
||||
for (int i = 0; i < nreg; ++i)
|
||||
{
|
||||
rcRegion& reg = regions[i];
|
||||
if (reg.id == 0)
|
||||
if (reg.id == 0 || (reg.id & 0x8000))
|
||||
continue;
|
||||
if (reg.count == 0)
|
||||
continue;
|
||||
@ -766,7 +767,7 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize,
|
||||
for (int i = 0; i < nreg; ++i)
|
||||
{
|
||||
rcRegion& reg = regions[i];
|
||||
if (reg.id == 0)
|
||||
if (reg.id == 0 || (reg.id & 0x8000))
|
||||
continue;
|
||||
if (reg.count == 0)
|
||||
continue;
|
||||
@ -782,8 +783,9 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize,
|
||||
unsigned short mergeId = reg.id;
|
||||
for (int j = 0; j < reg.connections.size(); ++j)
|
||||
{
|
||||
if (reg.connections[j] & 0x8000) continue;
|
||||
rcRegion& mreg = regions[reg.connections[j]];
|
||||
if (mreg.id == 0) continue;
|
||||
if (mreg.id == 0 || (mreg.id & 0x8000)) continue;
|
||||
if (mreg.count < smallest &&
|
||||
canMergeWithRegion(reg, mreg.id) &&
|
||||
canMergeWithRegion(mreg, reg.id))
|
||||
@ -804,7 +806,7 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize,
|
||||
// Fixup regions pointing to current region.
|
||||
for (int j = 0; j < nreg; ++j)
|
||||
{
|
||||
if (regions[j].id == 0) continue;
|
||||
if (regions[j].id == 0 || (regions[j].id & 0x8000)) continue;
|
||||
// If another region was already merged into current region
|
||||
// change the nid of the previous region too.
|
||||
if (regions[j].id == oldId)
|
||||
@ -823,28 +825,36 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize,
|
||||
// Compress region Ids.
|
||||
for (int i = 0; i < nreg; ++i)
|
||||
{
|
||||
if (regions[i].id == 0) continue;
|
||||
regions[i].id |= 0x8000;
|
||||
regions[i].remap = false;
|
||||
if (regions[i].id == 0) continue; // Skip nil regions.
|
||||
if (regions[i].id & 0x8000) continue; // Skip external regions.
|
||||
regions[i].remap = true;
|
||||
}
|
||||
|
||||
unsigned short regIdGen = 0;
|
||||
for (int i = 0; i < nreg; ++i)
|
||||
{
|
||||
if ((regions[i].id & 0x8000) == 0)
|
||||
if (!regions[i].remap)
|
||||
continue;
|
||||
unsigned short oldId = regions[i].id;
|
||||
unsigned short newId = ++regIdGen;
|
||||
for (int j = i; j < nreg; ++j)
|
||||
{
|
||||
if (regions[j].id == oldId)
|
||||
{
|
||||
regions[j].id = newId;
|
||||
regions[j].remap = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
maxRegionId = regIdGen;
|
||||
|
||||
// Remap regions.
|
||||
for (int i = 0; i < chf.spanCount; ++i)
|
||||
src[i*2] = regions[src[i*2]].id;
|
||||
{
|
||||
if ((src[i*2] & 0x8000) == 0)
|
||||
src[i*2] = regions[src[i*2]].id;
|
||||
}
|
||||
|
||||
delete [] regions;
|
||||
|
||||
@ -902,18 +912,44 @@ bool rcBuildDistanceField(rcCompactHeightfield& chf)
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
/* if (rcGetLog())
|
||||
{
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Build distance field: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - dist: %.3f ms", rcGetDeltaTimeUsec(distStartTime, distEndTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - blur: %.3f ms", rcGetDeltaTimeUsec(blurStartTime, blurEndTime)/1000.0f);
|
||||
}*/
|
||||
if (rcGetBuildTimes())
|
||||
{
|
||||
rcGetBuildTimes()->buildDistanceField += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
rcGetBuildTimes()->buildDistanceFieldDist += rcGetDeltaTimeUsec(distStartTime, distEndTime);
|
||||
rcGetBuildTimes()->buildDistanceFieldBlur += rcGetDeltaTimeUsec(blurStartTime, blurEndTime);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void paintRectRegion(int minx, int maxx, int miny, int maxy,
|
||||
unsigned short regId, unsigned short minLevel,
|
||||
rcCompactHeightfield& chf, unsigned short* src)
|
||||
{
|
||||
const int w = chf.width;
|
||||
for (int y = miny; y < maxy; ++y)
|
||||
{
|
||||
for (int x = minx; x < maxx; ++x)
|
||||
{
|
||||
const rcCompactCell& c = chf.cells[x+y*w];
|
||||
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||||
{
|
||||
if (chf.spans[i].dist >= minLevel)
|
||||
src[i*2] = regId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rcBuildRegions(rcCompactHeightfield& chf,
|
||||
int walkableRadius, int minRegionSize, int mergeRegionSize)
|
||||
int walkableRadius, int borderSize,
|
||||
int minRegionSize, int mergeRegionSize)
|
||||
{
|
||||
rcTimeVal startTime = rcGetPerformanceTimer();
|
||||
|
||||
@ -952,9 +988,13 @@ bool rcBuildRegions(rcCompactHeightfield& chf,
|
||||
unsigned short minLevel = (unsigned short)walkableRadius * 2;
|
||||
|
||||
const int expandIters = 4 + walkableRadius * 2;
|
||||
|
||||
|
||||
paintRectRegion(0, borderSize, 0, h, regionId|0x8000, minLevel, chf, src); regionId++;
|
||||
paintRectRegion(w-borderSize, w, 0, h, regionId|0x8000, minLevel, chf, src); regionId++;
|
||||
paintRectRegion(0, w, 0, borderSize, regionId|0x8000, minLevel, chf, src); regionId++;
|
||||
paintRectRegion(0, w, h-borderSize, h, regionId|0x8000, minLevel, chf, src); regionId++;
|
||||
|
||||
rcTimeVal expTime = 0;
|
||||
rcTimeVal marknewTime = 0;
|
||||
rcTimeVal floodTime = 0;
|
||||
|
||||
while (level > minLevel)
|
||||
@ -1017,16 +1057,24 @@ bool rcBuildRegions(rcCompactHeightfield& chf,
|
||||
|
||||
rcTimeVal endTime = rcGetPerformanceTimer();
|
||||
|
||||
if (rcGetLog())
|
||||
/* if (rcGetLog())
|
||||
{
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, "Build regions: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - reg: %.3f ms", rcGetDeltaTimeUsec(regStartTime, regEndTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - exp: %.3f ms", rcGetDeltaTimeUsec(0, expTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - new: %.3f ms", rcGetDeltaTimeUsec(0, marknewTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - flood: %.3f ms", rcGetDeltaTimeUsec(0, floodTime)/1000.0f);
|
||||
rcGetLog()->log(RC_LOG_PROGRESS, " - filter: %.3f ms", rcGetDeltaTimeUsec(filterStartTime, filterEndTime)/1000.0f);
|
||||
}
|
||||
|
||||
*/
|
||||
if (rcGetBuildTimes())
|
||||
{
|
||||
rcGetBuildTimes()->buildRegions += rcGetDeltaTimeUsec(startTime, endTime);
|
||||
rcGetBuildTimes()->buildRegionsReg += rcGetDeltaTimeUsec(regStartTime, regEndTime);
|
||||
rcGetBuildTimes()->buildRegionsExp += rcGetDeltaTimeUsec(0, expTime);
|
||||
rcGetBuildTimes()->buildRegionsFlood += rcGetDeltaTimeUsec(0, floodTime);
|
||||
rcGetBuildTimes()->buildRegionsFilter += rcGetDeltaTimeUsec(filterStartTime, filterEndTime);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -200,8 +200,8 @@
|
||||
<array/>
|
||||
<key>PerspectiveWidths</key>
|
||||
<array>
|
||||
<integer>810</integer>
|
||||
<integer>810</integer>
|
||||
<integer>1280</integer>
|
||||
<integer>1280</integer>
|
||||
</array>
|
||||
<key>Perspectives</key>
|
||||
<array>
|
||||
@ -230,8 +230,6 @@
|
||||
<key>Layout</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BecomeActive</key>
|
||||
<true/>
|
||||
<key>ContentConfiguration</key>
|
||||
<dict>
|
||||
<key>PBXBottomSmartGroupGIDs</key>
|
||||
@ -257,7 +255,7 @@
|
||||
<dict>
|
||||
<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
|
||||
<array>
|
||||
<real>185</real>
|
||||
<real>228</real>
|
||||
</array>
|
||||
<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
|
||||
<array>
|
||||
@ -270,23 +268,23 @@
|
||||
<array>
|
||||
<string>29B97314FDCFA39411CA2CEA</string>
|
||||
<string>080E96DDFE201D6D7F000001</string>
|
||||
<string>6BDD9E030F91110C00904EEF</string>
|
||||
<string>6B137C7D0F7FCBE800459200</string>
|
||||
<string>29B97315FDCFA39411CA2CEA</string>
|
||||
<string>29B97317FDCFA39411CA2CEA</string>
|
||||
<string>29B97323FDCFA39411CA2CEA</string>
|
||||
<string>1058C7A0FEA54F0111CA2CBB</string>
|
||||
<string>1058C7A2FEA54F0111CA2CBB</string>
|
||||
<string>1C37FBAC04509CD000000102</string>
|
||||
<string>1C77FABC04509CD000000102</string>
|
||||
</array>
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
|
||||
<array>
|
||||
<array>
|
||||
<integer>2</integer>
|
||||
<integer>27</integer>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</array>
|
||||
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
|
||||
<string>{{0, 0}, {185, 595}}</string>
|
||||
<string>{{0, 17}, {228, 660}}</string>
|
||||
</dict>
|
||||
<key>PBXTopSmartGroupGIDs</key>
|
||||
<array/>
|
||||
@ -296,30 +294,32 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {202, 613}}</string>
|
||||
<string>{{0, 0}, {245, 678}}</string>
|
||||
<key>GroupTreeTableConfiguration</key>
|
||||
<array>
|
||||
<string>MainColumn</string>
|
||||
<real>185</real>
|
||||
<real>228</real>
|
||||
</array>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>55 112 1071 654 0 0 1280 778 </string>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXSmartGroupTreeModule</string>
|
||||
<key>Proportion</key>
|
||||
<string>202pt</string>
|
||||
<string>245pt</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Dock</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BecomeActive</key>
|
||||
<true/>
|
||||
<key>ContentConfiguration</key>
|
||||
<dict>
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>6B8632A30F78115100E2684A</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>imgui.h</string>
|
||||
<string>demo.cpp</string>
|
||||
<key>PBXSplitModuleInNavigatorKey</key>
|
||||
<dict>
|
||||
<key>Split0</key>
|
||||
@ -327,14 +327,173 @@
|
||||
<key>PBXProjectModuleGUID</key>
|
||||
<string>6B8632A40F78115100E2684A</string>
|
||||
<key>PBXProjectModuleLabel</key>
|
||||
<string>imgui.h</string>
|
||||
<string>demo.cpp</string>
|
||||
<key>_historyCapacity</key>
|
||||
<integer>0</integer>
|
||||
<key>bookmark</key>
|
||||
<string>6BB788140FC045A2003C24DB</string>
|
||||
<key>history</key>
|
||||
<array>
|
||||
<string>6B8633370F7813A600E2684A</string>
|
||||
<string>6B8DB3890F9798DE007FA9E1</string>
|
||||
<string>6B8DB38A0F9798DE007FA9E1</string>
|
||||
<string>6BB87E0B0F9DE8A300E33F12</string>
|
||||
<string>6B77074C0FBD597500D21BAE</string>
|
||||
<string>6B77074D0FBD597500D21BAE</string>
|
||||
<string>6B7707710FBD5DB300D21BAE</string>
|
||||
<string>6B7707AF0FBD66CF00D21BAE</string>
|
||||
<string>6B7707EF0FBD90F100D21BAE</string>
|
||||
<string>6B7707F00FBD90F100D21BAE</string>
|
||||
<string>6B7707F30FBD90F100D21BAE</string>
|
||||
<string>6B7708F20FBDA96300D21BAE</string>
|
||||
<string>6BB787660FC03EAD003C24DB</string>
|
||||
<string>6BB787670FC03EAD003C24DB</string>
|
||||
<string>6BB787680FC03EAD003C24DB</string>
|
||||
<string>6BB787690FC03EAD003C24DB</string>
|
||||
<string>6BB7876A0FC03EAD003C24DB</string>
|
||||
<string>6BB7876B0FC03EAD003C24DB</string>
|
||||
<string>6BB7876C0FC03EAD003C24DB</string>
|
||||
<string>6BB7876D0FC03EAD003C24DB</string>
|
||||
<string>6BB7876E0FC03EAD003C24DB</string>
|
||||
<string>6BB7876F0FC03EAD003C24DB</string>
|
||||
<string>6BB787700FC03EAD003C24DB</string>
|
||||
<string>6BB787710FC03EAD003C24DB</string>
|
||||
<string>6BB787720FC03EAD003C24DB</string>
|
||||
<string>6BB787730FC03EAD003C24DB</string>
|
||||
<string>6BB788130FC045A2003C24DB</string>
|
||||
</array>
|
||||
<key>prevStack</key>
|
||||
<array>
|
||||
<string>6B86333B0F7813A600E2684A</string>
|
||||
<string>6B1E02680F924A8500CC0038</string>
|
||||
<string>6B1E02750F924A8500CC0038</string>
|
||||
<string>6B1E028F0F924D5A00CC0038</string>
|
||||
<string>6B1E029B0F924D8B00CC0038</string>
|
||||
<string>6B1E02AE0F92530C00CC0038</string>
|
||||
<string>6B1E02BB0F92547D00CC0038</string>
|
||||
<string>6B1E02FC0F92563500CC0038</string>
|
||||
<string>6B1E032E0F925D9100CC0038</string>
|
||||
<string>6B8DB2D70F93A7A5007FA9E1</string>
|
||||
<string>6B8DB38F0F9798DE007FA9E1</string>
|
||||
<string>6B8DB3900F9798DE007FA9E1</string>
|
||||
<string>6BB87E0E0F9DE8A300E33F12</string>
|
||||
<string>6B458EA80FB4540500044EA9</string>
|
||||
<string>6B77072C0FBD540400D21BAE</string>
|
||||
<string>6B7707B90FBD66CF00D21BAE</string>
|
||||
<string>6B7707F70FBD90F100D21BAE</string>
|
||||
<string>6B7707F90FBD90F100D21BAE</string>
|
||||
<string>6B7707FC0FBD90F100D21BAE</string>
|
||||
<string>6B7708010FBD90F100D21BAE</string>
|
||||
<string>6B7708F70FBDA96300D21BAE</string>
|
||||
<string>6BB787750FC03EAD003C24DB</string>
|
||||
<string>6BB787760FC03EAD003C24DB</string>
|
||||
<string>6BB787770FC03EAD003C24DB</string>
|
||||
<string>6BB787780FC03EAD003C24DB</string>
|
||||
<string>6BB787790FC03EAD003C24DB</string>
|
||||
<string>6BB7877A0FC03EAD003C24DB</string>
|
||||
<string>6BB7877B0FC03EAD003C24DB</string>
|
||||
<string>6BB7877C0FC03EAD003C24DB</string>
|
||||
<string>6BB7877D0FC03EAD003C24DB</string>
|
||||
<string>6BB7877E0FC03EAD003C24DB</string>
|
||||
<string>6BB7877F0FC03EAD003C24DB</string>
|
||||
<string>6BB787800FC03EAD003C24DB</string>
|
||||
<string>6BB787810FC03EAD003C24DB</string>
|
||||
<string>6BB787820FC03EAD003C24DB</string>
|
||||
<string>6BB787830FC03EAD003C24DB</string>
|
||||
<string>6BB787840FC03EAD003C24DB</string>
|
||||
<string>6BB787850FC03EAD003C24DB</string>
|
||||
<string>6BB787860FC03EAD003C24DB</string>
|
||||
<string>6BB787870FC03EAD003C24DB</string>
|
||||
<string>6BB787880FC03EAD003C24DB</string>
|
||||
<string>6BB787890FC03EAD003C24DB</string>
|
||||
<string>6BB7878A0FC03EAD003C24DB</string>
|
||||
<string>6BB7878B0FC03EAD003C24DB</string>
|
||||
<string>6BB7878C0FC03EAD003C24DB</string>
|
||||
<string>6BB7878D0FC03EAD003C24DB</string>
|
||||
<string>6BB7878E0FC03EAD003C24DB</string>
|
||||
<string>6BB7878F0FC03EAD003C24DB</string>
|
||||
<string>6BB787900FC03EAD003C24DB</string>
|
||||
<string>6BB787910FC03EAD003C24DB</string>
|
||||
<string>6BB787920FC03EAD003C24DB</string>
|
||||
<string>6BB787930FC03EAD003C24DB</string>
|
||||
<string>6BB787940FC03EAD003C24DB</string>
|
||||
<string>6BB787950FC03EAD003C24DB</string>
|
||||
<string>6BB787960FC03EAD003C24DB</string>
|
||||
<string>6BB787970FC03EAD003C24DB</string>
|
||||
<string>6BB787980FC03EAD003C24DB</string>
|
||||
<string>6BB787990FC03EAD003C24DB</string>
|
||||
<string>6BB7879A0FC03EAD003C24DB</string>
|
||||
<string>6BB7879B0FC03EAD003C24DB</string>
|
||||
<string>6BB7879C0FC03EAD003C24DB</string>
|
||||
<string>6BB7879D0FC03EAD003C24DB</string>
|
||||
<string>6BB7879E0FC03EAD003C24DB</string>
|
||||
<string>6BB7879F0FC03EAD003C24DB</string>
|
||||
<string>6BB787A00FC03EAD003C24DB</string>
|
||||
<string>6BB787A10FC03EAD003C24DB</string>
|
||||
<string>6BB787A20FC03EAD003C24DB</string>
|
||||
<string>6BB787A30FC03EAD003C24DB</string>
|
||||
<string>6BB787A40FC03EAD003C24DB</string>
|
||||
<string>6BB787A50FC03EAD003C24DB</string>
|
||||
<string>6BB787A60FC03EAD003C24DB</string>
|
||||
<string>6BB787A70FC03EAD003C24DB</string>
|
||||
<string>6BB787A80FC03EAD003C24DB</string>
|
||||
<string>6BB787A90FC03EAD003C24DB</string>
|
||||
<string>6BB787AA0FC03EAD003C24DB</string>
|
||||
<string>6BB787AB0FC03EAD003C24DB</string>
|
||||
<string>6BB787AC0FC03EAD003C24DB</string>
|
||||
<string>6BB787AD0FC03EAD003C24DB</string>
|
||||
<string>6BB787AE0FC03EAD003C24DB</string>
|
||||
<string>6BB787AF0FC03EAD003C24DB</string>
|
||||
<string>6BB787B00FC03EAD003C24DB</string>
|
||||
<string>6BB787B10FC03EAD003C24DB</string>
|
||||
<string>6BB787B20FC03EAD003C24DB</string>
|
||||
<string>6BB787B30FC03EAD003C24DB</string>
|
||||
<string>6BB787B40FC03EAD003C24DB</string>
|
||||
<string>6BB787B50FC03EAD003C24DB</string>
|
||||
<string>6BB787B60FC03EAD003C24DB</string>
|
||||
<string>6BB787B70FC03EAD003C24DB</string>
|
||||
<string>6BB787B80FC03EAD003C24DB</string>
|
||||
<string>6BB787B90FC03EAD003C24DB</string>
|
||||
<string>6BB787BA0FC03EAD003C24DB</string>
|
||||
<string>6BB787BB0FC03EAD003C24DB</string>
|
||||
<string>6BB787BC0FC03EAD003C24DB</string>
|
||||
<string>6BB787BD0FC03EAD003C24DB</string>
|
||||
<string>6BB787BE0FC03EAD003C24DB</string>
|
||||
<string>6BB787BF0FC03EAD003C24DB</string>
|
||||
<string>6BB787C00FC03EAD003C24DB</string>
|
||||
<string>6BB787C10FC03EAD003C24DB</string>
|
||||
<string>6BB787C20FC03EAD003C24DB</string>
|
||||
<string>6BB787C30FC03EAD003C24DB</string>
|
||||
<string>6BB787C40FC03EAD003C24DB</string>
|
||||
<string>6BB787C50FC03EAD003C24DB</string>
|
||||
<string>6BB787C60FC03EAD003C24DB</string>
|
||||
<string>6BB787C70FC03EAD003C24DB</string>
|
||||
<string>6BB787C80FC03EAD003C24DB</string>
|
||||
<string>6BB787C90FC03EAD003C24DB</string>
|
||||
<string>6BB787CA0FC03EAD003C24DB</string>
|
||||
<string>6BB787CB0FC03EAD003C24DB</string>
|
||||
<string>6BB787CC0FC03EAD003C24DB</string>
|
||||
<string>6BB787CD0FC03EAD003C24DB</string>
|
||||
<string>6BB787CE0FC03EAD003C24DB</string>
|
||||
<string>6BB787CF0FC03EAD003C24DB</string>
|
||||
<string>6BB787D00FC03EAD003C24DB</string>
|
||||
<string>6BB787D10FC03EAD003C24DB</string>
|
||||
<string>6BB787D20FC03EAD003C24DB</string>
|
||||
<string>6BB787D30FC03EAD003C24DB</string>
|
||||
<string>6BB787D40FC03EAD003C24DB</string>
|
||||
<string>6BB787D50FC03EAD003C24DB</string>
|
||||
<string>6BB787D60FC03EAD003C24DB</string>
|
||||
<string>6BB787D70FC03EAD003C24DB</string>
|
||||
<string>6BB787D80FC03EAD003C24DB</string>
|
||||
<string>6BB787D90FC03EAD003C24DB</string>
|
||||
<string>6BB787DA0FC03EAD003C24DB</string>
|
||||
<string>6BB787DB0FC03EAD003C24DB</string>
|
||||
<string>6BB787DC0FC03EAD003C24DB</string>
|
||||
<string>6BB787DD0FC03EAD003C24DB</string>
|
||||
<string>6BB787DE0FC03EAD003C24DB</string>
|
||||
<string>6BB787DF0FC03EAD003C24DB</string>
|
||||
<string>6BB787E00FC03EAD003C24DB</string>
|
||||
<string>6BB787E10FC03EAD003C24DB</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>SplitCount</key>
|
||||
@ -348,18 +507,18 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {864, 405}}</string>
|
||||
<string>{{0, 0}, {1030, 585}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>55 112 1071 654 0 0 1280 778 </string>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXNavigatorGroup</string>
|
||||
<key>Proportion</key>
|
||||
<string>405pt</string>
|
||||
<string>585pt</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Proportion</key>
|
||||
<string>203pt</string>
|
||||
<string>88pt</string>
|
||||
<key>Tabs</key>
|
||||
<array>
|
||||
<dict>
|
||||
@ -373,9 +532,7 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {864, 176}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>55 112 1071 654 0 0 1280 778 </string>
|
||||
<string>{{10, 27}, {1030, 100}}</string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>XCDetailModule</string>
|
||||
@ -391,7 +548,7 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 31}, {603, 297}}</string>
|
||||
<string>{{10, 27}, {1030, 225}}</string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXProjectFindModule</string>
|
||||
@ -429,7 +586,9 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{10, 27}, {864, 176}}</string>
|
||||
<string>{{10, 27}, {1030, 61}}</string>
|
||||
<key>RubberWindowFrame</key>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXBuildResultsModule</string>
|
||||
@ -438,7 +597,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>Proportion</key>
|
||||
<string>864pt</string>
|
||||
<string>1030pt</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>Name</key>
|
||||
@ -457,11 +616,11 @@
|
||||
</array>
|
||||
<key>TableOfContents</key>
|
||||
<array>
|
||||
<string>6BDD9E120F91114E00904EEF</string>
|
||||
<string>6BB787E50FC03EB7003C24DB</string>
|
||||
<string>1CA23ED40692098700951B8B</string>
|
||||
<string>6BDD9E130F91114E00904EEF</string>
|
||||
<string>6BB787E60FC03EB7003C24DB</string>
|
||||
<string>6B8632A30F78115100E2684A</string>
|
||||
<string>6BDD9E140F91114E00904EEF</string>
|
||||
<string>6BB787E70FC03EB7003C24DB</string>
|
||||
<string>1CA23EDF0692099D00951B8B</string>
|
||||
<string>1CA23EE00692099D00951B8B</string>
|
||||
<string>1CA23EE10692099D00951B8B</string>
|
||||
@ -510,12 +669,12 @@
|
||||
<key>GeometryConfiguration</key>
|
||||
<dict>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 0}, {810, 132}}</string>
|
||||
<string>{{0, 0}, {1280, 199}}</string>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXDebugCLIModule</string>
|
||||
<key>Proportion</key>
|
||||
<string>132pt</string>
|
||||
<string>199pt</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>ContentConfiguration</key>
|
||||
@ -534,8 +693,8 @@
|
||||
<string>yes</string>
|
||||
<key>sizes</key>
|
||||
<array>
|
||||
<string>{{0, 0}, {395, 150}}</string>
|
||||
<string>{{395, 0}, {415, 150}}</string>
|
||||
<string>{{0, 0}, {637, 130}}</string>
|
||||
<string>{{637, 0}, {643, 130}}</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>VerticalSplitView</key>
|
||||
@ -550,8 +709,8 @@
|
||||
<string>yes</string>
|
||||
<key>sizes</key>
|
||||
<array>
|
||||
<string>{{0, 0}, {810, 150}}</string>
|
||||
<string>{{0, 150}, {810, 159}}</string>
|
||||
<string>{{0, 0}, {1280, 130}}</string>
|
||||
<string>{{0, 130}, {1280, 344}}</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
@ -571,7 +730,7 @@
|
||||
<key>DebugSTDIOWindowFrame</key>
|
||||
<string>{{200, 200}, {500, 300}}</string>
|
||||
<key>Frame</key>
|
||||
<string>{{0, 137}, {810, 309}}</string>
|
||||
<string>{{0, 204}, {1280, 474}}</string>
|
||||
<key>PBXDebugSessionStackFrameViewKey</key>
|
||||
<dict>
|
||||
<key>DebugVariablesTableConfiguration</key>
|
||||
@ -581,16 +740,16 @@
|
||||
<string>Value</string>
|
||||
<real>85</real>
|
||||
<string>Summary</string>
|
||||
<real>185</real>
|
||||
<real>413</real>
|
||||
</array>
|
||||
<key>Frame</key>
|
||||
<string>{{395, 0}, {415, 150}}</string>
|
||||
<string>{{637, 0}, {643, 130}}</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>Module</key>
|
||||
<string>PBXDebugSessionModule</string>
|
||||
<key>Proportion</key>
|
||||
<string>309pt</string>
|
||||
<string>474pt</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>Name</key>
|
||||
@ -608,14 +767,14 @@
|
||||
</array>
|
||||
<key>TableOfContents</key>
|
||||
<array>
|
||||
<string>6BDD9E150F91114E00904EEF</string>
|
||||
<string>6BB787E80FC03EB7003C24DB</string>
|
||||
<string>1CCC7628064C1048000F2A68</string>
|
||||
<string>1CCC7629064C1048000F2A68</string>
|
||||
<string>6BDD9E160F91114E00904EEF</string>
|
||||
<string>6BDD9E170F91114E00904EEF</string>
|
||||
<string>6BDD9E180F91114E00904EEF</string>
|
||||
<string>6BDD9E190F91114E00904EEF</string>
|
||||
<string>6BDD9E1A0F91114E00904EEF</string>
|
||||
<string>6BB787E90FC03EB7003C24DB</string>
|
||||
<string>6BB787EA0FC03EB7003C24DB</string>
|
||||
<string>6BB787EB0FC03EB7003C24DB</string>
|
||||
<string>6BB787EC0FC03EB7003C24DB</string>
|
||||
<string>6BB786F40FC0091C003C24DB</string>
|
||||
</array>
|
||||
<key>ToolbarConfiguration</key>
|
||||
<string>xcode.toolbar.config.debugV3</string>
|
||||
@ -648,7 +807,7 @@
|
||||
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
|
||||
</array>
|
||||
<key>WindowString</key>
|
||||
<string>55 112 1071 654 0 0 1280 778 </string>
|
||||
<string>0 59 1280 719 0 0 1280 778 </string>
|
||||
<key>WindowToolsV3</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
@ -24,6 +24,7 @@
|
||||
6B137C930F7FCC1100459200 /* RecastTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B137C8A0F7FCC1100459200 /* RecastTimer.cpp */; };
|
||||
6B8632DA0F78122C00E2684A /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B8632D90F78122C00E2684A /* SDL.framework */; };
|
||||
6B8632DC0F78123E00E2684A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B8632DB0F78123E00E2684A /* OpenGL.framework */; };
|
||||
6BB788170FC0472B003C24DB /* ChunkyTriMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB788160FC0472B003C24DB /* ChunkyTriMesh.cpp */; };
|
||||
6BDD9E0A0F91113800904EEF /* DetourDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BDD9E070F91113800904EEF /* DetourDebugDraw.cpp */; };
|
||||
6BDD9E0B0F91113800904EEF /* DetourStatNavMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BDD9E080F91113800904EEF /* DetourStatNavMesh.cpp */; };
|
||||
6BDD9E0C0F91113800904EEF /* DetourStatNavMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BDD9E090F91113800904EEF /* DetourStatNavMeshBuilder.cpp */; };
|
||||
@ -63,6 +64,8 @@
|
||||
6B137C8A0F7FCC1100459200 /* RecastTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastTimer.cpp; path = ../../../Recast/Source/RecastTimer.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6B8632D90F78122C00E2684A /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = Library/Frameworks/SDL.framework; sourceTree = SDKROOT; };
|
||||
6B8632DB0F78123E00E2684A /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
|
||||
6BB788160FC0472B003C24DB /* ChunkyTriMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ChunkyTriMesh.cpp; path = ../../Source/ChunkyTriMesh.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6BB788180FC04753003C24DB /* ChunkyTriMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChunkyTriMesh.h; path = ../../Include/ChunkyTriMesh.h; sourceTree = SOURCE_ROOT; };
|
||||
6BDD9E040F91112200904EEF /* DetourDebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetourDebugDraw.h; path = ../../../Detour/Include/DetourDebugDraw.h; sourceTree = SOURCE_ROOT; };
|
||||
6BDD9E050F91112200904EEF /* DetourStatNavMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetourStatNavMesh.h; path = ../../../Detour/Include/DetourStatNavMesh.h; sourceTree = SOURCE_ROOT; };
|
||||
6BDD9E060F91112200904EEF /* DetourStatNavMeshBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetourStatNavMeshBuilder.h; path = ../../../Detour/Include/DetourStatNavMeshBuilder.h; sourceTree = SOURCE_ROOT; };
|
||||
@ -93,13 +96,15 @@
|
||||
6BDD9E030F91110C00904EEF /* Detour */,
|
||||
6B137C7D0F7FCBE800459200 /* Recast */,
|
||||
6B137C790F7FCBE400459200 /* glfont.h */,
|
||||
6B137C7A0F7FCBE400459200 /* imgui.h */,
|
||||
6B137C7B0F7FCBE400459200 /* MeshLoaderObj.h */,
|
||||
6B137C7C0F7FCBE400459200 /* SDLMain.h */,
|
||||
6B137C6A0F7FCBBB00459200 /* demo.cpp */,
|
||||
6B137C6B0F7FCBBB00459200 /* glfont.cpp */,
|
||||
6B137C7A0F7FCBE400459200 /* imgui.h */,
|
||||
6B137C6C0F7FCBBB00459200 /* imgui.cpp */,
|
||||
6B137C7B0F7FCBE400459200 /* MeshLoaderObj.h */,
|
||||
6B137C6D0F7FCBBB00459200 /* MeshLoaderObj.cpp */,
|
||||
6BB788160FC0472B003C24DB /* ChunkyTriMesh.cpp */,
|
||||
6BB788180FC04753003C24DB /* ChunkyTriMesh.h */,
|
||||
6B137C6A0F7FCBBB00459200 /* demo.cpp */,
|
||||
6B137C7C0F7FCBE400459200 /* SDLMain.h */,
|
||||
6B137C6E0F7FCBBB00459200 /* SDLMain.m */,
|
||||
);
|
||||
name = Classes;
|
||||
@ -277,6 +282,7 @@
|
||||
6BDD9E0A0F91113800904EEF /* DetourDebugDraw.cpp in Sources */,
|
||||
6BDD9E0B0F91113800904EEF /* DetourStatNavMesh.cpp in Sources */,
|
||||
6BDD9E0C0F91113800904EEF /* DetourStatNavMeshBuilder.cpp in Sources */,
|
||||
6BB788170FC0472B003C24DB /* ChunkyTriMesh.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
49
RecastDemo/Include/ChunkyTriMesh.h
Normal file
49
RecastDemo/Include/ChunkyTriMesh.h
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef CHUNKYTRIMESH_H
|
||||
#define CHUNKYTRIMESH_H
|
||||
|
||||
struct rcChunkyTriMeshNode
|
||||
{
|
||||
float bmin[2], bmax[2];
|
||||
int i, n;
|
||||
};
|
||||
|
||||
struct rcChunkyTriMesh
|
||||
{
|
||||
inline rcChunkyTriMesh() : nodes(0), tris(0) {};
|
||||
inline ~rcChunkyTriMesh() { delete [] nodes; delete [] tris; }
|
||||
|
||||
rcChunkyTriMeshNode* nodes;
|
||||
int nnodes;
|
||||
int* tris;
|
||||
int ntris;
|
||||
int maxTrisPerChunk;
|
||||
};
|
||||
|
||||
// Creates partitioned triangle mesh (AABB tree),
|
||||
// where each node contains at max trisPerChunk triangles.
|
||||
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm);
|
||||
|
||||
// Returns the chunk indices which touch the input rectable.
|
||||
int rcGetChunksInRect(const rcChunkyTriMesh* cm, float bmin[2], float bmax[2], int* ids, const int maxIds);
|
||||
|
||||
|
||||
#endif // CHUNKYTRIMESH_H
|
@ -32,12 +32,13 @@ public:
|
||||
inline const int* getTris() const { return m_tris; }
|
||||
inline int getVertCount() const { return m_vertCount; }
|
||||
inline int getTriCount() const { return m_triCount; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void addVertex(float x, float y, float z, int& cap);
|
||||
void addTriangle(int a, int b, int c, int& cap);
|
||||
|
||||
|
||||
float* m_verts;
|
||||
int* m_tris;
|
||||
float* m_normals;
|
||||
|
251
RecastDemo/Source/ChunkyTriMesh.cpp
Normal file
251
RecastDemo/Source/ChunkyTriMesh.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
//
|
||||
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include "ChunkyTriMesh.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct BoundsItem
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
int i;
|
||||
};
|
||||
|
||||
static int compareItemX(const void* va, const void* vb)
|
||||
{
|
||||
const BoundsItem* a = (const BoundsItem*)va;
|
||||
const BoundsItem* b = (const BoundsItem*)vb;
|
||||
if (a->bmin[0] < b->bmin[0])
|
||||
return -1;
|
||||
if (a->bmin[0] > b->bmin[0])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compareItemY(const void* va, const void* vb)
|
||||
{
|
||||
const BoundsItem* a = (const BoundsItem*)va;
|
||||
const BoundsItem* b = (const BoundsItem*)vb;
|
||||
if (a->bmin[1] < b->bmin[1])
|
||||
return -1;
|
||||
if (a->bmin[1] > b->bmin[1])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void calcExtends(BoundsItem* items, int nitems, int imin, int imax,
|
||||
float* bmin, float* bmax)
|
||||
{
|
||||
bmin[0] = items[imin].bmin[0];
|
||||
bmin[1] = items[imin].bmin[1];
|
||||
|
||||
bmax[0] = items[imin].bmax[0];
|
||||
bmax[1] = items[imin].bmax[1];
|
||||
|
||||
for (int i = imin+1; i < imax; ++i)
|
||||
{
|
||||
const BoundsItem& it = items[i];
|
||||
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
|
||||
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
|
||||
|
||||
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
|
||||
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
|
||||
}
|
||||
}
|
||||
|
||||
inline int longestAxis(float x, float y)
|
||||
{
|
||||
int axis = 0;
|
||||
unsigned short maxVal = x;
|
||||
if (y > maxVal)
|
||||
{
|
||||
axis = 1;
|
||||
maxVal = y;
|
||||
}
|
||||
return axis;
|
||||
}
|
||||
|
||||
static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk,
|
||||
int& curNode, rcChunkyTriMeshNode* nodes, const int maxNodes,
|
||||
int& curTri, int* outTris, const int* inTris)
|
||||
{
|
||||
int inum = imax - imin;
|
||||
int icur = curNode;
|
||||
|
||||
if (curNode > maxNodes)
|
||||
return;
|
||||
|
||||
rcChunkyTriMeshNode& node = nodes[curNode++];
|
||||
|
||||
if (inum <= trisPerChunk)
|
||||
{
|
||||
// Leaf
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
|
||||
// Copy triangles.
|
||||
node.i = curTri;
|
||||
node.n = inum;
|
||||
|
||||
for (int i = imin; i < imax; ++i)
|
||||
{
|
||||
const int* src = &inTris[items[i].i*3];
|
||||
int* dst = &outTris[curTri*3];
|
||||
curTri++;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
|
||||
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||
node.bmax[1] - node.bmin[1]);
|
||||
|
||||
if (axis == 0)
|
||||
{
|
||||
// Sort along x-axis
|
||||
qsort(items+imin, inum, sizeof(BoundsItem), compareItemX);
|
||||
}
|
||||
else if (axis == 1)
|
||||
{
|
||||
// Sort along y-axis
|
||||
qsort(items+imin, inum, sizeof(BoundsItem), compareItemY);
|
||||
}
|
||||
|
||||
int isplit = imin+inum/2;
|
||||
|
||||
// Left
|
||||
subdivide(items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
||||
// Right
|
||||
subdivide(items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
||||
|
||||
int iescape = curNode - icur;
|
||||
// Negative index means escape.
|
||||
node.i = -iescape;
|
||||
}
|
||||
}
|
||||
|
||||
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm)
|
||||
{
|
||||
int nchunks = (ntris + trisPerChunk-1) / trisPerChunk;
|
||||
|
||||
cm->nodes = new rcChunkyTriMeshNode[nchunks*4];
|
||||
if (!cm->nodes)
|
||||
return false;
|
||||
|
||||
cm->tris = new int[ntris*3];
|
||||
if (!cm->tris)
|
||||
return false;
|
||||
|
||||
cm->ntris = ntris;
|
||||
|
||||
// Build tree
|
||||
BoundsItem* items = new BoundsItem[ntris];
|
||||
if (!items)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < ntris; i++)
|
||||
{
|
||||
const int* t = &tris[i*3];
|
||||
BoundsItem& it = items[i];
|
||||
it.i = i;
|
||||
// Calc triangle XZ bounds.
|
||||
it.bmin[0] = it.bmax[0] = verts[t[0]*3+0];
|
||||
it.bmin[1] = it.bmax[1] = verts[t[0]*3+2];
|
||||
for (int j = 1; j < 3; ++j)
|
||||
{
|
||||
const float* v = &verts[t[j]*3];
|
||||
if (v[0] < it.bmin[0]) it.bmin[0] = v[0];
|
||||
if (v[2] < it.bmin[1]) it.bmin[1] = v[2];
|
||||
|
||||
if (v[0] > it.bmax[0]) it.bmax[0] = v[0];
|
||||
if (v[2] > it.bmax[1]) it.bmax[1] = v[2];
|
||||
}
|
||||
}
|
||||
|
||||
int curTri = 0;
|
||||
int curNode = 0;
|
||||
subdivide(items, ntris, 0, ntris, trisPerChunk, curNode, cm->nodes, nchunks*4, curTri, cm->tris, tris);
|
||||
|
||||
delete [] items;
|
||||
|
||||
cm->nnodes = curNode;
|
||||
|
||||
// Calc max tris per node.
|
||||
cm->maxTrisPerChunk = 0;
|
||||
for (int i = 0; i < cm->nnodes; ++i)
|
||||
{
|
||||
rcChunkyTriMeshNode& node = cm->nodes[i];
|
||||
const bool isLeaf = node.i >= 0;
|
||||
if (!isLeaf) continue;
|
||||
if (node.n > cm->maxTrisPerChunk)
|
||||
cm->maxTrisPerChunk = node.n;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool checkOverlapRect(const float amin[2], const float amax[2],
|
||||
const float bmin[2], const float bmax[2])
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
|
||||
int rcGetChunksInRect(const rcChunkyTriMesh* cm,
|
||||
float bmin[2], float bmax[2],
|
||||
int* ids, const int maxIds)
|
||||
{
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while (i < cm->nnodes)
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[i];
|
||||
const bool overlap = checkOverlapRect(bmin, bmax, node->bmin, node->bmax);
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
|
||||
if (isLeafNode && overlap)
|
||||
{
|
||||
if (n < maxIds)
|
||||
{
|
||||
ids[n] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap || isLeafNode)
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user