Refactored rcBuildContext to be more customization friendly, changed name to rcContext.

This commit is contained in:
Mikko Mononen 2010-08-24 17:53:38 +00:00
parent 02b189a7cb
commit 5abddbf0cd
28 changed files with 3268 additions and 1444 deletions

View File

@ -37,7 +37,7 @@ bool duReadContourSet(struct rcContourSet& cset, duFileIO* io);
bool duDumpCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io); bool duDumpCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io);
bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io); bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io);
void duLogBuildTimes(rcBuildContext* ctx, const int totalTileUsec); void duLogBuildTimes(rcContext& ctx, const int totalTileUsec);
#endif // RECAST_DUMP_H #endif // RECAST_DUMP_H

View File

@ -399,41 +399,41 @@ bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io)
} }
static void logLine(rcBuildContext* ctx, rcBuildTimeLabel label, const char* name, const float pc) static void logLine(rcContext& ctx, rcTimerLabel label, const char* name, const float pc)
{ {
const int t = ctx->getBuildTime(label); const int t = ctx.getAccumulatedTime(label);
if (t < 0) return; if (t < 0) return;
ctx->log(RC_LOG_PROGRESS, "%s:\t%.2fms\t(%.1f%%)", name, t/1000.0f, t*pc); ctx.log(RC_LOG_PROGRESS, "%s:\t%.2fms\t(%.1f%%)", name, t/1000.0f, t*pc);
} }
void duLogBuildTimes(rcBuildContext* ctx, const int totalTimeUsec) void duLogBuildTimes(rcContext& ctx, const int totalTimeUsec)
{ {
const float pc = 100.0f / totalTimeUsec; const float pc = 100.0f / totalTimeUsec;
ctx->log(RC_LOG_PROGRESS, "Build Times"); ctx.log(RC_LOG_PROGRESS, "Build Times");
logLine(ctx, RC_TIME_RASTERIZE_TRIANGLES, "- Rasterize", pc); logLine(ctx, RC_TIMER_RASTERIZE_TRIANGLES, "- Rasterize", pc);
logLine(ctx, RC_TIME_BUILD_COMPACTHEIGHFIELD, "- Build Compact", pc); logLine(ctx, RC_TIMER_BUILD_COMPACTHEIGHFIELD, "- Build Compact", pc);
logLine(ctx, RC_TIME_FILTER_BORDER, "- Filter Border", pc); logLine(ctx, RC_TIMER_FILTER_BORDER, "- Filter Border", pc);
logLine(ctx, RC_TIME_FILTER_WALKABLE, "- Filter Walkable", pc); logLine(ctx, RC_TIMER_FILTER_WALKABLE, "- Filter Walkable", pc);
logLine(ctx, RC_TIME_ERODE_AREA, "- Erode Area", pc); logLine(ctx, RC_TIMER_ERODE_AREA, "- Erode Area", pc);
logLine(ctx, RC_TIME_MEDIAN_AREA, "- Median Area", pc); logLine(ctx, RC_TIMER_MEDIAN_AREA, "- Median Area", pc);
logLine(ctx, RC_TIME_MARK_BOX_AREA, "- Mark Box Area", pc); logLine(ctx, RC_TIMER_MARK_BOX_AREA, "- Mark Box Area", pc);
logLine(ctx, RC_TIME_MARK_CONVEXPOLY_AREA, "- Mark Convex Area", pc); logLine(ctx, RC_TIMER_MARK_CONVEXPOLY_AREA, "- Mark Convex Area", pc);
logLine(ctx, RC_TIME_BUILD_DISTANCEFIELD, "- Build Disntace Field", pc); logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD, "- Build Disntace Field", pc);
logLine(ctx, RC_TIME_BUILD_DISTANCEFIELD_DIST, " - Distance", pc); logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD_DIST, " - Distance", pc);
logLine(ctx, RC_TIME_BUILD_DISTANCEFIELD_BLUR, " - Blur", pc); logLine(ctx, RC_TIMER_BUILD_DISTANCEFIELD_BLUR, " - Blur", pc);
logLine(ctx, RC_TIME_BUILD_REGIONS, "- Build Regions", pc); logLine(ctx, RC_TIMER_BUILD_REGIONS, "- Build Regions", pc);
logLine(ctx, RC_TIME_BUILD_REGIONS_WATERSHED, " - Watershed", pc); logLine(ctx, RC_TIMER_BUILD_REGIONS_WATERSHED, " - Watershed", pc);
logLine(ctx, RC_TIME_BUILD_REGIONS_EXPAND, " - Expand", pc); logLine(ctx, RC_TIMER_BUILD_REGIONS_EXPAND, " - Expand", pc);
logLine(ctx, RC_TIME_BUILD_REGIONS_FLOOD, " - Find Basins", pc); logLine(ctx, RC_TIMER_BUILD_REGIONS_FLOOD, " - Find Basins", pc);
logLine(ctx, RC_TIME_BUILD_REGIONS_FILTER, " - Filter", pc); logLine(ctx, RC_TIMER_BUILD_REGIONS_FILTER, " - Filter", pc);
logLine(ctx, RC_TIME_BUILD_CONTOURS, "- Build Contours", pc); logLine(ctx, RC_TIMER_BUILD_CONTOURS, "- Build Contours", pc);
logLine(ctx, RC_TIME_BUILD_CONTOURS_TRACE, " - Trace", pc); logLine(ctx, RC_TIMER_BUILD_CONTOURS_TRACE, " - Trace", pc);
logLine(ctx, RC_TIME_BUILD_CONTOURS_SIMPLIFY, " - Simplify", pc); logLine(ctx, RC_TIMER_BUILD_CONTOURS_SIMPLIFY, " - Simplify", pc);
logLine(ctx, RC_TIME_BUILD_POLYMESH, "- Build Polymesh", pc); logLine(ctx, RC_TIMER_BUILD_POLYMESH, "- Build Polymesh", pc);
logLine(ctx, RC_TIME_BUILD_POLYMESHDETAIL, "- Build Polymesh Detail", pc); logLine(ctx, RC_TIMER_BUILD_POLYMESHDETAIL, "- Build Polymesh Detail", pc);
logLine(ctx, RC_TIME_MERGE_POLYMESH, "- Merge Polymeshes", pc); logLine(ctx, RC_TIMER_MERGE_POLYMESH, "- Merge Polymeshes", pc);
logLine(ctx, RC_TIME_MERGE_POLYMESHDETAIL, "- Merge Polymesh Details", pc); logLine(ctx, RC_TIMER_MERGE_POLYMESHDETAIL, "- Merge Polymesh Details", pc);
ctx->log(RC_LOG_PROGRESS, "=== TOTAL:\t%.2fms", totalTimeUsec/1000.0f); ctx.log(RC_LOG_PROGRESS, "=== TOTAL:\t%.2fms", totalTimeUsec/1000.0f);
} }

View File

@ -19,14 +19,6 @@
#ifndef RECAST_H #ifndef RECAST_H
#define RECAST_H #define RECAST_H
#ifdef __GNUC__
#include <stdint.h>
typedef int64_t rcTimeVal;
#else
typedef __int64 rcTimeVal;
#endif
enum rcLogCategory enum rcLogCategory
{ {
RC_LOG_PROGRESS = 1, RC_LOG_PROGRESS = 1,
@ -34,55 +26,74 @@ enum rcLogCategory
RC_LOG_ERROR, RC_LOG_ERROR,
}; };
enum rcBuildTimeLabel enum rcTimerLabel
{ {
RC_TIME_RASTERIZE_TRIANGLES, RC_TIMER_TOTAL,
RC_TIME_BUILD_COMPACTHEIGHFIELD, RC_TIMER_TEMP,
RC_TIME_BUILD_CONTOURS, RC_TIMER_RASTERIZE_TRIANGLES,
RC_TIME_BUILD_CONTOURS_TRACE, RC_TIMER_BUILD_COMPACTHEIGHFIELD,
RC_TIME_BUILD_CONTOURS_SIMPLIFY, RC_TIMER_BUILD_CONTOURS,
RC_TIME_FILTER_BORDER, RC_TIMER_BUILD_CONTOURS_TRACE,
RC_TIME_FILTER_WALKABLE, RC_TIMER_BUILD_CONTOURS_SIMPLIFY,
RC_TIME_MEDIAN_AREA, RC_TIMER_FILTER_BORDER,
RC_TIME_FILTER_LOW_OBSTACLES, RC_TIMER_FILTER_WALKABLE,
RC_TIME_BUILD_POLYMESH, RC_TIMER_MEDIAN_AREA,
RC_TIME_MERGE_POLYMESH, RC_TIMER_FILTER_LOW_OBSTACLES,
RC_TIME_ERODE_AREA, RC_TIMER_BUILD_POLYMESH,
RC_TIME_MARK_BOX_AREA, RC_TIMER_MERGE_POLYMESH,
RC_TIME_MARK_CONVEXPOLY_AREA, RC_TIMER_ERODE_AREA,
RC_TIME_BUILD_DISTANCEFIELD, RC_TIMER_MARK_BOX_AREA,
RC_TIME_BUILD_DISTANCEFIELD_DIST, RC_TIMER_MARK_CONVEXPOLY_AREA,
RC_TIME_BUILD_DISTANCEFIELD_BLUR, RC_TIMER_BUILD_DISTANCEFIELD,
RC_TIME_BUILD_REGIONS, RC_TIMER_BUILD_DISTANCEFIELD_DIST,
RC_TIME_BUILD_REGIONS_WATERSHED, RC_TIMER_BUILD_DISTANCEFIELD_BLUR,
RC_TIME_BUILD_REGIONS_EXPAND, RC_TIMER_BUILD_REGIONS,
RC_TIME_BUILD_REGIONS_FLOOD, RC_TIMER_BUILD_REGIONS_WATERSHED,
RC_TIME_BUILD_REGIONS_FILTER, RC_TIMER_BUILD_REGIONS_EXPAND,
RC_TIME_BUILD_POLYMESHDETAIL, RC_TIMER_BUILD_REGIONS_FLOOD,
RC_TIME_MERGE_POLYMESHDETAIL, RC_TIMER_BUILD_REGIONS_FILTER,
RC_MAX_TIMES RC_TIMER_BUILD_POLYMESHDETAIL,
RC_TIMER_MERGE_POLYMESHDETAIL,
RC_MAX_TIMERS
}; };
// Build context provides several optional utilities needed for the build process, // Build context provides several optional utilities needed for the build process,
// such as timing, logging, and build time collecting. // such as timing, logging, and build time collecting.
struct rcBuildContext class rcContext
{ {
// Get current time in platform specific units. public:
virtual rcTimeVal getTime() { return 0; } inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {}
// Returns time passed from 'start' to 'end' in microseconds. virtual ~rcContext() {}
virtual int getDeltaTimeUsec(const rcTimeVal /*start*/, const rcTimeVal /*end*/) { return 0; }
// Enables or disables logging.
inline void enableLog(bool state) { m_logEnabled = state; }
// Resets log. // Resets log.
virtual void resetLog() {} inline void resetLog() { if (m_logEnabled) doResetLog(); }
// Logs a message. // Logs a message.
virtual void log(const rcLogCategory /*category*/, const char* /*format*/, ...) {} void log(const rcLogCategory category, const char* format, ...);
// Resets build time collecting. // Enables or disables timer.
virtual void resetBuildTimes() {} inline void enableTimer(bool state) { m_timerEnabled = state; }
// Reports build time of specified label for accumulation. // Resets all timers.
virtual void reportBuildTime(const rcBuildTimeLabel /*label*/, const int /*time*/) {} inline void resetTimers() { if (m_timerEnabled) doResetTimers(); }
// Returns accumulated build time for specified label, or -1 if no time was reported. // Starts timer, used for performance timing.
virtual int getBuildTime(const rcBuildTimeLabel /*label*/) { return -1; } inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); }
// Stops timer, used for performance timing.
inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); }
// Returns time accumulated between timer start/stop.
inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; }
protected:
// Virtual functions to override for custom implementations.
virtual void doResetLog() {}
virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {}
virtual void doResetTimers() {}
virtual void doStartTimer(const rcTimerLabel /*label*/) {}
virtual void doStopTimer(const rcTimerLabel /*label*/) {}
virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; }
bool m_logEnabled;
bool m_timerEnabled;
}; };
@ -143,6 +154,10 @@ struct rcHeightfield
rcSpan* freelist; // Pointer to next free span. rcSpan* freelist; // Pointer to next free span.
}; };
rcHeightfield* rcAllocHeightfield();
void rcFreeHeightField(rcHeightfield* hf);
struct rcCompactCell struct rcCompactCell
{ {
unsigned int index : 24; // Index to first span in column. unsigned int index : 24; // Index to first span in column.
@ -160,9 +175,6 @@ struct rcCompactSpan
// Compact static heightfield. // Compact static heightfield.
struct rcCompactHeightfield struct rcCompactHeightfield
{ {
rcCompactHeightfield();
~rcCompactHeightfield();
int width, height; // Width and height of the heighfield. int width, height; // Width and height of the heighfield.
int spanCount; // Number of spans in the heightfield. int spanCount; // Number of spans in the heightfield.
int walkableHeight, walkableClimb; // Agent properties. int walkableHeight, walkableClimb; // Agent properties.
@ -176,6 +188,10 @@ struct rcCompactHeightfield
unsigned char* areas; // Pointer to per span area ID. unsigned char* areas; // Pointer to per span area ID.
}; };
rcCompactHeightfield* rcAllocCompactHeightfield();
void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
struct rcContour struct rcContour
{ {
int* verts; // Vertex coordinates, each vertex contains 4 components. int* verts; // Vertex coordinates, each vertex contains 4 components.
@ -194,6 +210,10 @@ struct rcContourSet
float cs, ch; // Cell size and height. float cs, ch; // Cell size and height.
}; };
rcContourSet* rcAllocContourSet();
void rcFreeContourSet(rcContourSet* cset);
// Polymesh store a connected mesh of polygons. // Polymesh store a connected mesh of polygons.
// The polygons are store in an array where each polygons takes // The polygons are store in an array where each polygons takes
// 'nvp*2' elements. The first 'nvp' elements are indices to vertices // 'nvp*2' elements. The first 'nvp' elements are indices to vertices
@ -220,6 +240,10 @@ struct rcPolyMesh
float cs, ch; // Cell size and height. float cs, ch; // Cell size and height.
}; };
rcPolyMesh* rcAllocPolyMesh();
void rcFreePolyMesh(rcPolyMesh* pmesh);
// Detail mesh generated from a rcPolyMesh. // Detail mesh generated from a rcPolyMesh.
// Each submesh represents a polygon in the polymesh and they are stored in // Each submesh represents a polygon in the polymesh and they are stored in
// excatly same order. Each submesh is described as 4 values: // excatly same order. Each submesh is described as 4 values:
@ -240,19 +264,6 @@ struct rcPolyMeshDetail
int ntris; // Number of triangles. int ntris; // Number of triangles.
}; };
// Allocators and destructors for Recast objects.
rcHeightfield* rcAllocHeightfield();
void rcFreeHeightField(rcHeightfield* hf);
rcCompactHeightfield* rcAllocCompactHeightfield();
void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
rcContourSet* rcAllocContourSet();
void rcFreeContourSet(rcContourSet* cset);
rcPolyMesh* rcAllocPolyMesh();
void rcFreePolyMesh(rcPolyMesh* pmesh);
rcPolyMeshDetail* rcAllocPolyMeshDetail(); rcPolyMeshDetail* rcAllocPolyMeshDetail();
void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh); void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh);
@ -432,7 +443,7 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int*
// bmin, bmax - (in) bounding box of the heightfield // bmin, bmax - (in) bounding box of the heightfield
// cs - (in) grid cell size // cs - (in) grid cell size
// ch - (in) grid cell height // ch - (in) grid cell height
bool rcCreateHeightfield(rcBuildContext* ctx, rcHeightfield& hf, int width, int height, bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height,
const float* bmin, const float* bmax, const float* bmin, const float* bmax,
float cs, float ch); float cs, float ch);
@ -445,7 +456,7 @@ bool rcCreateHeightfield(rcBuildContext* ctx, rcHeightfield& hf, int width, int
// tris - (in) array of triangle vertex indices // tris - (in) array of triangle vertex indices
// nt - (in) triangle count // nt - (in) triangle count
// areas - (out) array of triangle area types // areas - (out) array of triangle area types
void rcMarkWalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
const int* tris, int nt, unsigned char* areas); const int* tris, int nt, unsigned char* areas);
// Sets the RC_NULL_AREA for every triangle whose slope is steeper than // Sets the RC_NULL_AREA for every triangle whose slope is steeper than
@ -457,7 +468,7 @@ void rcMarkWalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAngle
// tris - (in) array of triangle vertex indices // tris - (in) array of triangle vertex indices
// nt - (in) triangle count // nt - (in) triangle count
// areas - (out) array of triangle are types // areas - (out) array of triangle are types
void rcClearUnwalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
const int* tris, int nt, unsigned char* areas); const int* tris, int nt, unsigned char* areas);
// Adds span to heighfield. // Adds span to heighfield.
@ -470,7 +481,7 @@ void rcClearUnwalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAn
// smin,smax - (in) spans min/max height // smin,smax - (in) spans min/max height
// flags - (in) span flags (zero or WALKABLE) // flags - (in) span flags (zero or WALKABLE)
// flagMergeThr - (in) merge threshold. // flagMergeThr - (in) merge threshold.
void rcAddSpan(rcBuildContext* ctx, rcHeightfield& solid, const int x, const int y, void rcAddSpan(rcContext* ctx, rcHeightfield& solid, const int x, const int y,
const unsigned short smin, const unsigned short smax, const unsigned short smin, const unsigned short smax,
const unsigned short area, const int flagMergeThr); const unsigned short area, const int flagMergeThr);
@ -480,7 +491,7 @@ void rcAddSpan(rcBuildContext* ctx, rcHeightfield& solid, const int x, const int
// area - (in) area type of the triangle. // area - (in) area type of the triangle.
// solid - (in) heighfield where the triangle is rasterized // solid - (in) heighfield where the triangle is rasterized
// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable. // flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
void rcRasterizeTriangle(rcBuildContext* ctx, const float* v0, const float* v1, const float* v2, void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
const unsigned char area, rcHeightfield& solid, const unsigned char area, rcHeightfield& solid,
const int flagMergeThr = 1); const int flagMergeThr = 1);
@ -493,7 +504,7 @@ void rcRasterizeTriangle(rcBuildContext* ctx, const float* v0, const float* v1,
// nt - (in) triangle count // nt - (in) triangle count
// solid - (in) heighfield where the triangles are rasterized // solid - (in) heighfield where the triangles are rasterized
// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable. // flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
const int* tris, const unsigned char* areas, const int nt, const int* tris, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr = 1); rcHeightfield& solid, const int flagMergeThr = 1);
@ -506,7 +517,7 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv,
// nt - (in) triangle count // nt - (in) triangle count
// solid - (in) heighfield where the triangles are rasterized // solid - (in) heighfield where the triangles are rasterized
// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable. // flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
const unsigned short* tris, const unsigned char* areas, const int nt, const unsigned short* tris, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr = 1); rcHeightfield& solid, const int flagMergeThr = 1);
@ -516,7 +527,7 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv,
// area - (in) array of triangle area types. // area - (in) array of triangle area types.
// nt - (in) triangle count // nt - (in) triangle count
// solid - (in) heighfield where the triangles are rasterized // solid - (in) heighfield where the triangles are rasterized
void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const unsigned char* areas, const int nt, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr = 1); rcHeightfield& solid, const int flagMergeThr = 1);
// Marks non-walkable low obstacles as walkable if they are closer than walkableClimb // Marks non-walkable low obstacles as walkable if they are closer than walkableClimb
@ -526,7 +537,7 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const unsigne
// walkableHeight - (in) minimum height where the agent can still walk // walkableHeight - (in) minimum height where the agent can still walk
// solid - (in/out) heightfield describing the solid space // solid - (in/out) heightfield describing the solid space
// TODO: Missuses ledge flag, must be called before rcFilterLedgeSpans! // TODO: Missuses ledge flag, must be called before rcFilterLedgeSpans!
void rcFilterLowHangingWalkableObstacles(rcBuildContext* ctx, const int walkableClimb, rcHeightfield& solid); void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid);
// Removes WALKABLE flag from all spans that are at ledges. This filtering // Removes WALKABLE flag from all spans that are at ledges. This filtering
// removes possible overestimation of the conservative voxelization so that // removes possible overestimation of the conservative voxelization so that
@ -535,20 +546,20 @@ void rcFilterLowHangingWalkableObstacles(rcBuildContext* ctx, const int walkable
// walkableHeight - (in) minimum height where the agent can still walk // walkableHeight - (in) minimum height where the agent can still walk
// walkableClimb - (in) maximum height between grid cells the agent can climb // walkableClimb - (in) maximum height between grid cells the agent can climb
// solid - (in/out) heightfield describing the solid space // solid - (in/out) heightfield describing the solid space
void rcFilterLedgeSpans(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& solid); void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& solid);
// Removes WALKABLE flag from all spans which have smaller than // Removes WALKABLE flag from all spans which have smaller than
// 'walkableHeight' clearane above them. // 'walkableHeight' clearane above them.
// Params: // Params:
// walkableHeight - (in) minimum height where the agent can still walk // walkableHeight - (in) minimum height where the agent can still walk
// solid - (in/out) heightfield describing the solid space // solid - (in/out) heightfield describing the solid space
void rcFilterWalkableLowHeightSpans(rcBuildContext* ctx, int walkableHeight, rcHeightfield& solid); void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid);
// Returns number of spans contained in a heightfield. // Returns number of spans contained in a heightfield.
// Params: // Params:
// hf - (in) heightfield to be compacted // hf - (in) heightfield to be compacted
// Returns number of spans. // Returns number of spans.
int rcGetHeightFieldSpanCount(rcBuildContext* ctx, rcHeightfield& hf); int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf);
// Builds compact representation of the heightfield. // Builds compact representation of the heightfield.
// Params: // Params:
@ -558,7 +569,7 @@ int rcGetHeightFieldSpanCount(rcBuildContext* ctx, rcHeightfield& hf);
// hf - (in) heightfield to be compacted // hf - (in) heightfield to be compacted
// chf - (out) compact heightfield representing the open space. // chf - (out) compact heightfield representing the open space.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
rcHeightfield& hf, rcCompactHeightfield& chf); rcHeightfield& hf, rcCompactHeightfield& chf);
// Erodes walkable area. // Erodes walkable area.
@ -566,20 +577,20 @@ bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, co
// radius - (in) radius of erosion (max 255). // radius - (in) radius of erosion (max 255).
// chf - (in/out) compact heightfield to erode. // chf - (in/out) compact heightfield to erode.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcErodeWalkableArea(rcBuildContext* ctx, int radius, rcCompactHeightfield& chf); bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf);
// Applies median filter to walkable area types, removing noise. // Applies median filter to walkable area types, removing noise.
// Params: // Params:
// chf - (in/out) compact heightfield to erode. // chf - (in/out) compact heightfield to erode.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcMedianFilterWalkableArea(rcBuildContext* ctx, rcCompactHeightfield& chf); bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf);
// Marks the area of the convex polygon into the area type of the compact heighfield. // Marks the area of the convex polygon into the area type of the compact heighfield.
// Params: // Params:
// bmin/bmax - (in) bounds of the axis aligned box. // bmin/bmax - (in) bounds of the axis aligned box.
// areaId - (in) area ID to mark. // areaId - (in) area ID to mark.
// chf - (in/out) compact heightfield to mark. // chf - (in/out) compact heightfield to mark.
void rcMarkBoxArea(rcBuildContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
rcCompactHeightfield& chf); rcCompactHeightfield& chf);
// Marks the area of the convex polygon into the area type of the compact heighfield. // Marks the area of the convex polygon into the area type of the compact heighfield.
@ -589,7 +600,7 @@ void rcMarkBoxArea(rcBuildContext* ctx, const float* bmin, const float* bmax, un
// hmin/hmax - (in) min and max height of the polygon. // hmin/hmax - (in) min and max height of the polygon.
// areaId - (in) area ID to mark. // areaId - (in) area ID to mark.
// chf - (in/out) compact heightfield to mark. // chf - (in/out) compact heightfield to mark.
void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nverts, void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
const float hmin, const float hmax, unsigned char areaId, const float hmin, const float hmax, unsigned char areaId,
rcCompactHeightfield& chf); rcCompactHeightfield& chf);
@ -597,7 +608,7 @@ void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nve
// Params: // Params:
// chf - (in/out) compact heightfield representing the open space. // chf - (in/out) compact heightfield representing the open space.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf); bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf);
// Divides the walkable heighfied into simple regions using watershed partitioning. // Divides the walkable heighfied into simple regions using watershed partitioning.
// Each region has only one contour and no overlaps. // Each region has only one contour and no overlaps.
@ -612,7 +623,7 @@ bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf);
// minRegionSize - (in) the smallest allowed regions size. // minRegionSize - (in) the smallest allowed regions size.
// maxMergeRegionSize - (in) the largest allowed regions size which can be merged. // maxMergeRegionSize - (in) the largest allowed regions size which can be merged.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf, bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionSize, const int mergeRegionSize); const int borderSize, const int minRegionSize, const int mergeRegionSize);
// Divides the walkable heighfied into simple regions using simple monotone partitioning. // Divides the walkable heighfied into simple regions using simple monotone partitioning.
@ -628,7 +639,7 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
// minRegionSize - (in) the smallest allowed regions size. // minRegionSize - (in) the smallest allowed regions size.
// maxMergeRegionSize - (in) the largest allowed regions size which can be merged. // maxMergeRegionSize - (in) the largest allowed regions size which can be merged.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf, bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionSize, const int mergeRegionSize); const int borderSize, const int minRegionSize, const int mergeRegionSize);
// Builds simplified contours from the regions outlines. // Builds simplified contours from the regions outlines.
@ -639,7 +650,7 @@ bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf,
// cset - (out) Resulting contour set. // cset - (out) Resulting contour set.
// flags - (in) build flags, see rcBuildContoursFlags. // flags - (in) build flags, see rcBuildContoursFlags.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf, bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
const float maxError, const int maxEdgeLen, const float maxError, const int maxEdgeLen,
rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES); rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES);
@ -649,9 +660,9 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
// nvp - (in) maximum number of vertices per polygon. // nvp - (in) maximum number of vertices per polygon.
// mesh - (out) poly mesh. // mesh - (out) poly mesh.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildPolyMesh(rcBuildContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh); bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh);
bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh);
// Builds detail triangle mesh for each polygon in the poly mesh. // Builds detail triangle mesh for each polygon in the poly mesh.
// Params: // Params:
@ -661,11 +672,11 @@ bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmesh
// sampleMaxError - (in) maximum allowed distance between simplified detail mesh and height sample. // sampleMaxError - (in) maximum allowed distance between simplified detail mesh and height sample.
// pmdtl - (out) detail mesh. // pmdtl - (out) detail mesh.
// Returns false if operation ran out of memory. // Returns false if operation ran out of memory.
bool rcBuildPolyMeshDetail(rcBuildContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
const float sampleDist, const float sampleMaxError, const float sampleDist, const float sampleMaxError,
rcPolyMeshDetail& dmesh); rcPolyMeshDetail& dmesh);
bool rcMergePolyMeshDetails(rcBuildContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh);
#endif // RECAST_H #endif // RECAST_H

View File

@ -22,6 +22,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
#include "Recast.h" #include "Recast.h"
#include "RecastAlloc.h" #include "RecastAlloc.h"
#include "RecastAssert.h" #include "RecastAssert.h"
@ -31,6 +32,25 @@ float rcSqrt(float x)
return sqrtf(x); return sqrtf(x);
} }
void rcContext::log(const rcLogCategory category, const char* format, ...)
{
if (!m_logEnabled)
return;
static const int MSG_SIZE = 512;
char msg[MSG_SIZE];
va_list ap;
va_start(ap, format);
int len = vsnprintf(msg, MSG_SIZE, format, ap);
if (len >= MSG_SIZE)
{
len = MSG_SIZE-1;
msg[MSG_SIZE-1] = '\0';
}
va_end(ap);
doLog(category, msg, len);
}
rcHeightfield* rcAllocHeightfield() rcHeightfield* rcAllocHeightfield()
{ {
rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM); rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM);
@ -143,7 +163,7 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int*
*h = (int)((bmax[2] - bmin[2])/cs+0.5f); *h = (int)((bmax[2] - bmin[2])/cs+0.5f);
} }
bool rcCreateHeightfield(rcBuildContext* /*ctx*/, rcHeightfield& hf, int width, int height, bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height,
const float* bmin, const float* bmax, const float* bmin, const float* bmax,
float cs, float ch) float cs, float ch)
{ {
@ -172,7 +192,7 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
rcVnormalize(norm); rcVnormalize(norm);
} }
void rcMarkWalkableTriangles(rcBuildContext* /*ctx*/, const float walkableSlopeAngle, void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
const float* verts, int /*nv*/, const float* verts, int /*nv*/,
const int* tris, int nt, const int* tris, int nt,
unsigned char* areas) unsigned char* areas)
@ -194,7 +214,7 @@ void rcMarkWalkableTriangles(rcBuildContext* /*ctx*/, const float walkableSlopeA
} }
} }
void rcClearUnwalkableTriangles(rcBuildContext* /*ctx*/, const float walkableSlopeAngle, void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
const float* verts, int /*nv*/, const float* verts, int /*nv*/,
const int* tris, int nt, const int* tris, int nt,
unsigned char* areas) unsigned char* areas)
@ -216,7 +236,7 @@ void rcClearUnwalkableTriangles(rcBuildContext* /*ctx*/, const float walkableSlo
} }
} }
int rcGetHeightFieldSpanCount(rcBuildContext* /*ctx*/, rcHeightfield& hf) int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf)
{ {
// TODO: VC complains about unref formal variable, figure out a way to handle this better. // TODO: VC complains about unref formal variable, figure out a way to handle this better.
// rcAssert(ctx); // rcAssert(ctx);
@ -238,12 +258,12 @@ int rcGetHeightFieldSpanCount(rcBuildContext* /*ctx*/, rcHeightfield& hf)
return spanCount; return spanCount;
} }
bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
rcHeightfield& hf, rcCompactHeightfield& chf) rcHeightfield& hf, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHFIELD);
const int w = hf.width; const int w = hf.width;
const int h = hf.height; const int h = hf.height;
@ -371,9 +391,7 @@ bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, co
tooHighNeighbour, MAX_LAYERS); tooHighNeighbour, MAX_LAYERS);
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHFIELD);
ctx->reportBuildTime(RC_TIME_BUILD_COMPACTHEIGHFIELD, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }

View File

@ -27,14 +27,14 @@
#include "RecastAssert.h" #include "RecastAssert.h"
bool rcErodeWalkableArea(rcBuildContext* ctx, int radius, rcCompactHeightfield& chf) bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
const int w = chf.width; const int w = chf.width;
const int h = chf.height; const int h = chf.height;
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_ERODE_AREA);
unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
if (!dist) if (!dist)
@ -196,9 +196,7 @@ bool rcErodeWalkableArea(rcBuildContext* ctx, int radius, rcCompactHeightfield&
rcFree(dist); rcFree(dist);
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_ERODE_AREA);
ctx->reportBuildTime(RC_TIME_ERODE_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }
@ -216,14 +214,14 @@ static void insertSort(unsigned char* a, const int n)
} }
bool rcMedianFilterWalkableArea(rcBuildContext* ctx, rcCompactHeightfield& chf) bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
const int w = chf.width; const int w = chf.width;
const int h = chf.height; const int h = chf.height;
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_MEDIAN_AREA);
unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
if (!areas) if (!areas)
@ -285,19 +283,17 @@ bool rcMedianFilterWalkableArea(rcBuildContext* ctx, rcCompactHeightfield& chf)
rcFree(areas); rcFree(areas);
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_MEDIAN_AREA);
ctx->reportBuildTime(RC_TIME_MEDIAN_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }
void rcMarkBoxArea(rcBuildContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
rcCompactHeightfield& chf) rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_MARK_BOX_AREA);
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
@ -333,9 +329,7 @@ void rcMarkBoxArea(rcBuildContext* ctx, const float* bmin, const float* bmax, un
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_MARK_BOX_AREA);
ctx->reportBuildTime(RC_TIME_MARK_BOX_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
} }
@ -354,13 +348,13 @@ static int pointInPoly(int nvert, const float* verts, const float* p)
return c; return c;
} }
void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nverts, void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
const float hmin, const float hmax, unsigned char areaId, const float hmin, const float hmax, unsigned char areaId,
rcCompactHeightfield& chf) rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
float bmin[3], bmax[3]; float bmin[3], bmax[3];
rcVcopy(bmin, verts); rcVcopy(bmin, verts);
@ -419,7 +413,5 @@ void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nve
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
ctx->reportBuildTime(RC_TIME_MARK_CONVEXPOLY_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
} }

View File

@ -592,7 +592,7 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
return true; return true;
} }
bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf, bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
const float maxError, const int maxEdgeLen, const float maxError, const int maxEdgeLen,
rcContourSet& cset, const int buildFlags) rcContourSet& cset, const int buildFlags)
{ {
@ -601,7 +601,7 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
const int w = chf.width; const int w = chf.width;
const int h = chf.height; const int h = chf.height;
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_CONTOURS);
rcVcopy(cset.bmin, chf.bmin); rcVcopy(cset.bmin, chf.bmin);
rcVcopy(cset.bmax, chf.bmax); rcVcopy(cset.bmax, chf.bmax);
@ -621,8 +621,7 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
return false; return false;
} }
rcTimeVal traceStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
// Mark boundaries. // Mark boundaries.
for (int y = 0; y < h; ++y) for (int y = 0; y < h; ++y)
@ -657,9 +656,9 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
} }
} }
rcTimeVal traceEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
rcTimeVal simplifyStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
rcIntArray verts(256); rcIntArray verts(256);
rcIntArray simplified(64); rcIntArray simplified(64);
@ -797,13 +796,9 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
} }
} }
rcTimeVal simplifyEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_CONTOURS);
ctx->reportBuildTime(RC_TIME_BUILD_CONTOURS, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->reportBuildTime(RC_TIME_BUILD_CONTOURS_TRACE, ctx->getDeltaTimeUsec(traceStartTime, traceEndTime));
ctx->reportBuildTime(RC_TIME_BUILD_CONTOURS_SIMPLIFY, ctx->getDeltaTimeUsec(simplifyStartTime, simplifyEndTime));
return true; return true;
} }

View File

@ -23,11 +23,11 @@
#include "RecastAssert.h" #include "RecastAssert.h"
void rcFilterLowHangingWalkableObstacles(rcBuildContext* ctx, const int walkableClimb, rcHeightfield& solid) void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
const int w = solid.width; const int w = solid.width;
const int h = solid.height; const int h = solid.height;
@ -56,17 +56,15 @@ void rcFilterLowHangingWalkableObstacles(rcBuildContext* ctx, const int walkable
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
ctx->reportBuildTime(RC_TIME_FILTER_LOW_OBSTACLES, ctx->getDeltaTimeUsec(startTime, endTime));
} }
void rcFilterLedgeSpans(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb,
rcHeightfield& solid) rcHeightfield& solid)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_FILTER_BORDER);
const int w = solid.width; const int w = solid.width;
const int h = solid.height; const int h = solid.height;
@ -148,16 +146,14 @@ void rcFilterLedgeSpans(rcBuildContext* ctx, const int walkableHeight, const int
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_FILTER_BORDER);
ctx->reportBuildTime(RC_TIME_FILTER_BORDER, ctx->getDeltaTimeUsec(startTime, endTime));
} }
void rcFilterWalkableLowHeightSpans(rcBuildContext* ctx, int walkableHeight, rcHeightfield& solid) void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_FILTER_WALKABLE);
const int w = solid.width; const int w = solid.width;
const int h = solid.height; const int h = solid.height;
@ -179,7 +175,5 @@ void rcFilterWalkableLowHeightSpans(rcBuildContext* ctx, int walkableHeight, rcH
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_FILTER_WALKABLE);
ctx->reportBuildTime(RC_TIME_FILTER_WALKABLE, ctx->getDeltaTimeUsec(startTime, endTime));
} }

View File

@ -483,7 +483,7 @@ static void pushBack(int v, int* arr, int& an)
an++; an++;
} }
static bool canRemoveVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigned short rem) static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short rem)
{ {
const int nvp = mesh.nvp; const int nvp = mesh.nvp;
@ -585,7 +585,7 @@ static bool canRemoveVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigne
return true; return true;
} }
static bool removeVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigned short rem, const int maxTris) static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short rem, const int maxTris)
{ {
const int nvp = mesh.nvp; const int nvp = mesh.nvp;
@ -893,11 +893,11 @@ static bool removeVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigned s
} }
bool rcBuildPolyMesh(rcBuildContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh) bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_POLYMESH);
rcVcopy(mesh.bmin, cset.bmin); rcVcopy(mesh.bmin, cset.bmin);
rcVcopy(mesh.bmax, cset.bmax); rcVcopy(mesh.bmax, cset.bmax);
@ -1163,21 +1163,19 @@ bool rcBuildPolyMesh(rcBuildContext* ctx, rcContourSet& cset, int nvp, rcPolyMes
} }
memset(mesh.flags, 0, sizeof(unsigned short) * mesh.npolys); memset(mesh.flags, 0, sizeof(unsigned short) * mesh.npolys);
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_POLYMESH);
ctx->reportBuildTime(RC_TIME_BUILD_POLYMESH, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }
bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
{ {
rcAssert(ctx); rcAssert(ctx);
if (!nmeshes || !meshes) if (!nmeshes || !meshes)
return true; return true;
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_MERGE_POLYMESH);
mesh.nvp = meshes[0]->nvp; mesh.nvp = meshes[0]->nvp;
mesh.cs = meshes[0]->cs; mesh.cs = meshes[0]->cs;
@ -1300,10 +1298,7 @@ bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmesh
return false; return false;
} }
ctx->stopTimer(RC_TIMER_MERGE_POLYMESH);
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_MERGE_POLYMESH, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }

View File

@ -255,7 +255,7 @@ static int findEdge(const int* edges, int nedges, int s, int t)
return UNDEF; return UNDEF;
} }
static int addEdge(rcBuildContext* ctx, int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r) static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r)
{ {
if (nedges >= maxEdges) if (nedges >= maxEdges)
{ {
@ -317,7 +317,7 @@ static bool overlapEdges(const float* pts, const int* edges, int nedges, int s1,
return false; return false;
} }
static void completeFacet(rcBuildContext* ctx, const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e) static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e)
{ {
static const float EPS = 1e-5f; static const float EPS = 1e-5f;
@ -413,7 +413,7 @@ static void completeFacet(rcBuildContext* ctx, const float* pts, int npts, int*
} }
} }
static void delaunayHull(rcBuildContext* ctx, const int npts, const float* pts, static void delaunayHull(rcContext* ctx, const int npts, const float* pts,
const int nhull, const int* hull, const int nhull, const int* hull,
rcIntArray& tris, rcIntArray& edges) rcIntArray& tris, rcIntArray& edges)
{ {
@ -491,7 +491,7 @@ static void delaunayHull(rcBuildContext* ctx, const int npts, const float* pts,
static bool buildPolyDetail(rcBuildContext* ctx, const float* in, const int nin, static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
const float sampleDist, const float sampleMaxError, const float sampleDist, const float sampleMaxError,
const rcCompactHeightfield& chf, const rcHeightPatch& hp, const rcCompactHeightfield& chf, const rcHeightPatch& hp,
float* verts, int& nverts, rcIntArray& tris, float* verts, int& nverts, rcIntArray& tris,
@ -914,14 +914,14 @@ static unsigned char getTriFlags(const float* va, const float* vb, const float*
bool rcBuildPolyMeshDetail(rcBuildContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
const float sampleDist, const float sampleMaxError, const float sampleDist, const float sampleMaxError,
rcPolyMeshDetail& dmesh) rcPolyMeshDetail& dmesh)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL);
if (mesh.nverts == 0 || mesh.npolys == 0) if (mesh.nverts == 0 || mesh.npolys == 0)
return true; return true;
@ -1126,19 +1126,17 @@ bool rcBuildPolyMeshDetail(rcBuildContext* ctx, const rcPolyMesh& mesh, const rc
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL);
ctx->reportBuildTime(RC_TIME_BUILD_POLYMESHDETAIL, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }
bool rcMergePolyMeshDetails(rcBuildContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh) bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_MERGE_POLYMESHDETAIL);
int maxVerts = 0; int maxVerts = 0;
int maxTris = 0; int maxTris = 0;
int maxMeshes = 0; int maxMeshes = 0;
@ -1206,9 +1204,7 @@ bool rcMergePolyMeshDetails(rcBuildContext* ctx, rcPolyMeshDetail** meshes, cons
} }
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_MERGE_POLYMESHDETAIL);
ctx->reportBuildTime(RC_TIME_MERGE_POLYMESHDETAIL, ctx->getDeltaTimeUsec(startTime, endTime));
return true; return true;
} }

View File

@ -154,7 +154,7 @@ static void addSpan(rcHeightfield& hf, const int x, const int y,
} }
} }
void rcAddSpan(rcBuildContext* /*ctx*/, rcHeightfield& hf, const int x, const int y, void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y,
const unsigned short smin, const unsigned short smax, const unsigned short smin, const unsigned short smax,
const unsigned char area, const int flagMergeThr) const unsigned char area, const int flagMergeThr)
{ {
@ -276,30 +276,28 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2,
} }
} }
void rcRasterizeTriangle(rcBuildContext* ctx, const float* v0, const float* v1, const float* v2, void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
const unsigned char area, rcHeightfield& solid, const unsigned char area, rcHeightfield& solid,
const int flagMergeThr) const int flagMergeThr)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs; const float ics = 1.0f/solid.cs;
const float ich = 1.0f/solid.ch; const float ich = 1.0f/solid.ch;
rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
} }
void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int /*nv*/, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
const int* tris, const unsigned char* areas, const int nt, const int* tris, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr) rcHeightfield& solid, const int flagMergeThr)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs; const float ics = 1.0f/solid.cs;
const float ich = 1.0f/solid.ch; const float ich = 1.0f/solid.ch;
@ -313,18 +311,16 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int /*n
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
} }
void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int /*nv*/, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
const unsigned short* tris, const unsigned char* areas, const int nt, const unsigned short* tris, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr) rcHeightfield& solid, const int flagMergeThr)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs; const float ics = 1.0f/solid.cs;
const float ich = 1.0f/solid.ch; const float ich = 1.0f/solid.ch;
@ -338,17 +334,15 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int /*n
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
} }
void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const unsigned char* areas, const int nt, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr) rcHeightfield& solid, const int flagMergeThr)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs; const float ics = 1.0f/solid.cs;
const float ich = 1.0f/solid.ch; const float ich = 1.0f/solid.ch;
@ -362,7 +356,5 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const unsigne
rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
} }
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
} }

View File

@ -687,7 +687,7 @@ static void walkContour(int x, int y, int i, int dir,
} }
} }
static bool filterSmallRegions(rcBuildContext* ctx, int minRegionSize, int mergeRegionSize, static bool filterSmallRegions(rcContext* ctx, int minRegionSize, int mergeRegionSize,
unsigned short& maxRegionId, unsigned short& maxRegionId,
rcCompactHeightfield& chf, rcCompactHeightfield& chf,
unsigned short* srcReg) unsigned short* srcReg)
@ -886,11 +886,11 @@ static bool filterSmallRegions(rcBuildContext* ctx, int minRegionSize, int merge
} }
bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf) bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD);
if (chf.dist) if (chf.dist)
{ {
@ -914,14 +914,14 @@ bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf)
unsigned short maxDist = 0; unsigned short maxDist = 0;
rcTimeVal distStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST);
calculateDistanceField(chf, src, maxDist); calculateDistanceField(chf, src, maxDist);
chf.maxDistance = maxDist; chf.maxDistance = maxDist;
rcTimeVal distEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST);
rcTimeVal blurStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR);
// Blur // Blur
if (boxBlur(chf, 1, src, dst) != src) if (boxBlur(chf, 1, src, dst) != src)
@ -930,16 +930,10 @@ bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf)
// Store distance. // Store distance.
chf.dist = src; chf.dist = src;
rcTimeVal blurEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR);
rcFree(dst); rcFree(dst);
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_BUILD_DISTANCEFIELD, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->reportBuildTime(RC_TIME_BUILD_DISTANCEFIELD_DIST, ctx->getDeltaTimeUsec(distStartTime, distEndTime));
ctx->reportBuildTime(RC_TIME_BUILD_DISTANCEFIELD_BLUR, ctx->getDeltaTimeUsec(blurStartTime, blurEndTime));
return true; return true;
} }
@ -973,12 +967,12 @@ struct rcSweepSpan
unsigned short nei; // neighbour id unsigned short nei; // neighbour id
}; };
bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf, bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionSize, const int mergeRegionSize) const int borderSize, const int minRegionSize, const int mergeRegionSize)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS);
const int w = chf.width; const int w = chf.width;
const int h = chf.height; const int h = chf.height;
@ -1101,33 +1095,30 @@ bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf,
} }
} }
rcTimeVal filterStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER);
// Filter out small regions. // Filter out small regions.
chf.maxRegions = id; chf.maxRegions = id;
if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg)) if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg))
return false; return false;
rcTimeVal filterEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER);
// Store the result out. // Store the result out.
for (int i = 0; i < chf.spanCount; ++i) for (int i = 0; i < chf.spanCount; ++i)
chf.spans[i].reg = srcReg[i]; chf.spans[i].reg = srcReg[i];
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_REGIONS);
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_FILTER, ctx->getDeltaTimeUsec(filterStartTime, filterEndTime));
return true; return true;
} }
bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf, bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionSize, const int mergeRegionSize) const int borderSize, const int minRegionSize, const int mergeRegionSize)
{ {
rcAssert(ctx); rcAssert(ctx);
rcTimeVal startTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS);
const int w = chf.width; const int w = chf.width;
const int h = chf.height; const int h = chf.height;
@ -1139,7 +1130,7 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
return false; return false;
} }
rcTimeVal regStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS_WATERSHED);
rcIntArray stack(1024); rcIntArray stack(1024);
rcIntArray visited(1024); rcIntArray visited(1024);
@ -1166,15 +1157,12 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
paintRectRegion(w-borderSize, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; paintRectRegion(w-borderSize, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
paintRectRegion(0, w, 0, borderSize, regionId|RC_BORDER_REG, chf, srcReg); regionId++; paintRectRegion(0, w, 0, borderSize, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
paintRectRegion(0, w, h-borderSize, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; paintRectRegion(0, w, h-borderSize, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
rcTimeVal expTime = 0;
rcTimeVal floodTime = 0;
while (level > 0) while (level > 0)
{ {
level = level >= 2 ? level-2 : 0; level = level >= 2 ? level-2 : 0;
rcTimeVal expStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS_EXPAND);
// Expand current regions until no empty connected cells found. // Expand current regions until no empty connected cells found.
if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg) if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg)
@ -1183,9 +1171,9 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
rcSwap(srcDist, dstDist); rcSwap(srcDist, dstDist);
} }
expTime += ctx->getTime() - expStartTime; ctx->stopTimer(RC_TIMER_BUILD_REGIONS_EXPAND);
rcTimeVal floodStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS_FLOOD);
// Mark new regions with IDs. // Mark new regions with IDs.
for (int y = 0; y < h; ++y) for (int y = 0; y < h; ++y)
@ -1204,7 +1192,7 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
} }
} }
floodTime += ctx->getTime() - floodStartTime; ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FLOOD);
} }
@ -1215,29 +1203,23 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
rcSwap(srcDist, dstDist); rcSwap(srcDist, dstDist);
} }
rcTimeVal regEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_REGIONS_WATERSHED);
rcTimeVal filterStartTime = ctx->getTime(); ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER);
// Filter out small regions. // Filter out small regions.
chf.maxRegions = regionId; chf.maxRegions = regionId;
if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg)) if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg))
return false; return false;
rcTimeVal filterEndTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER);
// Write the result out. // Write the result out.
for (int i = 0; i < chf.spanCount; ++i) for (int i = 0; i < chf.spanCount; ++i)
chf.spans[i].reg = srcReg[i]; chf.spans[i].reg = srcReg[i];
rcTimeVal endTime = ctx->getTime(); ctx->stopTimer(RC_TIMER_BUILD_REGIONS);
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_WATERSHED, ctx->getDeltaTimeUsec(regStartTime, regEndTime));
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_EXPAND, ctx->getDeltaTimeUsec(0, expTime));
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_FLOOD, ctx->getDeltaTimeUsec(0, floodTime));
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_FILTER, ctx->getDeltaTimeUsec(filterStartTime, filterEndTime));
return true; return true;
} }

File diff suppressed because it is too large Load Diff

View File

@ -290,7 +290,7 @@
</array> </array>
</array> </array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 388}, {264, 660}}</string> <string>{{0, 196}, {264, 660}}</string>
</dict> </dict>
<key>PBXTopSmartGroupGIDs</key> <key>PBXTopSmartGroupGIDs</key>
<array/> <array/>
@ -337,7 +337,7 @@
<key>_historyCapacity</key> <key>_historyCapacity</key>
<integer>0</integer> <integer>0</integer>
<key>bookmark</key> <key>bookmark</key>
<string>6BA687751222F02E00730711</string> <string>6BD402B112243CEA00995864</string>
<key>history</key> <key>history</key>
<array> <array>
<string>6BBB4AA5115B4F3400CF791D</string> <string>6BBB4AA5115B4F3400CF791D</string>
@ -348,74 +348,79 @@
<string>6BF5F2E511748884000502A6</string> <string>6BF5F2E511748884000502A6</string>
<string>6BF5F2E611748884000502A6</string> <string>6BF5F2E611748884000502A6</string>
<string>6BF5F2E711748884000502A6</string> <string>6BF5F2E711748884000502A6</string>
<string>6BF5F5041176F5F8000502A6</string>
<string>6B4214D911803923006C347B</string> <string>6B4214D911803923006C347B</string>
<string>6B98462E11E6141900FA177B</string> <string>6B98462E11E6141900FA177B</string>
<string>6B98473011E737D800FA177B</string> <string>6B98473011E737D800FA177B</string>
<string>6BF9B12C11EB8CF20043574C</string>
<string>6BAF3CB012116AD9008CFCDF</string> <string>6BAF3CB012116AD9008CFCDF</string>
<string>6BAF3CB112116AD9008CFCDF</string> <string>6BAF3CB112116AD9008CFCDF</string>
<string>6BAF3CB412116AD9008CFCDF</string> <string>6BAF3CB412116AD9008CFCDF</string>
<string>6BAF3E781212869F008CFCDF</string> <string>6BAF3E781212869F008CFCDF</string>
<string>6BAF404F12140B4E008CFCDF</string> <string>6BAF404F12140B4E008CFCDF</string>
<string>6BAF405112140B4E008CFCDF</string>
<string>6BAF40F412197F3D008CFCDF</string> <string>6BAF40F412197F3D008CFCDF</string>
<string>6BAF427E121ADD46008CFCDF</string>
<string>6BAF4280121ADD46008CFCDF</string>
<string>6BAF4321121AF998008CFCDF</string> <string>6BAF4321121AF998008CFCDF</string>
<string>6BAF43FB121C241D008CFCDF</string> <string>6BAF43FB121C241D008CFCDF</string>
<string>6BAF4421121C25E3008CFCDF</string> <string>6BAF4421121C25E3008CFCDF</string>
<string>6BAF4422121C25E3008CFCDF</string> <string>6BAF4422121C25E3008CFCDF</string>
<string>6BAF4446121C40AC008CFCDF</string> <string>6BAF4446121C40AC008CFCDF</string>
<string>6BAF446E121C4895008CFCDF</string>
<string>6BAF44D9121C4DFC008CFCDF</string>
<string>6BAF44DE121C54D4008CFCDF</string> <string>6BAF44DE121C54D4008CFCDF</string>
<string>6BAF4524121D1723008CFCDF</string> <string>6BAF4524121D1723008CFCDF</string>
<string>6BAF4525121D1723008CFCDF</string> <string>6BAF4525121D1723008CFCDF</string>
<string>6BAF4562121D1849008CFCDF</string> <string>6BAF4562121D1849008CFCDF</string>
<string>6BAF457D121D19CB008CFCDF</string>
<string>6BAF457E121D19CB008CFCDF</string>
<string>6BAF457F121D19CB008CFCDF</string>
<string>6BAF4580121D19CB008CFCDF</string>
<string>6BAF4581121D19CB008CFCDF</string>
<string>6BAF4582121D19CB008CFCDF</string>
<string>6BAF4593121D1B18008CFCDF</string>
<string>6BAF45B8121D2F37008CFCDF</string>
<string>6BAF45E4121D7277008CFCDF</string> <string>6BAF45E4121D7277008CFCDF</string>
<string>6BAF4604121D7388008CFCDF</string>
<string>6BAF4605121D7388008CFCDF</string>
<string>6BAF4637121D74D3008CFCDF</string> <string>6BAF4637121D74D3008CFCDF</string>
<string>6BAF46A2121D8B41008CFCDF</string>
<string>6BAF46D3121D8FF1008CFCDF</string> <string>6BAF46D3121D8FF1008CFCDF</string>
<string>6BAF4739121D9FBE008CFCDF</string> <string>6BAF4739121D9FBE008CFCDF</string>
<string>6BAF473A121D9FBE008CFCDF</string>
<string>6BAF4747121D9FED008CFCDF</string> <string>6BAF4747121D9FED008CFCDF</string>
<string>6BAF475A121DA31D008CFCDF</string> <string>6BAF475A121DA31D008CFCDF</string>
<string>6BAF475B121DA31D008CFCDF</string> <string>6BAF475B121DA31D008CFCDF</string>
<string>6BAF475C121DA31D008CFCDF</string>
<string>6B1C8D82121E80950048697F</string>
<string>6B1C8DA2121E813D0048697F</string>
<string>6B1C8DB3121E8D970048697F</string> <string>6B1C8DB3121E8D970048697F</string>
<string>6B1C8DC0121E8F610048697F</string>
<string>6B1C8DC5121E902F0048697F</string> <string>6B1C8DC5121E902F0048697F</string>
<string>6B1C8E08121EB4FF0048697F</string> <string>6B1C8E08121EB4FF0048697F</string>
<string>6B1C8E0A121EB4FF0048697F</string> <string>6B1C8E0A121EB4FF0048697F</string>
<string>6B1C8E24121EB6D30048697F</string> <string>6B1C8E24121EB6D30048697F</string>
<string>6B1C8E27121EB6D30048697F</string> <string>6B1C8E27121EB6D30048697F</string>
<string>6B1C8E6A1221BC910048697F</string>
<string>6BA687441222EADA00730711</string>
<string>6BA687451222EADA00730711</string> <string>6BA687451222EADA00730711</string>
<string>6BA687461222EADA00730711</string>
<string>6BA687471222EADA00730711</string>
<string>6BA687481222EADA00730711</string> <string>6BA687481222EADA00730711</string>
<string>6BA6874A1222EADA00730711</string>
<string>6BA6874B1222EADA00730711</string>
<string>6BA6874C1222EADA00730711</string>
<string>6BA6874D1222EADA00730711</string>
<string>6BA6876C1222F02E00730711</string>
<string>6BA6876D1222F02E00730711</string>
<string>6BA6876E1222F02E00730711</string> <string>6BA6876E1222F02E00730711</string>
<string>6BA687701222F02E00730711</string> <string>6BA687831222F42100730711</string>
<string>6BA687881222F4DB00730711</string>
<string>6BA687CA1222FA9300730711</string>
<string>6BA687D81222FC4700730711</string>
<string>6BA687E4122300C300730711</string>
<string>6BA688091223041E00730711</string>
<string>6BA688211223066C00730711</string>
<string>6BA6887B1223122200730711</string>
<string>6BA688D1122321D800730711</string>
<string>6BD4020A1224336600995864</string>
<string>6BD4020B1224336600995864</string>
<string>6BD4020C1224336600995864</string>
<string>6BD4020D1224336600995864</string>
<string>6BD4020E1224336600995864</string>
<string>6BD4020F1224336600995864</string>
<string>6BD402111224336600995864</string>
<string>6BD402121224336600995864</string>
<string>6BD402161224336600995864</string>
<string>6BD402461224345E00995864</string>
<string>6BD402481224345E00995864</string>
<string>6BD402491224345E00995864</string>
<string>6BD4024A1224345E00995864</string>
<string>6BD4025F1224387200995864</string>
<string>6BD402601224387200995864</string>
<string>6BD402611224387200995864</string>
<string>6BD402621224387200995864</string>
<string>6BD402631224387200995864</string>
<string>6BD402641224387200995864</string>
<string>6BD402671224387200995864</string>
<string>6BD402811224393000995864</string>
<string>6BD402871224395C00995864</string>
<string>6BD4028C1224399300995864</string>
<string>6BD4029B12243A8000995864</string>
<string>6BD4029C12243A8000995864</string>
<string>6BD4029D12243A8000995864</string>
<string>6BD402A612243C8100995864</string>
<string>6BD402AB12243CEA00995864</string>
<string>6BD402AC12243CEA00995864</string>
<string>6BD402AD12243CEA00995864</string>
</array> </array>
<key>prevStack</key> <key>prevStack</key>
<array> <array>
@ -443,7 +448,6 @@
<string>6BF5F2ED11748884000502A6</string> <string>6BF5F2ED11748884000502A6</string>
<string>6BF5F2EE11748884000502A6</string> <string>6BF5F2EE11748884000502A6</string>
<string>6BF5F33911759C3C000502A6</string> <string>6BF5F33911759C3C000502A6</string>
<string>6B98465411E6F9B400FA177B</string>
<string>6B98466011E6F9B400FA177B</string> <string>6B98466011E6F9B400FA177B</string>
<string>6B98471011E734A100FA177B</string> <string>6B98471011E734A100FA177B</string>
<string>6B98471211E734A100FA177B</string> <string>6B98471211E734A100FA177B</string>
@ -457,7 +461,6 @@
<string>6BAF3A3B1210235F008CFCDF</string> <string>6BAF3A3B1210235F008CFCDF</string>
<string>6BAF3ABC121038F9008CFCDF</string> <string>6BAF3ABC121038F9008CFCDF</string>
<string>6BAF3B0612112E63008CFCDF</string> <string>6BAF3B0612112E63008CFCDF</string>
<string>6BAF3B1512112F65008CFCDF</string>
<string>6BAF3DAA1211882E008CFCDF</string> <string>6BAF3DAA1211882E008CFCDF</string>
<string>6BAF3E631211B713008CFCDF</string> <string>6BAF3E631211B713008CFCDF</string>
<string>6BBB4AE2115B4F3400CF791D</string> <string>6BBB4AE2115B4F3400CF791D</string>
@ -467,18 +470,14 @@
<string>6BAF4243121AD679008CFCDF</string> <string>6BAF4243121AD679008CFCDF</string>
<string>6BAF4289121ADD46008CFCDF</string> <string>6BAF4289121ADD46008CFCDF</string>
<string>6BAF4396121C1F3D008CFCDF</string> <string>6BAF4396121C1F3D008CFCDF</string>
<string>6BAF43A1121C1F3D008CFCDF</string>
<string>6BAF43BE121C1F3D008CFCDF</string> <string>6BAF43BE121C1F3D008CFCDF</string>
<string>6BAF43D1121C2164008CFCDF</string> <string>6BAF43D1121C2164008CFCDF</string>
<string>6BAF43D2121C2164008CFCDF</string> <string>6BAF43D2121C2164008CFCDF</string>
<string>6BAF4453121C40AC008CFCDF</string>
<string>6BAF4456121C40AC008CFCDF</string> <string>6BAF4456121C40AC008CFCDF</string>
<string>6B98477411E7406900FA177B</string> <string>6B98477411E7406900FA177B</string>
<string>6BAF3861120A8A8E008CFCDF</string> <string>6BAF3861120A8A8E008CFCDF</string>
<string>6BAF410212197F3D008CFCDF</string>
<string>6BAF44FA121C5713008CFCDF</string> <string>6BAF44FA121C5713008CFCDF</string>
<string>6BAF45E9121D7277008CFCDF</string> <string>6BAF45E9121D7277008CFCDF</string>
<string>6BAF447E121C4895008CFCDF</string>
<string>6BAF473D121D9FBE008CFCDF</string> <string>6BAF473D121D9FBE008CFCDF</string>
<string>6BAF4749121D9FED008CFCDF</string> <string>6BAF4749121D9FED008CFCDF</string>
<string>6BAF4762121DA31D008CFCDF</string> <string>6BAF4762121DA31D008CFCDF</string>
@ -486,30 +485,89 @@
<string>6BAF4768121DA31D008CFCDF</string> <string>6BAF4768121DA31D008CFCDF</string>
<string>6B1C8DDB121EA3470048697F</string> <string>6B1C8DDB121EA3470048697F</string>
<string>6B1C8E2A121EB6D30048697F</string> <string>6B1C8E2A121EB6D30048697F</string>
<string>6B1C8E2B121EB6D30048697F</string>
<string>6B1C8E2D121EB6D30048697F</string> <string>6B1C8E2D121EB6D30048697F</string>
<string>6B1C8E58121EBEBF0048697F</string>
<string>6BA6874E1222EADA00730711</string>
<string>6BA6874F1222EADA00730711</string> <string>6BA6874F1222EADA00730711</string>
<string>6BA687501222EADA00730711</string>
<string>6BA687511222EADA00730711</string>
<string>6BA687521222EADA00730711</string>
<string>6BA687531222EADA00730711</string> <string>6BA687531222EADA00730711</string>
<string>6BA687541222EADA00730711</string>
<string>6BA687551222EADA00730711</string>
<string>6BA687561222EADA00730711</string>
<string>6BA687571222EADA00730711</string>
<string>6BA687581222EADA00730711</string>
<string>6BA687591222EADA00730711</string>
<string>6BA6875A1222EADA00730711</string>
<string>6BA6875B1222EADA00730711</string>
<string>6BA6875C1222EADA00730711</string>
<string>6BA6875D1222EADA00730711</string>
<string>6BA6875E1222EADA00730711</string>
<string>6BA6875F1222EADA00730711</string>
<string>6BA687711222F02E00730711</string>
<string>6BA687721222F02E00730711</string>
<string>6BA687731222F02E00730711</string> <string>6BA687731222F02E00730711</string>
<string>6BA687BC1222F82500730711</string>
<string>6BA687BD1222F82500730711</string>
<string>6BA6881D1223060400730711</string>
<string>6BA688231223066C00730711</string>
<string>6BA6885412230ECD00730711</string>
<string>6BD402191224336600995864</string>
<string>6BD4021A1224336600995864</string>
<string>6BD4021B1224336600995864</string>
<string>6BD4021C1224336600995864</string>
<string>6BD4021D1224336600995864</string>
<string>6BD4021E1224336600995864</string>
<string>6BD4021F1224336600995864</string>
<string>6BD402201224336600995864</string>
<string>6BD402211224336600995864</string>
<string>6BD402221224336600995864</string>
<string>6BD402231224336600995864</string>
<string>6BD402241224336600995864</string>
<string>6BD402251224336600995864</string>
<string>6BD402261224336600995864</string>
<string>6BD402271224336600995864</string>
<string>6BD402281224336600995864</string>
<string>6BD402291224336600995864</string>
<string>6BD4022A1224336600995864</string>
<string>6BD4022B1224336600995864</string>
<string>6BD4022C1224336600995864</string>
<string>6BD4022D1224336600995864</string>
<string>6BD4022E1224336600995864</string>
<string>6BD4022F1224336600995864</string>
<string>6BD402301224336600995864</string>
<string>6BD402311224336600995864</string>
<string>6BD402321224336600995864</string>
<string>6BD402331224336600995864</string>
<string>6BD402341224336600995864</string>
<string>6BD402351224336600995864</string>
<string>6BD402361224336600995864</string>
<string>6BD402371224336600995864</string>
<string>6BD402381224336600995864</string>
<string>6BD402391224336600995864</string>
<string>6BD4023A1224336600995864</string>
<string>6BD4023B1224336600995864</string>
<string>6BD4023C1224336600995864</string>
<string>6BD4023D1224336600995864</string>
<string>6BD4023E1224336600995864</string>
<string>6BD4023F1224336600995864</string>
<string>6BD402401224336600995864</string>
<string>6BD402411224336600995864</string>
<string>6BD4024C1224345E00995864</string>
<string>6BD4024D1224345E00995864</string>
<string>6BD4024E1224345E00995864</string>
<string>6BD4024F1224345E00995864</string>
<string>6BD402501224345E00995864</string>
<string>6BD4026A1224387200995864</string>
<string>6BD4026B1224387200995864</string>
<string>6BD4026C1224387200995864</string>
<string>6BD4026D1224387200995864</string>
<string>6BD4026E1224387200995864</string>
<string>6BD4026F1224387200995864</string>
<string>6BD402701224387200995864</string>
<string>6BD402711224387200995864</string>
<string>6BD402721224387200995864</string>
<string>6BD402731224387200995864</string>
<string>6BD402741224387200995864</string>
<string>6BD402751224387200995864</string>
<string>6BD402761224387200995864</string>
<string>6BD402831224393000995864</string>
<string>6BD402841224393000995864</string>
<string>6BD402891224395C00995864</string>
<string>6BD4028E1224399300995864</string>
<string>6BD4028F1224399300995864</string>
<string>6BD402901224399300995864</string>
<string>6BD402911224399300995864</string>
<string>6BD402921224399300995864</string>
<string>6BD4029F12243A8000995864</string>
<string>6BD402A012243A8000995864</string>
<string>6BD402A112243A8000995864</string>
<string>6BD402A812243C8100995864</string>
<string>6BD402AE12243CEA00995864</string>
<string>6BD402AF12243CEA00995864</string>
<string>6BD402B012243CEA00995864</string>
</array> </array>
</dict> </dict>
<key>SplitCount</key> <key>SplitCount</key>
@ -523,18 +581,18 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{0, 0}, {994, 381}}</string> <string>{{0, 0}, {994, 493}}</string>
<key>RubberWindowFrame</key> <key>RubberWindowFrame</key>
<string>0 59 1280 719 0 0 1280 778 </string> <string>0 59 1280 719 0 0 1280 778 </string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXNavigatorGroup</string> <string>PBXNavigatorGroup</string>
<key>Proportion</key> <key>Proportion</key>
<string>381pt</string> <string>493pt</string>
</dict> </dict>
<dict> <dict>
<key>Proportion</key> <key>Proportion</key>
<string>292pt</string> <string>180pt</string>
<key>Tabs</key> <key>Tabs</key>
<array> <array>
<dict> <dict>
@ -548,7 +606,7 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{10, 27}, {994, 304}}</string> <string>{{10, 27}, {994, 81}}</string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>XCDetailModule</string> <string>XCDetailModule</string>
@ -564,7 +622,9 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{10, 27}, {994, 304}}</string> <string>{{10, 27}, {994, 153}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1280 719 0 0 1280 778 </string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXProjectFindModule</string> <string>PBXProjectFindModule</string>
@ -602,9 +662,7 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{10, 27}, {994, 265}}</string> <string>{{10, 27}, {994, 83}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1280 719 0 0 1280 778 </string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXBuildResultsModule</string> <string>PBXBuildResultsModule</string>
@ -632,11 +690,11 @@
</array> </array>
<key>TableOfContents</key> <key>TableOfContents</key>
<array> <array>
<string>6BA687641222EAE200730711</string> <string>6BD401FC1224235500995864</string>
<string>1CA23ED40692098700951B8B</string> <string>1CA23ED40692098700951B8B</string>
<string>6BA687651222EAE200730711</string> <string>6BD401FD1224235500995864</string>
<string>6B8632A30F78115100E2684A</string> <string>6B8632A30F78115100E2684A</string>
<string>6BA687661222EAE200730711</string> <string>6BD401FE1224235500995864</string>
<string>1CA23EDF0692099D00951B8B</string> <string>1CA23EDF0692099D00951B8B</string>
<string>1CA23EE00692099D00951B8B</string> <string>1CA23EE00692099D00951B8B</string>
<string>1CA23EE10692099D00951B8B</string> <string>1CA23EE10692099D00951B8B</string>
@ -687,12 +745,12 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{0, 0}, {1280, 411}}</string> <string>{{0, 0}, {1280, 328}}</string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXDebugCLIModule</string> <string>PBXDebugCLIModule</string>
<key>Proportion</key> <key>Proportion</key>
<string>411pt</string> <string>328pt</string>
</dict> </dict>
<dict> <dict>
<key>ContentConfiguration</key> <key>ContentConfiguration</key>
@ -711,8 +769,8 @@
<string>yes</string> <string>yes</string>
<key>sizes</key> <key>sizes</key>
<array> <array>
<string>{{0, 0}, {577, 109}}</string> <string>{{0, 0}, {577, 144}}</string>
<string>{{577, 0}, {703, 109}}</string> <string>{{577, 0}, {703, 144}}</string>
</array> </array>
</dict> </dict>
<key>VerticalSplitView</key> <key>VerticalSplitView</key>
@ -727,8 +785,8 @@
<string>yes</string> <string>yes</string>
<key>sizes</key> <key>sizes</key>
<array> <array>
<string>{{0, 0}, {1280, 109}}</string> <string>{{0, 0}, {1280, 144}}</string>
<string>{{0, 109}, {1280, 153}}</string> <string>{{0, 144}, {1280, 201}}</string>
</array> </array>
</dict> </dict>
</dict> </dict>
@ -748,7 +806,7 @@
<key>DebugSTDIOWindowFrame</key> <key>DebugSTDIOWindowFrame</key>
<string>{{200, 200}, {500, 300}}</string> <string>{{200, 200}, {500, 300}}</string>
<key>Frame</key> <key>Frame</key>
<string>{{0, 416}, {1280, 262}}</string> <string>{{0, 333}, {1280, 345}}</string>
<key>PBXDebugSessionStackFrameViewKey</key> <key>PBXDebugSessionStackFrameViewKey</key>
<dict> <dict>
<key>DebugVariablesTableConfiguration</key> <key>DebugVariablesTableConfiguration</key>
@ -761,13 +819,13 @@
<real>410</real> <real>410</real>
</array> </array>
<key>Frame</key> <key>Frame</key>
<string>{{577, 0}, {703, 109}}</string> <string>{{577, 0}, {703, 144}}</string>
</dict> </dict>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXDebugSessionModule</string> <string>PBXDebugSessionModule</string>
<key>Proportion</key> <key>Proportion</key>
<string>262pt</string> <string>345pt</string>
</dict> </dict>
</array> </array>
<key>Name</key> <key>Name</key>
@ -785,14 +843,14 @@
</array> </array>
<key>TableOfContents</key> <key>TableOfContents</key>
<array> <array>
<string>6BA687671222EAE200730711</string> <string>6BD402781224387200995864</string>
<string>1CCC7628064C1048000F2A68</string> <string>1CCC7628064C1048000F2A68</string>
<string>1CCC7629064C1048000F2A68</string> <string>1CCC7629064C1048000F2A68</string>
<string>6BA687681222EAE200730711</string> <string>6BD402791224387200995864</string>
<string>6BA687691222EAE200730711</string> <string>6BD4027A1224387200995864</string>
<string>6BA6876A1222EAE200730711</string> <string>6BD4027B1224387200995864</string>
<string>6BA6876B1222EAE200730711</string> <string>6BD4027C1224387200995864</string>
<string>6B8632A30F78115100E2684A</string> <string>6BD4027D1224387200995864</string>
</array> </array>
<key>ToolbarConfigUserDefaultsMinorVersion</key> <key>ToolbarConfigUserDefaultsMinorVersion</key>
<string>2</string> <string>2</string>

View File

@ -46,6 +46,7 @@
6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */; }; 6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */; };
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; }; 6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; };
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; }; 6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; };
6BD402011224279400995864 /* PerfTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BD402001224279400995864 /* PerfTimer.cpp */; };
6BF5F23A11747606000502A6 /* Filelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23911747606000502A6 /* Filelist.cpp */; }; 6BF5F23A11747606000502A6 /* Filelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23911747606000502A6 /* Filelist.cpp */; };
6BF5F2401174763B000502A6 /* SlideShow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; }; 6BF5F2401174763B000502A6 /* SlideShow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23F1174763B000502A6 /* SlideShow.cpp */; };
6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C13F1111953A002B3F46 /* TestCase.cpp */; }; 6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C13F1111953A002B3F46 /* TestCase.cpp */; };
@ -131,6 +132,8 @@
6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastDump.cpp; path = ../../../DebugUtils/Source/RecastDump.cpp; sourceTree = SOURCE_ROOT; }; 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastDump.cpp; path = ../../../DebugUtils/Source/RecastDump.cpp; sourceTree = SOURCE_ROOT; };
6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OffMeshConnectionTool.h; path = ../../Include/OffMeshConnectionTool.h; sourceTree = SOURCE_ROOT; }; 6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OffMeshConnectionTool.h; path = ../../Include/OffMeshConnectionTool.h; sourceTree = SOURCE_ROOT; };
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; }; 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; };
6BD401FF1224278800995864 /* PerfTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PerfTimer.h; path = ../../Include/PerfTimer.h; sourceTree = SOURCE_ROOT; };
6BD402001224279400995864 /* PerfTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PerfTimer.cpp; path = ../../Source/PerfTimer.cpp; sourceTree = SOURCE_ROOT; };
6BF5F23911747606000502A6 /* Filelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Filelist.cpp; path = ../../Source/Filelist.cpp; sourceTree = SOURCE_ROOT; }; 6BF5F23911747606000502A6 /* Filelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Filelist.cpp; path = ../../Source/Filelist.cpp; sourceTree = SOURCE_ROOT; };
6BF5F23C11747614000502A6 /* Filelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Filelist.h; path = ../../Include/Filelist.h; sourceTree = SOURCE_ROOT; }; 6BF5F23C11747614000502A6 /* Filelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Filelist.h; path = ../../Include/Filelist.h; sourceTree = SOURCE_ROOT; };
6BF5F23E1174763B000502A6 /* SlideShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SlideShow.h; path = ../../Include/SlideShow.h; sourceTree = SOURCE_ROOT; }; 6BF5F23E1174763B000502A6 /* SlideShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SlideShow.h; path = ../../Include/SlideShow.h; sourceTree = SOURCE_ROOT; };
@ -188,6 +191,8 @@
6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */, 6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */,
6BF7C13E11119520002B3F46 /* TestCase.h */, 6BF7C13E11119520002B3F46 /* TestCase.h */,
6BF7C13F1111953A002B3F46 /* TestCase.cpp */, 6BF7C13F1111953A002B3F46 /* TestCase.cpp */,
6BD401FF1224278800995864 /* PerfTimer.h */,
6BD402001224279400995864 /* PerfTimer.cpp */,
); );
name = Classes; name = Classes;
sourceTree = "<group>"; sourceTree = "<group>";
@ -441,6 +446,7 @@
6BAF3C591211663A008CFCDF /* CrowdTool.cpp in Sources */, 6BAF3C591211663A008CFCDF /* CrowdTool.cpp in Sources */,
6BAF40DB12196A3D008CFCDF /* DetourNavMeshQuery.cpp in Sources */, 6BAF40DB12196A3D008CFCDF /* DetourNavMeshQuery.cpp in Sources */,
6BAF4442121C3D26008CFCDF /* SampleInterfaces.cpp in Sources */, 6BAF4442121C3D26008CFCDF /* SampleInterfaces.cpp in Sources */,
6BD402011224279400995864 /* PerfTimer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -39,6 +39,8 @@ struct ObstacleBody
float dp[3], np[3]; // Use for side selection during sampling. float dp[3], np[3]; // Use for side selection during sampling.
bool touch; bool touch;
int type; // Type of the obstacle (see ObstacleType) int type; // Type of the obstacle (see ObstacleType)
float dist;
int idx;
}; };
@ -120,6 +122,34 @@ struct Agent
}; };
struct Isect
{
float u;
int inside;
};
static const int FORM_MAX_ISECT = 32;
static const int FORM_MAX_SEGS = 16;
static const int FORM_MAX_POLYS = 32;
struct FormationSeg
{
float p[3], q[3];
Isect ints[FORM_MAX_ISECT];
int nints;
};
struct Formation
{
FormationSeg segs[FORM_MAX_SEGS];
int nsegs;
dtPolyRef polys[FORM_MAX_POLYS];
int npolys;
};
class SampleGraph class SampleGraph
{ {
static const int MAX_SAMPLES = 512; static const int MAX_SAMPLES = 512;
@ -211,6 +241,8 @@ class CrowdTool : public SampleTool
float m_targetPos[3]; float m_targetPos[3];
bool m_targetPosSet; bool m_targetPosSet;
Formation m_form;
bool m_expandDebugDraw; bool m_expandDebugDraw;
bool m_showLabels; bool m_showLabels;
bool m_showCorners; bool m_showCorners;

View File

@ -55,9 +55,9 @@ public:
InputGeom(); InputGeom();
~InputGeom(); ~InputGeom();
bool loadMesh(struct rcBuildContext* ctx, const char* filepath); bool loadMesh(class rcContext* ctx, const char* filepath);
bool load(struct rcBuildContext* ctx, const char* filepath); bool load(class rcContext* ctx, const char* filepath);
bool save(const char* filepath); bool save(const char* filepath);
// Method to return static mesh data. // Method to return static mesh data.

View File

@ -94,13 +94,13 @@ protected:
SampleTool* m_tool; SampleTool* m_tool;
rcBuildContext* m_ctx; rcContext* m_ctx;
public: public:
Sample(); Sample();
virtual ~Sample(); virtual ~Sample();
void setContext(rcBuildContext* ctx) { m_ctx = ctx; } void setContext(rcContext* ctx) { m_ctx = ctx; }
void setTool(SampleTool* tool); void setTool(SampleTool* tool);

View File

@ -22,13 +22,15 @@
#include "DebugDraw.h" #include "DebugDraw.h"
#include "Recast.h" #include "Recast.h"
#include "RecastDump.h" #include "RecastDump.h"
#include "PerfTimer.h"
// These are example implementations of various interfaces used in Recast and Detour. // These are example implementations of various interfaces used in Recast and Detour.
// Recast build context. // Recast build context.
class BuildContext : public rcBuildContext class BuildContext : public rcContext
{ {
int m_buildTime[RC_MAX_TIMES]; TimeVal m_startTime[RC_MAX_TIMERS];
int m_accTime[RC_MAX_TIMERS];
static const int MAX_MESSAGES = 1000; static const int MAX_MESSAGES = 1000;
const char* m_messages[MAX_MESSAGES]; const char* m_messages[MAX_MESSAGES];
@ -39,17 +41,8 @@ class BuildContext : public rcBuildContext
public: public:
BuildContext(); BuildContext();
~BuildContext(); virtual ~BuildContext();
// Get current time in platform specific units.
virtual rcTimeVal getTime();
// Returns time passed from 'start' to 'end' in microseconds.
virtual int getDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end);
// Resets log.
virtual void resetLog();
// Logs a message.
virtual void log(const rcLogCategory category, const char* format, ...);
// Dumps the log to stdout. // Dumps the log to stdout.
void dumpLog(const char* format, ...); void dumpLog(const char* format, ...);
// Returns number of log messages. // Returns number of log messages.
@ -57,20 +50,16 @@ public:
// Returns log message text. // Returns log message text.
const char* getLogText(const int i) const; const char* getLogText(const int i) const;
// Resets build time collecting. protected:
virtual void resetBuildTimes(); // Virtual functions for custom implementations.
// Reports build time of specified label for accumulation. virtual void doResetLog();
virtual void reportBuildTime(const rcBuildTimeLabel label, const int time); virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/);
// Returns accumulated build time for specified label, or -1 if no time was reported. virtual void doResetTimers();
virtual int getBuildTime(const rcBuildTimeLabel label); virtual void doStartTimer(const rcTimerLabel /*label*/);
virtual void doStopTimer(const rcTimerLabel /*label*/);
virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const;
}; };
// TODO: Find better solution. This is useful for timing in some cases when the full build interface would be overkill.
rcTimeVal getPerfTime();
int getPerfDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end);
// OpenGL debug draw implementation. // OpenGL debug draw implementation.
class DebugDrawGL : public duDebugDraw class DebugDrawGL : public duDebugDraw
{ {

View File

@ -20,7 +20,6 @@
#define TESTCASE_H #define TESTCASE_H
#include "DetourNavMesh.h" #include "DetourNavMesh.h"
#include "Recast.h"
class TestCase class TestCase
{ {
@ -49,9 +48,9 @@ class TestCase
dtPolyRef* polys; dtPolyRef* polys;
int npolys; int npolys;
rcTimeVal findNearestPolyTime; int findNearestPolyTime;
rcTimeVal findPathTime; int findPathTime;
rcTimeVal findStraightPathTime; int findStraightPathTime;
Test* next; Test* next;
}; };
@ -71,7 +70,7 @@ public:
inline const char* getSampleName() const { return m_sampleName; } inline const char* getSampleName() const { return m_sampleName; }
inline const char* getGeomFileName() const { return m_geomFileName; } inline const char* getGeomFileName() const { return m_geomFileName; }
void doTests(rcBuildContext* ctx, class dtNavMesh* navmesh, class dtNavMeshQuery* navquery); void doTests(class dtNavMesh* navmesh, class dtNavMeshQuery* navquery);
void handleRender(); void handleRender();
bool handleRenderOverlay(double* proj, double* model, int* view); bool handleRenderOverlay(double* proj, double* model, int* view);

View File

@ -208,25 +208,31 @@ void normalizeSamples(RVODebugData* rvo)
} }
void setDynCircleBody(ObstacleBody* b, const float* pos, const float rad, const float* vel, const float* dvel) static void setDynCircleBody(ObstacleBody* b, const float* pos, const float rad, const float* vel, const float* dvel,
const float dist, const int idx)
{ {
b->type = BODY_CIRCLE; b->type = BODY_CIRCLE;
dtVcopy(b->p, pos); dtVcopy(b->p, pos);
dtVcopy(b->vel, vel); dtVcopy(b->vel, vel);
dtVcopy(b->dvel, dvel); dtVcopy(b->dvel, dvel);
b->rad = rad; b->rad = rad;
b->dist = dist;
b->idx = idx;
} }
void setStatCircleBody(ObstacleBody* b, const float* pos, const float rad) /*
static void setStatCircleBody(ObstacleBody* b, const float* pos, const float rad)
{ {
b->type = BODY_CIRCLE; b->type = BODY_CIRCLE;
dtVcopy(b->p, pos); dtVcopy(b->p, pos);
dtVset(b->vel, 0,0,0); dtVset(b->vel, 0,0,0);
dtVset(b->dvel, 0,0,0); dtVset(b->dvel, 0,0,0);
b->rad = rad; b->rad = rad;
b->idx = -1;
} }
*/
void setStatSegmentBody(ObstacleBody* b, const float* p, const float* q) static void setStatSegmentBody(ObstacleBody* b, const float* p, const float* q)
{ {
b->type = BODY_SEGMENT; b->type = BODY_SEGMENT;
dtVcopy(b->p, p); dtVcopy(b->p, p);
@ -234,6 +240,7 @@ void setStatSegmentBody(ObstacleBody* b, const float* p, const float* q)
dtVset(b->vel, 0,0,0); dtVset(b->vel, 0,0,0);
dtVset(b->dvel, 0,0,0); dtVset(b->dvel, 0,0,0);
b->rad = 0; b->rad = 0;
b->idx = -1;
} }
static const float VEL_WEIGHT = 2.0f; static const float VEL_WEIGHT = 2.0f;
@ -473,6 +480,53 @@ void sampleRVO(ObstacleBody* agent, const float vmax, const ObstacleBody* obs,
processSamples(agent, vmax, obs, nobs, rvo, spos, cs/2, nspos, nvel); processSamples(agent, vmax, obs, nobs, rvo, spos, cs/2, nspos, nvel);
} }
static void sampleRVOAdaptive(ObstacleBody* agent, const float vmax, const ObstacleBody* obs,
const int nobs, RVODebugData* rvo, const float bias, float* nvel)
{
dtVset(nvel, 0,0,0);
float spos[MAX_RVO_SAMPLES*3];
int nspos = 0;
rvo->ns = 0;
int rad;
float res[3];
float cs;
// First sample location.
rad = 4;
res[0] = agent->dvel[0]*bias;
res[1] = 0;
res[2] = agent->dvel[2]*bias;
cs = vmax*(2-bias*2) / (float)(rad-1);
for (int k = 0; k < 5; ++k)
{
const float half = (rad-1)*cs*0.5f;
nspos = 0;
for (int y = 0; y < rad; ++y)
{
for (int x = 0; x < rad; ++x)
{
const float vx = res[0] + x*cs - half;
const float vz = res[2] + y*cs - half;
if (dtSqr(vx)+dtSqr(vz) > dtSqr(vmax+cs/2)) continue;
spos[nspos*3+0] = vx;
spos[nspos*3+1] = 0;
spos[nspos*3+2] = vz;
nspos++;
}
}
processSamples(agent, vmax, obs, nobs, rvo, spos, cs/2, nspos, res);
cs *= 0.5f;
}
dtVcopy(nvel, res);
}
CrowdManager::CrowdManager() : CrowdManager::CrowdManager() :
@ -571,12 +625,48 @@ static void calcSmoothSteerDirection(const float* pos, const float* corners, con
dvel[2] = dir0[2] - dir1[2]*len0*strength; dvel[2] = dir0[2] - dir1[2]*len0*strength;
} }
/*static void sortBodies(ObstacleBody* arr, const int n)
{
int i, j;
for (i = 1; i < n; i++)
{
const ObstacleBody& v = arr[i];
for (j = i - 1; j >= 0 && arr[j].dist > v.dist; j--)
memcpy(&arr[j+1], &arr[j], sizeof(ObstacleBody));
memcpy(&arr[j+1], &v, sizeof(ObstacleBody));
}
}*/
static ObstacleBody* insertBody(const float dist, ObstacleBody* obs, int& nobs)
{
ObstacleBody* ob = 0;
if (!nobs || dist >= obs[nobs-1].dist)
{
ob = &obs[nobs];
}
else
{
int i;
for (i = 0; i < nobs; ++i)
if (dist <= obs[i].dist)
break;
if (nobs-i > 0)
memmove(obs+i+1, obs+i, sizeof(ObstacleBody)*(nobs-i));
ob = &obs[i];
}
nobs++;
return ob;
}
void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery) void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery)
{ {
if (!navquery) if (!navquery)
return; return;
rcTimeVal startTime = getPerfTime(); TimeVal startTime = getPerfTime();
const float ext[3] = {2,4,2}; const float ext[3] = {2,4,2};
dtQueryFilter filter; dtQueryFilter filter;
@ -716,7 +806,7 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
if (!ag->ncorners) if (!ag->ncorners)
{ {
// No corner to steer to, // No corner to steer to, stop.
dtVset(ag->dvel, 0,0,0); dtVset(ag->dvel, 0,0,0);
} }
else else
@ -760,7 +850,7 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
} }
// Velocity planning. // Velocity planning.
rcTimeVal rvoStartTime = getPerfTime(); TimeVal rvoStartTime = getPerfTime();
static const int MAX_BODIES = 32; static const int MAX_BODIES = 32;
ObstacleBody bodies[MAX_BODIES]; ObstacleBody bodies[MAX_BODIES];
for (int i = 0; i < MAX_AGENTS; ++i) for (int i = 0; i < MAX_AGENTS; ++i)
@ -792,11 +882,14 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
if (nbodies < MAX_BODIES) if (nbodies < MAX_BODIES)
{ {
setDynCircleBody(&bodies[nbodies], nei->pos, nei->radius, nei->vel, nei->dvel); ObstacleBody* body = insertBody(dist, bodies, nbodies);
nbodies++; setDynCircleBody(body, nei->pos, nei->radius, nei->vel, nei->dvel, dist, j);
} }
} }
// Prune mas number of neighbours.
nbodies = dtMin(nbodies, 6);
// Add static obstacles. // Add static obstacles.
for (int j = 0; j < ag->ncolsegs; ++j) for (int j = 0; j < ag->ncolsegs; ++j)
{ {
@ -812,20 +905,16 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
} }
ObstacleBody agent; ObstacleBody agent;
setDynCircleBody(&agent, ag->pos, ag->radius, ag->vel, ag->dvel); setDynCircleBody(&agent, ag->pos, ag->radius, ag->vel, ag->dvel, 0, -1);
prepareBodies(&agent, bodies, nbodies); prepareBodies(&agent, bodies, nbodies);
sampleRVO(&agent, ag->maxspeed, bodies, nbodies, &ag->rvo, 0.4f, ag->nvel); sampleRVOAdaptive(&agent, ag->maxspeed, bodies, nbodies, &ag->rvo, 0.4f, ag->nvel);
// Normalize samples for debug draw
normalizeSamples(&ag->rvo);
} }
else else
{ {
dtVcopy(ag->nvel, ag->dvel); dtVcopy(ag->nvel, ag->dvel);
} }
} }
rcTimeVal rvoEndTime = getPerfTime(); TimeVal rvoEndTime = getPerfTime();
m_rvoTime.addSample(getPerfDeltaTimeUsec(rvoStartTime, rvoEndTime) / 1000.0f);
// Integrate and update perceived velocity. // Integrate and update perceived velocity.
for (int i = 0; i < MAX_AGENTS; ++i) for (int i = 0; i < MAX_AGENTS; ++i)
@ -964,12 +1053,117 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
} }
} }
rcTimeVal endTime = getPerfTime(); TimeVal endTime = getPerfTime();
for (int i = 0; i < MAX_AGENTS; ++i)
{
if (!m_agents[i].active) continue;
if (m_agents[i].targetState != AGENT_TARGET_PATH) continue;
Agent* ag = &m_agents[i];
if (flags & CROWDMAN_USE_VO)
{
// Normalize samples for debug draw
normalizeSamples(&ag->rvo);
}
}
m_totalTime.addSample(getPerfDeltaTimeUsec(startTime, endTime) / 1000.0f); m_totalTime.addSample(getPerfDeltaTimeUsec(startTime, endTime) / 1000.0f);
m_rvoTime.addSample(getPerfDeltaTimeUsec(rvoStartTime, rvoEndTime) / 1000.0f);
} }
static int insertIsect(float u, int inside, Isect* ints, int nints)
{
int i;
if (nints >= FORM_MAX_ISECT) return nints;
if (!nints || u >= ints[nints-1].u)
{
ints[nints].u = u;
ints[nints].inside = inside;
return nints+1;
}
for (i = 0; i < nints; ++i)
if (u <= ints[i].u) break;
if (nints-i > 0) memmove(ints+i+1,ints+i,sizeof(Isect)*(nints-i));
ints[i].u = u;
ints[i].inside = inside;
return nints+1;
}
static int removeAdjacent(Isect* ints, int nints)
{
const float eps = 0.0001f;
if (nints < 2)
return nints;
for (int i = 0; i < nints-1; ++i)
{
if (fabsf(ints[i].u - ints[i+1].u) < eps) // && ints[i].inside != ints[i+1].inside)
{
nints -= 2;
for (int j = i; j < nints; ++j)
ints[j] = ints[j+2];
// if (nints-i > 0) memmove(ints+i,ints+i+2,sizeof(Isect)*(nints-i));
i--;
}
}
return nints;
}
static int getPolyVerts(const dtNavMesh* navMesh, dtPolyRef ref, float* verts)
{
const dtMeshTile* tile = 0;
const dtPoly* poly = 0;
if (!navMesh->getTileAndPolyByRef(ref, &tile, &poly))
return 0;
for (int i = 0; i < (int)poly->vertCount; ++i)
dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]);
return poly->vertCount;
}
static void createFormation(Formation* form, const dtNavMesh* navmesh)
{
float verts[DT_VERTS_PER_POLYGON*3];
for (int i = 0; i < form->nsegs; i++)
{
FormationSeg* seg = &form->segs[i];
seg->nints = 0;
int startInside = 0;
for (int j = 0; j < form->npolys; ++j)
{
const int nverts = getPolyVerts(navmesh, form->polys[j], verts);
if (!nverts) continue;
float tmin, tmax;
int smin, smax;
bool res = dtIntersectSegmentPoly2D(seg->p, seg->q, verts, nverts, tmin, tmax, smin, smax);
if (!res)
continue;
if (tmin >= 0.0f && tmin <= 1.0f)
seg->nints = insertIsect(tmin, 1, seg->ints, seg->nints);
if (tmax >= 0.0f && tmax <= 1.0f)
seg->nints = insertIsect(tmax, -1, seg->ints, seg->nints);
if (tmin < 0.0f && tmax > 0.0f)
startInside++;
}
seg->nints = removeAdjacent(seg->ints, seg->nints);
}
// Calc winding
for (int i = 0; i < form->nsegs; ++i)
{
FormationSeg* seg = &form->segs[i];
int inside = 0;
for (int j = 0; j < seg->nints; ++j)
{
inside += seg->ints[j].inside;
seg->ints[j].inside = inside;
}
}
}
CrowdTool::CrowdTool() : CrowdTool::CrowdTool() :
m_sample(0), m_sample(0),
@ -989,6 +1183,7 @@ CrowdTool::CrowdTool() :
m_run(true), m_run(true),
m_mode(TOOLMODE_CREATE) m_mode(TOOLMODE_CREATE)
{ {
memset(&m_form, 0, sizeof(Formation));
} }
CrowdTool::~CrowdTool() CrowdTool::~CrowdTool()
@ -1105,9 +1300,77 @@ void CrowdTool::handleClick(const float* s, const float* p, bool shift)
else else
{ {
// Add // Add
int idx = m_crowd.addAgent(p, m_sample->getAgentRadius(), m_sample->getAgentHeight()); /* int idx = m_crowd.addAgent(p, m_sample->getAgentRadius(), m_sample->getAgentHeight());
if (idx != -1 && m_targetPosSet) if (idx != -1 && m_targetPosSet)
m_crowd.setMoveTarget(idx, m_targetPos); m_crowd.setMoveTarget(idx, m_targetPos);*/
const dtNavMesh* navmesh = m_sample->getNavMesh();
const dtNavMeshQuery* navquery = m_sample->getNavMeshQuery();
memset(&m_form, 0, sizeof(Formation));
const float ext[3] = {2,4,2};
dtQueryFilter filter;
const float r = m_sample->getAgentRadius();
float nearest[3];
dtPolyRef centerRef = navquery->findNearestPoly(p, ext, &filter, nearest);
if (centerRef)
{
const int rows = 6;
for (int i = 0; i < rows; ++i)
{
const float x0 = -r*2.5f*rows/2 + (i&1)*r;
const float x1 = r*2.5f*rows/2 + (i&1)*r;
const float z = (i-rows*0.5f)*r*2.5f;
dtVset(m_form.segs[m_form.nsegs].p, p[0]+x0, p[1]+2.0f, p[2]+z);
dtVset(m_form.segs[m_form.nsegs].q, p[0]+x1, p[1]+2.0f, p[2]+z);
m_form.nsegs++;
}
m_form.npolys = navquery->findLocalNeighbourhood(centerRef, p, r*rows*2.5f, &filter, m_form.polys, 0, FORM_MAX_POLYS);
createFormation(&m_form, navmesh);
const int createCount = 25;
int num = 0;
const float r = m_sample->getAgentRadius();
for (int i = 0; i < m_form.nsegs; ++i)
{
const FormationSeg* seg = &m_form.segs[i];
for (int j = 0; j < seg->nints-1; ++j)
{
if (seg->ints[j].inside == 0) continue;
const float u0 = seg->ints[j].u;
const float u1 = seg->ints[j+1].u;
float ia[3], ib[3];
dtVlerp(ia, seg->p,seg->q, u0);
dtVlerp(ib, seg->p,seg->q, u1);
const float spacing = r*2.5f;
float delta[3];
dtVsub(delta, ib,ia);
float d = dtVlen(delta);
int np = (int)floorf(d/spacing);
for (int k = 0; k < np; ++k)
{
float pos[3];
dtVmad(pos, ia, delta, (float)(k+0.5f)/(float)np);
if (num < createCount)
{
num++;
int idx = m_crowd.addAgent(pos, m_sample->getAgentRadius(), m_sample->getAgentHeight());
if (idx != -1 && m_targetPosSet)
m_crowd.setMoveTarget(idx, m_targetPos);
}
}
}
}
}
} }
} }
else if (m_mode == TOOLMODE_MOVE) else if (m_mode == TOOLMODE_MOVE)
@ -1306,6 +1569,91 @@ void CrowdTool::handleRender()
dd.depthMask(true); dd.depthMask(true);
} }
/*
for (int i = 0; i < m_form.npolys; ++i)
{
duDebugDrawNavMeshPoly(&dd, *nmesh, m_form.polys[i], duRGBA(255,255,255,32));
}
dd.depthMask(false);
dd.begin(DU_DRAW_POINTS, 4.0f);
for (int i = 0; i < m_form.nsegs; ++i)
{
const FormationSeg* seg = &m_form.segs[i];
for (int j = 0; j < seg->nints-1; ++j)
{
if (seg->ints[j].inside == 0) continue;
const float u0 = seg->ints[j].u;
const float u1 = seg->ints[j+1].u;
float ia[3], ib[3];
dtVlerp(ia, seg->p,seg->q, u0);
dtVlerp(ib, seg->p,seg->q, u1);
dd.vertex(ia,duRGBA(128,0,0,192));
dd.vertex(ib,duRGBA(128,0,0,192));
}
}
dd.end();
dd.begin(DU_DRAW_LINES, 2.0f);
for (int i = 0; i < m_form.nsegs; ++i)
{
const FormationSeg* seg = &m_form.segs[i];
dd.vertex(seg->p,duRGBA(255,255,255,128));
dd.vertex(seg->q,duRGBA(255,255,255,128));
for (int j = 0; j < seg->nints-1; ++j)
{
if (seg->ints[j].inside == 0) continue;
const float u0 = seg->ints[j].u;
const float u1 = seg->ints[j+1].u;
float ia[3], ib[3];
dtVlerp(ia, seg->p,seg->q, u0);
dtVlerp(ib, seg->p,seg->q, u1);
dd.vertex(ia,duRGBA(128,0,0,192));
dd.vertex(ib,duRGBA(128,0,0,192));
}
}
dd.end();
{
const float r = m_sample->getAgentRadius();
dd.begin(DU_DRAW_LINES, 2.0f);
for (int i = 0; i < m_form.nsegs; ++i)
{
const FormationSeg* seg = &m_form.segs[i];
dd.vertex(seg->p,duRGBA(255,255,255,128));
dd.vertex(seg->q,duRGBA(255,255,255,128));
for (int j = 0; j < seg->nints-1; ++j)
{
if (seg->ints[j].inside == 0) continue;
const float u0 = seg->ints[j].u;
const float u1 = seg->ints[j+1].u;
float ia[3], ib[3];
dtVlerp(ia, seg->p,seg->q, u0);
dtVlerp(ib, seg->p,seg->q, u1);
const float spacing = r*2.5f;
float delta[3];
dtVsub(delta, ib,ia);
float d = dtVlen(delta);
int np = (int)floorf(d/spacing);
for (int k = 0; k < np; ++k)
{
float pos[3];
dtVmad(pos, ia, delta, (float)(k+0.5f)/(float)np);
dd.vertex(pos[0],pos[1]-1,pos[2],duRGBA(128,0,0,192));
dd.vertex(pos[0],pos[1]+2,pos[2],duRGBA(128,0,0,192));
}
}
}
dd.end();
}
dd.depthMask(true);
*/
} }
@ -1401,7 +1749,7 @@ void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
} }
const int gx = 300, gy = 10, gw = 500, gh = 200; const int gx = 300, gy = 10, gw = 500, gh = 200;
const float vmin = 0.0f, vmax = 10.0f; const float vmin = 0.0f, vmax = 2.0f;
drawGraphBackground(gx,gy,gw,gh, vmin,vmax, 4, "ms"); drawGraphBackground(gx,gy,gw,gh, vmin,vmax, 4, "ms");
drawGraph(m_crowd.getRVOTimeGraph(), gx,gy,gw,gh, vmin,vmax, duRGBA(255,0,0,128)); drawGraph(m_crowd.getRVOTimeGraph(), gx,gy,gw,gh, vmin,vmax, duRGBA(255,0,0,128));

View File

@ -118,7 +118,7 @@ InputGeom::~InputGeom()
delete m_mesh; delete m_mesh;
} }
bool InputGeom::loadMesh(rcBuildContext* ctx, const char* filepath) bool InputGeom::loadMesh(rcContext* ctx, const char* filepath)
{ {
if (m_mesh) if (m_mesh)
{ {
@ -159,7 +159,7 @@ bool InputGeom::loadMesh(rcBuildContext* ctx, const char* filepath)
return true; return true;
} }
bool InputGeom::load(rcBuildContext* ctx, const char* filePath) bool InputGeom::load(rcContext* ctx, const char* filePath)
{ {
char* buf = 0; char* buf = 0;
FILE* fp = fopen(filePath, "rb"); FILE* fp = fopen(filePath, "rb");

View File

@ -6,6 +6,7 @@
#include "Recast.h" #include "Recast.h"
#include "RecastDebugDraw.h" #include "RecastDebugDraw.h"
#include "DetourDebugDraw.h" #include "DetourDebugDraw.h"
#include "PerfTimer.h"
#include "SDL.h" #include "SDL.h"
#include "SDL_opengl.h" #include "SDL_opengl.h"
@ -19,64 +20,23 @@ BuildContext::BuildContext() :
m_messageCount(0), m_messageCount(0),
m_textPoolSize(0) m_textPoolSize(0)
{ {
resetBuildTimes(); resetTimers();
} }
BuildContext::~BuildContext() BuildContext::~BuildContext()
{ {
} }
// Virtual functions for custom implementations.
#if defined(WIN32) void BuildContext::doResetLog()
// Win32
#include <windows.h>
rcTimeVal BuildContext::getTime()
{
__int64 count;
QueryPerformanceCounter((LARGE_INTEGER*)&count);
return count;
}
int BuildContext::getDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end)
{
static __int64 freq = 0;
if (freq == 0)
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
__int64 elapsed = end - start;
return (int)(elapsed*1000000 / freq);
}
#else
// Linux, BSD, OSX
#include <sys/time.h>
rcTimeVal BuildContext::getTime()
{
timeval now;
gettimeofday(&now, 0);
return (rcTimeVal)now.tv_sec*1000000L + (rcTimeVal)now.tv_usec;
}
int BuildContext::getDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end)
{
return (int)(end - start);
}
#endif
void BuildContext::resetLog()
{ {
m_messageCount = 0; m_messageCount = 0;
m_textPoolSize = 0; m_textPoolSize = 0;
} }
void BuildContext::log(const rcLogCategory category, const char* format, ...) void BuildContext::doLog(const rcLogCategory category, const char* msg, const int len)
{ {
if (!len) return;
if (m_messageCount >= MAX_MESSAGES) if (m_messageCount >= MAX_MESSAGES)
return; return;
char* dst = &m_textPool[m_textPoolSize]; char* dst = &m_textPool[m_textPoolSize];
@ -87,15 +47,39 @@ void BuildContext::log(const rcLogCategory category, const char* format, ...)
*dst = (char)category; *dst = (char)category;
n--; n--;
// Store message // Store message
va_list ap; const int count = rcMin(len+1, n);
va_start(ap, format); memcpy(dst+1, msg, count);
int ret = vsnprintf(dst+1, n-1, format, ap); dst[count+1] = '\0';
va_end(ap); m_textPoolSize += count+1;
if (ret > 0)
m_textPoolSize += ret+2;
m_messages[m_messageCount++] = dst; m_messages[m_messageCount++] = dst;
} }
void BuildContext::doResetTimers()
{
for (int i = 0; i < RC_MAX_TIMERS; ++i)
m_accTime[i] = -1;
}
void BuildContext::doStartTimer(const rcTimerLabel label)
{
m_startTime[label] = getPerfTime();
}
void BuildContext::doStopTimer(const rcTimerLabel label)
{
const TimeVal endTime = getPerfTime();
const int deltaTime = endTime - m_startTime[label];
if (m_accTime[label] == -1)
m_accTime[label] = deltaTime;
else
m_accTime[label] += deltaTime;
}
int BuildContext::doGetAccumulatedTime(const rcTimerLabel label) const
{
return m_accTime[label];
}
void BuildContext::dumpLog(const char* format, ...) void BuildContext::dumpLog(const char* format, ...)
{ {
// Print header. // Print header.
@ -150,70 +134,6 @@ const char* BuildContext::getLogText(const int i) const
{ {
return m_messages[i]+1; return m_messages[i]+1;
} }
void BuildContext::resetBuildTimes()
{
for (int i = 0; i < RC_MAX_TIMES; ++i)
m_buildTime[i] = -1;
}
void BuildContext::reportBuildTime(const rcBuildTimeLabel label, const int time)
{
const int idx = (int)label;
// The build times are initialized to negative to indicate no samples collected.
if (m_buildTime[idx] < 0)
m_buildTime[idx] = time;
else
m_buildTime[idx] += time;
}
int BuildContext::getBuildTime(const rcBuildTimeLabel label)
{
return m_buildTime[label];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(WIN32)
// Win32
#include <windows.h>
rcTimeVal getPerfTime()
{
__int64 count;
QueryPerformanceCounter((LARGE_INTEGER*)&count);
return count;
}
int getPerfDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end)
{
static __int64 freq = 0;
if (freq == 0)
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
__int64 elapsed = end - start;
return (int)(elapsed*1000000 / freq);
}
#else
// Linux, BSD, OSX
#include <sys/time.h>
rcTimeVal getPerfTime()
{
timeval now;
gettimeofday(&now, 0);
return (rcTimeVal)now.tv_sec*1000000L + (rcTimeVal)now.tv_usec;
}
int getPerfDeltaTimeUsec(const rcTimeVal start, const rcTimeVal end)
{
return (int)(end - start);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -138,7 +138,7 @@ Sample_Debug::Sample_Debug() :
if (m_cset) if (m_cset)
{ {
FileIO io; FileIO io;
if (io.openForRead("remove_vertex_issue_contour_cache.rc")) if (io.openForRead("PathSet_TMP_NA_PathingTestAReg1_1_2_CS.rc"))
{ {
duReadContourSet(*m_cset, &io); duReadContourSet(*m_cset, &io);
@ -158,14 +158,14 @@ Sample_Debug::Sample_Debug() :
} }
if (m_cset) /* if (m_cset)
{ {
m_pmesh = rcAllocPolyMesh(); m_pmesh = rcAllocPolyMesh();
if (m_pmesh) if (m_pmesh)
{ {
rcBuildPolyMesh(m_ctx, *m_cset, 6, *m_pmesh); rcBuildPolyMesh(m_ctx, *m_cset, 6, *m_pmesh);
} }
} }*/
} }
} }
@ -214,7 +214,7 @@ void Sample_Debug::handleRender()
if (m_cset) if (m_cset)
{ {
duDebugDrawRawContours(&dd, *m_cset, 0.25f); duDebugDrawRawContours(&dd, *m_cset, 0.25f);
// duDebugDrawContours(&dd, *m_cset); duDebugDrawContours(&dd, *m_cset);
} }
if (m_pmesh) if (m_pmesh)

View File

@ -389,10 +389,10 @@ bool Sample_SoloMeshSimple::handleBuild()
rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height); rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
// Reset build times gathering. // Reset build times gathering.
m_ctx->resetBuildTimes(); m_ctx->resetTimers();
// Start the build process. // Start the build process.
rcTimeVal totStartTime = m_ctx->getTime(); m_ctx->startTimer(RC_TIMER_TOTAL);
m_ctx->log(RC_LOG_PROGRESS, "Building navigation:"); m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height); m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
@ -653,13 +653,13 @@ bool Sample_SoloMeshSimple::handleBuild()
} }
} }
rcTimeVal totEndTime = m_ctx->getTime(); m_ctx->stopTimer(RC_TIMER_TOTAL);
// Show performance stats. // Show performance stats.
duLogBuildTimes(m_ctx, m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)); duLogBuildTimes(*m_ctx, m_ctx->getAccumulatedTime(RC_TIMER_TOTAL));
m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices %d polygons", m_pmesh->nverts, m_pmesh->npolys); m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices %d polygons", m_pmesh->nverts, m_pmesh->npolys);
m_totalBuildTimeMs = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f; m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
if (m_tool) if (m_tool)
m_tool->init(this); m_tool->init(this);

View File

@ -736,10 +736,10 @@ bool Sample_SoloMeshTiled::handleBuild()
rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height); rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);
// Reset build times gathering. // Reset build times gathering.
m_ctx->resetBuildTimes(); m_ctx->resetTimers();
// Start the build process. // Start the build process.
rcTimeVal totStartTime = m_ctx->getTime(); m_ctx->startTimer(RC_TIMER_TOTAL);
// Calculate the number of tiles in the output and initialize tiles. // Calculate the number of tiles in the output and initialize tiles.
m_tileSet = new TileSet; m_tileSet = new TileSet;
@ -785,7 +785,7 @@ bool Sample_SoloMeshTiled::handleBuild()
{ {
for (int x = 0; x < m_tileSet->width; ++x) for (int x = 0; x < m_tileSet->width; ++x)
{ {
rcTimeVal startTime = m_ctx->getTime(); m_ctx->startTimer(RC_TIMER_TEMP);
Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width]; Tile& tile = m_tileSet->tiles[x + y*m_tileSet->width];
tile.x = x; tile.x = x;
@ -920,8 +920,9 @@ bool Sample_SoloMeshTiled::handleBuild()
tile.cset = 0; tile.cset = 0;
} }
rcTimeVal endTime = m_ctx->getTime(); m_ctx->stopTimer(RC_TIMER_TOTAL);
tile.buildTime += m_ctx->getDeltaTimeUsec(startTime, endTime);
tile.buildTime += m_ctx->getAccumulatedTime(RC_TIMER_TOTAL);
// Some extra code to measure some per tile statistics, // Some extra code to measure some per tile statistics,
// such as build time and how many polygons there are per tile. // such as build time and how many polygons there are per tile.
@ -1092,12 +1093,12 @@ bool Sample_SoloMeshTiled::handleBuild()
} }
} }
rcTimeVal totEndTime = m_ctx->getTime(); m_ctx->stopTimer(RC_TIMER_TOTAL);
duLogBuildTimes(m_ctx, m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)); duLogBuildTimes(*m_ctx, m_ctx->getAccumulatedTime(RC_TIMER_TOTAL));
m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices %d polygons", m_pmesh->nverts, m_pmesh->npolys); m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices %d polygons", m_pmesh->nverts, m_pmesh->npolys);
m_totalBuildTimeMs = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f; m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
if (m_tool) if (m_tool)
m_tool->init(this); m_tool->init(this);

View File

@ -818,8 +818,8 @@ void Sample_TileMesh::buildAllTiles()
const float tcs = m_tileSize*m_cellSize; const float tcs = m_tileSize*m_cellSize;
// Start the build process. // Start the build process.
rcTimeVal totStartTime = m_ctx->getTime(); m_ctx->startTimer(RC_TIMER_TEMP);
for (int y = 0; y < th; ++y) for (int y = 0; y < th; ++y)
{ {
@ -847,9 +847,9 @@ void Sample_TileMesh::buildAllTiles()
} }
// Start the build process. // Start the build process.
rcTimeVal totEndTime = m_ctx->getTime(); m_ctx->startTimer(RC_TIMER_TEMP);
m_totalBuildTimeMs = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f; m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TEMP)/1000.0f;
} }
void Sample_TileMesh::removeAllTiles() void Sample_TileMesh::removeAllTiles()
@ -913,10 +913,10 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
m_cfg.bmax[2] += m_cfg.borderSize*m_cfg.cs; m_cfg.bmax[2] += m_cfg.borderSize*m_cfg.cs;
// Reset build times gathering. // Reset build times gathering.
m_ctx->resetBuildTimes(); m_ctx->resetTimers();
// Start the build process. // Start the build process.
rcTimeVal totStartTime = m_ctx->getTime(); m_ctx->startTimer(RC_TIMER_TOTAL);
m_ctx->log(RC_LOG_PROGRESS, "Building navigation:"); m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height); m_ctx->log(RC_LOG_PROGRESS, " - %d x %d cells", m_cfg.width, m_cfg.height);
@ -1176,13 +1176,13 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
} }
m_tileMemUsage = navDataSize/1024.0f; m_tileMemUsage = navDataSize/1024.0f;
rcTimeVal totEndTime = m_ctx->getTime(); m_ctx->stopTimer(RC_TIMER_TOTAL);
// Show performance stats. // Show performance stats.
duLogBuildTimes(m_ctx, m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)); duLogBuildTimes(*m_ctx, m_ctx->getAccumulatedTime(RC_TIMER_TOTAL));
m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices %d polygons", m_pmesh->nverts, m_pmesh->npolys); m_ctx->log(RC_LOG_PROGRESS, ">> Polymesh: %d vertices %d polygons", m_pmesh->nverts, m_pmesh->npolys);
m_tileBuildTime = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f; m_tileBuildTime = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
dataSize = navDataSize; dataSize = navDataSize;
return navData; return navData;

View File

@ -23,10 +23,11 @@
#include "TestCase.h" #include "TestCase.h"
#include "DetourNavMesh.h" #include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h" #include "DetourNavMeshQuery.h"
#include "DetourCommon.h"
#include "SDL.h" #include "SDL.h"
#include "SDL_opengl.h" #include "SDL_opengl.h"
#include "imgui.h" #include "imgui.h"
#include "Recast.h" #include "PerfTimer.h"
#ifdef WIN32 #ifdef WIN32
#define snprintf _snprintf #define snprintf _snprintf
@ -157,7 +158,7 @@ void TestCase::resetTimes()
} }
} }
void TestCase::doTests(rcBuildContext* ctx, dtNavMesh* navmesh, dtNavMeshQuery* navquery) void TestCase::doTests(dtNavMesh* navmesh, dtNavMeshQuery* navquery)
{ {
if (!navmesh || !navquery) if (!navmesh || !navquery)
return; return;
@ -183,34 +184,34 @@ void TestCase::doTests(rcBuildContext* ctx, dtNavMesh* navmesh, dtNavMeshQuery*
filter.setExcludeFlags((unsigned short)iter->excludeFlags); filter.setExcludeFlags((unsigned short)iter->excludeFlags);
// Find start points // Find start points
rcTimeVal findNearestPolyStart = ctx->getTime(); TimeVal findNearestPolyStart = getPerfTime();
dtPolyRef startRef = navquery->findNearestPoly(iter->spos, polyPickExt, &filter, 0); dtPolyRef startRef = navquery->findNearestPoly(iter->spos, polyPickExt, &filter, 0);
dtPolyRef endRef = navquery->findNearestPoly(iter->epos, polyPickExt, &filter, 0); dtPolyRef endRef = navquery->findNearestPoly(iter->epos, polyPickExt, &filter, 0);
rcTimeVal findNearestPolyEnd = ctx->getTime(); TimeVal findNearestPolyEnd = getPerfTime();
iter->findNearestPolyTime += ctx->getDeltaTimeUsec(findNearestPolyStart, findNearestPolyEnd); iter->findNearestPolyTime += getPerfDeltaTimeUsec(findNearestPolyStart, findNearestPolyEnd);
if (!startRef || ! endRef) if (!startRef || ! endRef)
continue; continue;
// Find path // Find path
rcTimeVal findPathStart = ctx->getTime(); TimeVal findPathStart = getPerfTime();
iter->npolys = navquery->findPath(startRef, endRef, iter->spos, iter->epos, &filter, polys, MAX_POLYS); iter->npolys = navquery->findPath(startRef, endRef, iter->spos, iter->epos, &filter, polys, MAX_POLYS);
rcTimeVal findPathEnd = ctx->getTime(); TimeVal findPathEnd = getPerfTime();
iter->findPathTime += ctx->getDeltaTimeUsec(findPathStart, findPathEnd); iter->findPathTime += getPerfDeltaTimeUsec(findPathStart, findPathEnd);
// Find straight path // Find straight path
if (iter->npolys) if (iter->npolys)
{ {
rcTimeVal findStraightPathStart = ctx->getTime(); TimeVal findStraightPathStart = getPerfTime();
iter->nstraight = navquery->findStraightPath(iter->spos, iter->epos, polys, iter->npolys, iter->nstraight = navquery->findStraightPath(iter->spos, iter->epos, polys, iter->npolys,
straight, 0, 0, MAX_POLYS); straight, 0, 0, MAX_POLYS);
rcTimeVal findStraightPathEnd = ctx->getTime(); TimeVal findStraightPathEnd = getPerfTime();
iter->findStraightPathTime += ctx->getDeltaTimeUsec(findStraightPathStart, findStraightPathEnd); iter->findStraightPathTime += getPerfDeltaTimeUsec(findStraightPathStart, findStraightPathEnd);
} }
// Copy results // Copy results
@ -231,7 +232,7 @@ void TestCase::doTests(rcBuildContext* ctx, dtNavMesh* navmesh, dtNavMeshQuery*
int n = 0; int n = 0;
for (Test* iter = m_tests; iter; iter = iter->next) for (Test* iter = m_tests; iter; iter = iter->next)
{ {
rcTimeVal total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime; const int total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime;
printf(" - Path %02d: %.4f ms\n", n, (float)total/1000.0f); printf(" - Path %02d: %.4f ms\n", n, (float)total/1000.0f);
printf(" - poly: %.4f ms\n", (float)iter->findNearestPolyTime/1000.0f); printf(" - poly: %.4f ms\n", (float)iter->findNearestPolyTime/1000.0f);
printf(" - path: %.4f ms\n", (float)iter->findPathTime/1000.0f); printf(" - path: %.4f ms\n", (float)iter->findPathTime/1000.0f);
@ -247,8 +248,8 @@ void TestCase::handleRender()
for (Test* iter = m_tests; iter; iter = iter->next) for (Test* iter = m_tests; iter; iter = iter->next)
{ {
float dir[3]; float dir[3];
rcVsub(dir, iter->epos, iter->spos); dtVsub(dir, iter->epos, iter->spos);
rcVnormalize(dir); dtVnormalize(dir);
glColor4ub(128,25,0,192); glColor4ub(128,25,0,192);
glVertex3f(iter->spos[0],iter->spos[1]-0.3f,iter->spos[2]); glVertex3f(iter->spos[0],iter->spos[1]-0.3f,iter->spos[2]);
glVertex3f(iter->spos[0],iter->spos[1]+0.3f,iter->spos[2]); glVertex3f(iter->spos[0],iter->spos[1]+0.3f,iter->spos[2]);
@ -286,20 +287,20 @@ bool TestCase::handleRenderOverlay(double* proj, double* model, int* view)
float pt[3], dir[3]; float pt[3], dir[3];
if (iter->nstraight) if (iter->nstraight)
{ {
rcVcopy(pt, &iter->straight[3]); dtVcopy(pt, &iter->straight[3]);
if (rcVdist(pt, iter->spos) > LABEL_DIST) if (dtVdist(pt, iter->spos) > LABEL_DIST)
{ {
rcVsub(dir, pt, iter->spos); dtVsub(dir, pt, iter->spos);
rcVnormalize(dir); dtVnormalize(dir);
rcVmad(pt, iter->spos, dir, LABEL_DIST); dtVmad(pt, iter->spos, dir, LABEL_DIST);
} }
pt[1]+=0.5f; pt[1]+=0.5f;
} }
else else
{ {
rcVsub(dir, iter->epos, iter->spos); dtVsub(dir, iter->epos, iter->spos);
rcVnormalize(dir); dtVnormalize(dir);
rcVmad(pt, iter->spos, dir, LABEL_DIST); dtVmad(pt, iter->spos, dir, LABEL_DIST);
pt[1]+=0.5f; pt[1]+=0.5f;
} }
@ -322,7 +323,7 @@ bool TestCase::handleRenderOverlay(double* proj, double* model, int* view)
n = 0; n = 0;
for (Test* iter = m_tests; iter; iter = iter->next) for (Test* iter = m_tests; iter; iter = iter->next)
{ {
rcTimeVal total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime; const int total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime;
snprintf(subtext, 64, "%.4f ms", (float)total/1000.0f); snprintf(subtext, 64, "%.4f ms", (float)total/1000.0f);
snprintf(text, 64, "Path %d", n); snprintf(text, 64, "Path %d", n);

View File

@ -852,7 +852,7 @@ int main(int /*argc*/, char** /*argv*/)
// Do the tests. // Do the tests.
if (sample) if (sample)
test->doTests(&ctx, sample->getNavMesh(), sample->getNavMeshQuery()); test->doTests(sample->getNavMesh(), sample->getNavMeshQuery());
} }
} }