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

View File

@ -19,14 +19,6 @@
#ifndef RECAST_H
#define RECAST_H
#ifdef __GNUC__
#include <stdint.h>
typedef int64_t rcTimeVal;
#else
typedef __int64 rcTimeVal;
#endif
enum rcLogCategory
{
RC_LOG_PROGRESS = 1,
@ -34,55 +26,74 @@ enum rcLogCategory
RC_LOG_ERROR,
};
enum rcBuildTimeLabel
enum rcTimerLabel
{
RC_TIME_RASTERIZE_TRIANGLES,
RC_TIME_BUILD_COMPACTHEIGHFIELD,
RC_TIME_BUILD_CONTOURS,
RC_TIME_BUILD_CONTOURS_TRACE,
RC_TIME_BUILD_CONTOURS_SIMPLIFY,
RC_TIME_FILTER_BORDER,
RC_TIME_FILTER_WALKABLE,
RC_TIME_MEDIAN_AREA,
RC_TIME_FILTER_LOW_OBSTACLES,
RC_TIME_BUILD_POLYMESH,
RC_TIME_MERGE_POLYMESH,
RC_TIME_ERODE_AREA,
RC_TIME_MARK_BOX_AREA,
RC_TIME_MARK_CONVEXPOLY_AREA,
RC_TIME_BUILD_DISTANCEFIELD,
RC_TIME_BUILD_DISTANCEFIELD_DIST,
RC_TIME_BUILD_DISTANCEFIELD_BLUR,
RC_TIME_BUILD_REGIONS,
RC_TIME_BUILD_REGIONS_WATERSHED,
RC_TIME_BUILD_REGIONS_EXPAND,
RC_TIME_BUILD_REGIONS_FLOOD,
RC_TIME_BUILD_REGIONS_FILTER,
RC_TIME_BUILD_POLYMESHDETAIL,
RC_TIME_MERGE_POLYMESHDETAIL,
RC_MAX_TIMES
RC_TIMER_TOTAL,
RC_TIMER_TEMP,
RC_TIMER_RASTERIZE_TRIANGLES,
RC_TIMER_BUILD_COMPACTHEIGHFIELD,
RC_TIMER_BUILD_CONTOURS,
RC_TIMER_BUILD_CONTOURS_TRACE,
RC_TIMER_BUILD_CONTOURS_SIMPLIFY,
RC_TIMER_FILTER_BORDER,
RC_TIMER_FILTER_WALKABLE,
RC_TIMER_MEDIAN_AREA,
RC_TIMER_FILTER_LOW_OBSTACLES,
RC_TIMER_BUILD_POLYMESH,
RC_TIMER_MERGE_POLYMESH,
RC_TIMER_ERODE_AREA,
RC_TIMER_MARK_BOX_AREA,
RC_TIMER_MARK_CONVEXPOLY_AREA,
RC_TIMER_BUILD_DISTANCEFIELD,
RC_TIMER_BUILD_DISTANCEFIELD_DIST,
RC_TIMER_BUILD_DISTANCEFIELD_BLUR,
RC_TIMER_BUILD_REGIONS,
RC_TIMER_BUILD_REGIONS_WATERSHED,
RC_TIMER_BUILD_REGIONS_EXPAND,
RC_TIMER_BUILD_REGIONS_FLOOD,
RC_TIMER_BUILD_REGIONS_FILTER,
RC_TIMER_BUILD_POLYMESHDETAIL,
RC_TIMER_MERGE_POLYMESHDETAIL,
RC_MAX_TIMERS
};
// Build context provides several optional utilities needed for the build process,
// such as timing, logging, and build time collecting.
struct rcBuildContext
class rcContext
{
// Get current time in platform specific units.
virtual rcTimeVal getTime() { return 0; }
// Returns time passed from 'start' to 'end' in microseconds.
virtual int getDeltaTimeUsec(const rcTimeVal /*start*/, const rcTimeVal /*end*/) { return 0; }
public:
inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {}
virtual ~rcContext() {}
// Enables or disables logging.
inline void enableLog(bool state) { m_logEnabled = state; }
// Resets log.
virtual void resetLog() {}
inline void resetLog() { if (m_logEnabled) doResetLog(); }
// Logs a message.
virtual void log(const rcLogCategory /*category*/, const char* /*format*/, ...) {}
void log(const rcLogCategory category, const char* format, ...);
// Resets build time collecting.
virtual void resetBuildTimes() {}
// Reports build time of specified label for accumulation.
virtual void reportBuildTime(const rcBuildTimeLabel /*label*/, const int /*time*/) {}
// Returns accumulated build time for specified label, or -1 if no time was reported.
virtual int getBuildTime(const rcBuildTimeLabel /*label*/) { return -1; }
// Enables or disables timer.
inline void enableTimer(bool state) { m_timerEnabled = state; }
// Resets all timers.
inline void resetTimers() { if (m_timerEnabled) doResetTimers(); }
// Starts timer, used for performance timing.
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.
};
rcHeightfield* rcAllocHeightfield();
void rcFreeHeightField(rcHeightfield* hf);
struct rcCompactCell
{
unsigned int index : 24; // Index to first span in column.
@ -160,9 +175,6 @@ struct rcCompactSpan
// Compact static heightfield.
struct rcCompactHeightfield
{
rcCompactHeightfield();
~rcCompactHeightfield();
int width, height; // Width and height of the heighfield.
int spanCount; // Number of spans in the heightfield.
int walkableHeight, walkableClimb; // Agent properties.
@ -176,6 +188,10 @@ struct rcCompactHeightfield
unsigned char* areas; // Pointer to per span area ID.
};
rcCompactHeightfield* rcAllocCompactHeightfield();
void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
struct rcContour
{
int* verts; // Vertex coordinates, each vertex contains 4 components.
@ -194,6 +210,10 @@ struct rcContourSet
float cs, ch; // Cell size and height.
};
rcContourSet* rcAllocContourSet();
void rcFreeContourSet(rcContourSet* cset);
// Polymesh store a connected mesh of polygons.
// The polygons are store in an array where each polygons takes
// 'nvp*2' elements. The first 'nvp' elements are indices to vertices
@ -220,6 +240,10 @@ struct rcPolyMesh
float cs, ch; // Cell size and height.
};
rcPolyMesh* rcAllocPolyMesh();
void rcFreePolyMesh(rcPolyMesh* pmesh);
// Detail mesh generated from a rcPolyMesh.
// Each submesh represents a polygon in the polymesh and they are stored in
// excatly same order. Each submesh is described as 4 values:
@ -240,19 +264,6 @@ struct rcPolyMeshDetail
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();
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
// cs - (in) grid cell size
// 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,
float cs, float ch);
@ -445,7 +456,7 @@ bool rcCreateHeightfield(rcBuildContext* ctx, rcHeightfield& hf, int width, int
// tris - (in) array of triangle vertex indices
// nt - (in) triangle count
// 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);
// 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
// nt - (in) triangle count
// 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);
// Adds span to heighfield.
@ -470,7 +481,7 @@ void rcClearUnwalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAn
// smin,smax - (in) spans min/max height
// flags - (in) span flags (zero or WALKABLE)
// 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 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.
// solid - (in) heighfield where the triangle is rasterized
// 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 int flagMergeThr = 1);
@ -493,7 +504,7 @@ void rcRasterizeTriangle(rcBuildContext* ctx, const float* v0, const float* v1,
// nt - (in) triangle count
// solid - (in) heighfield where the triangles are rasterized
// 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,
rcHeightfield& solid, const int flagMergeThr = 1);
@ -506,7 +517,7 @@ void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv,
// nt - (in) triangle count
// solid - (in) heighfield where the triangles are rasterized
// 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,
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.
// nt - (in) triangle count
// 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);
// 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
// solid - (in/out) heightfield describing the solid space
// 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 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
// walkableClimb - (in) maximum height between grid cells the agent can climb
// 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
// 'walkableHeight' clearane above them.
// Params:
// walkableHeight - (in) minimum height where the agent can still walk
// 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.
// Params:
// hf - (in) heightfield to be compacted
// Returns number of spans.
int rcGetHeightFieldSpanCount(rcBuildContext* ctx, rcHeightfield& hf);
int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf);
// Builds compact representation of the heightfield.
// Params:
@ -558,7 +569,7 @@ int rcGetHeightFieldSpanCount(rcBuildContext* ctx, rcHeightfield& hf);
// hf - (in) heightfield to be compacted
// chf - (out) compact heightfield representing the open space.
// 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);
// Erodes walkable area.
@ -566,20 +577,20 @@ bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, co
// radius - (in) radius of erosion (max 255).
// chf - (in/out) compact heightfield to erode.
// 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.
// Params:
// chf - (in/out) compact heightfield to erode.
// 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.
// Params:
// bmin/bmax - (in) bounds of the axis aligned box.
// areaId - (in) area ID 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);
// 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.
// areaId - (in) area ID 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,
rcCompactHeightfield& chf);
@ -597,7 +608,7 @@ void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nve
// Params:
// chf - (in/out) compact heightfield representing the open space.
// 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.
// 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.
// maxMergeRegionSize - (in) the largest allowed regions size which can be merged.
// 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);
// 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.
// maxMergeRegionSize - (in) the largest allowed regions size which can be merged.
// 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);
// Builds simplified contours from the regions outlines.
@ -639,7 +650,7 @@ bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf,
// cset - (out) Resulting contour set.
// flags - (in) build flags, see rcBuildContoursFlags.
// 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,
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.
// mesh - (out) poly mesh.
// 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.
// 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.
// pmdtl - (out) detail mesh.
// 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,
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

View File

@ -22,6 +22,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "Recast.h"
#include "RecastAlloc.h"
#include "RecastAssert.h"
@ -31,6 +32,25 @@ float rcSqrt(float 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* 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);
}
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,
float cs, float ch)
{
@ -172,7 +192,7 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
rcVnormalize(norm);
}
void rcMarkWalkableTriangles(rcBuildContext* /*ctx*/, const float walkableSlopeAngle,
void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
const float* verts, int /*nv*/,
const int* tris, int nt,
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 int* tris, int nt,
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.
// rcAssert(ctx);
@ -238,12 +258,12 @@ int rcGetHeightFieldSpanCount(rcBuildContext* /*ctx*/, rcHeightfield& hf)
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)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHFIELD);
const int w = hf.width;
const int h = hf.height;
@ -371,9 +391,7 @@ bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, co
tooHighNeighbour, MAX_LAYERS);
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_BUILD_COMPACTHEIGHFIELD, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHFIELD);
return true;
}

View File

@ -27,14 +27,14 @@
#include "RecastAssert.h"
bool rcErodeWalkableArea(rcBuildContext* ctx, int radius, rcCompactHeightfield& chf)
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
{
rcAssert(ctx);
const int w = chf.width;
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);
if (!dist)
@ -196,9 +196,7 @@ bool rcErodeWalkableArea(rcBuildContext* ctx, int radius, rcCompactHeightfield&
rcFree(dist);
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_ERODE_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_ERODE_AREA);
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);
const int w = chf.width;
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);
if (!areas)
@ -285,19 +283,17 @@ bool rcMedianFilterWalkableArea(rcBuildContext* ctx, rcCompactHeightfield& chf)
rcFree(areas);
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_MEDIAN_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_MEDIAN_AREA);
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)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_MARK_BOX_AREA);
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
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->reportBuildTime(RC_TIME_MARK_BOX_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_MARK_BOX_AREA);
}
@ -354,13 +348,13 @@ static int pointInPoly(int nvert, const float* verts, const float* p)
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,
rcCompactHeightfield& chf)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
float bmin[3], bmax[3];
rcVcopy(bmin, verts);
@ -419,7 +413,5 @@ void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nve
}
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_MARK_CONVEXPOLY_AREA, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
}

View File

@ -592,7 +592,7 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
return true;
}
bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
const float maxError, const int maxEdgeLen,
rcContourSet& cset, const int buildFlags)
{
@ -601,7 +601,7 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
const int w = chf.width;
const int h = chf.height;
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_CONTOURS);
rcVcopy(cset.bmin, chf.bmin);
rcVcopy(cset.bmax, chf.bmax);
@ -621,8 +621,7 @@ bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf,
return false;
}
rcTimeVal traceStartTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
// Mark boundaries.
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 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->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));
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS);
return true;
}

View File

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

View File

@ -483,7 +483,7 @@ static void pushBack(int v, int* arr, int& 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;
@ -585,7 +585,7 @@ static bool canRemoveVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigne
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;
@ -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);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_POLYMESH);
rcVcopy(mesh.bmin, cset.bmin);
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);
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_BUILD_POLYMESH, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_BUILD_POLYMESH);
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);
if (!nmeshes || !meshes)
return true;
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_MERGE_POLYMESH);
mesh.nvp = meshes[0]->nvp;
mesh.cs = meshes[0]->cs;
@ -1300,10 +1298,7 @@ bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmesh
return false;
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_MERGE_POLYMESH, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_MERGE_POLYMESH);
return true;
}

View File

@ -255,7 +255,7 @@ static int findEdge(const int* edges, int nedges, int s, int t)
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)
{
@ -317,7 +317,7 @@ static bool overlapEdges(const float* pts, const int* edges, int nedges, int s1,
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;
@ -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,
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 rcCompactHeightfield& chf, const rcHeightPatch& hp,
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,
rcPolyMeshDetail& dmesh)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL);
if (mesh.nverts == 0 || mesh.npolys == 0)
return true;
@ -1126,19 +1126,17 @@ bool rcBuildPolyMeshDetail(rcBuildContext* ctx, const rcPolyMesh& mesh, const rc
}
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_BUILD_POLYMESHDETAIL, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL);
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);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_MERGE_POLYMESHDETAIL);
int maxVerts = 0;
int maxTris = 0;
int maxMeshes = 0;
@ -1206,9 +1204,7 @@ bool rcMergePolyMeshDetails(rcBuildContext* ctx, rcPolyMeshDetail** meshes, cons
}
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_MERGE_POLYMESHDETAIL, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_MERGE_POLYMESHDETAIL);
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 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 int flagMergeThr)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs;
const float ich = 1.0f/solid.ch;
rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr);
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
}
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,
rcHeightfield& solid, const int flagMergeThr)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs;
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);
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
}
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,
rcHeightfield& solid, const int flagMergeThr)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs;
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);
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
}
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)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES);
const float ics = 1.0f/solid.cs;
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);
}
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
}

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,
rcCompactHeightfield& chf,
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);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD);
if (chf.dist)
{
@ -914,14 +914,14 @@ bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf)
unsigned short maxDist = 0;
rcTimeVal distStartTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST);
calculateDistanceField(chf, src, 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
if (boxBlur(chf, 1, src, dst) != src)
@ -930,16 +930,10 @@ bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf)
// Store distance.
chf.dist = src;
rcTimeVal blurEndTime = ctx->getTime();
ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR);
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;
}
@ -973,12 +967,12 @@ struct rcSweepSpan
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)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_REGIONS);
const int w = chf.width;
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.
chf.maxRegions = id;
if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg))
return false;
rcTimeVal filterEndTime = ctx->getTime();
ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER);
// Store the result out.
for (int i = 0; i < chf.spanCount; ++i)
chf.spans[i].reg = srcReg[i];
rcTimeVal endTime = ctx->getTime();
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS, ctx->getDeltaTimeUsec(startTime, endTime));
ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_FILTER, ctx->getDeltaTimeUsec(filterStartTime, filterEndTime));
ctx->stopTimer(RC_TIMER_BUILD_REGIONS);
return true;
}
bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionSize, const int mergeRegionSize)
{
rcAssert(ctx);
rcTimeVal startTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_REGIONS);
const int w = chf.width;
const int h = chf.height;
@ -1139,7 +1130,7 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
return false;
}
rcTimeVal regStartTime = ctx->getTime();
ctx->startTimer(RC_TIMER_BUILD_REGIONS_WATERSHED);
rcIntArray stack(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(0, w, 0, borderSize, 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)
{
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.
if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg)
@ -1183,9 +1171,9 @@ bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf,
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.
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);
}
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.
chf.maxRegions = regionId;
if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg))
return false;
rcTimeVal filterEndTime = ctx->getTime();
ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER);
// Write the result out.
for (int i = 0; i < chf.spanCount; ++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;
}

File diff suppressed because it is too large Load Diff

View File

@ -290,7 +290,7 @@
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 388}, {264, 660}}</string>
<string>{{0, 196}, {264, 660}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@ -337,7 +337,7 @@
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>6BA687751222F02E00730711</string>
<string>6BD402B112243CEA00995864</string>
<key>history</key>
<array>
<string>6BBB4AA5115B4F3400CF791D</string>
@ -348,74 +348,79 @@
<string>6BF5F2E511748884000502A6</string>
<string>6BF5F2E611748884000502A6</string>
<string>6BF5F2E711748884000502A6</string>
<string>6BF5F5041176F5F8000502A6</string>
<string>6B4214D911803923006C347B</string>
<string>6B98462E11E6141900FA177B</string>
<string>6B98473011E737D800FA177B</string>
<string>6BF9B12C11EB8CF20043574C</string>
<string>6BAF3CB012116AD9008CFCDF</string>
<string>6BAF3CB112116AD9008CFCDF</string>
<string>6BAF3CB412116AD9008CFCDF</string>
<string>6BAF3E781212869F008CFCDF</string>
<string>6BAF404F12140B4E008CFCDF</string>
<string>6BAF405112140B4E008CFCDF</string>
<string>6BAF40F412197F3D008CFCDF</string>
<string>6BAF427E121ADD46008CFCDF</string>
<string>6BAF4280121ADD46008CFCDF</string>
<string>6BAF4321121AF998008CFCDF</string>
<string>6BAF43FB121C241D008CFCDF</string>
<string>6BAF4421121C25E3008CFCDF</string>
<string>6BAF4422121C25E3008CFCDF</string>
<string>6BAF4446121C40AC008CFCDF</string>
<string>6BAF446E121C4895008CFCDF</string>
<string>6BAF44D9121C4DFC008CFCDF</string>
<string>6BAF44DE121C54D4008CFCDF</string>
<string>6BAF4524121D1723008CFCDF</string>
<string>6BAF4525121D1723008CFCDF</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>6BAF4604121D7388008CFCDF</string>
<string>6BAF4605121D7388008CFCDF</string>
<string>6BAF4637121D74D3008CFCDF</string>
<string>6BAF46A2121D8B41008CFCDF</string>
<string>6BAF46D3121D8FF1008CFCDF</string>
<string>6BAF4739121D9FBE008CFCDF</string>
<string>6BAF473A121D9FBE008CFCDF</string>
<string>6BAF4747121D9FED008CFCDF</string>
<string>6BAF475A121DA31D008CFCDF</string>
<string>6BAF475B121DA31D008CFCDF</string>
<string>6BAF475C121DA31D008CFCDF</string>
<string>6B1C8D82121E80950048697F</string>
<string>6B1C8DA2121E813D0048697F</string>
<string>6B1C8DB3121E8D970048697F</string>
<string>6B1C8DC0121E8F610048697F</string>
<string>6B1C8DC5121E902F0048697F</string>
<string>6B1C8E08121EB4FF0048697F</string>
<string>6B1C8E0A121EB4FF0048697F</string>
<string>6B1C8E24121EB6D30048697F</string>
<string>6B1C8E27121EB6D30048697F</string>
<string>6B1C8E6A1221BC910048697F</string>
<string>6BA687441222EADA00730711</string>
<string>6BA687451222EADA00730711</string>
<string>6BA687461222EADA00730711</string>
<string>6BA687471222EADA00730711</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>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>
<key>prevStack</key>
<array>
@ -443,7 +448,6 @@
<string>6BF5F2ED11748884000502A6</string>
<string>6BF5F2EE11748884000502A6</string>
<string>6BF5F33911759C3C000502A6</string>
<string>6B98465411E6F9B400FA177B</string>
<string>6B98466011E6F9B400FA177B</string>
<string>6B98471011E734A100FA177B</string>
<string>6B98471211E734A100FA177B</string>
@ -457,7 +461,6 @@
<string>6BAF3A3B1210235F008CFCDF</string>
<string>6BAF3ABC121038F9008CFCDF</string>
<string>6BAF3B0612112E63008CFCDF</string>
<string>6BAF3B1512112F65008CFCDF</string>
<string>6BAF3DAA1211882E008CFCDF</string>
<string>6BAF3E631211B713008CFCDF</string>
<string>6BBB4AE2115B4F3400CF791D</string>
@ -467,18 +470,14 @@
<string>6BAF4243121AD679008CFCDF</string>
<string>6BAF4289121ADD46008CFCDF</string>
<string>6BAF4396121C1F3D008CFCDF</string>
<string>6BAF43A1121C1F3D008CFCDF</string>
<string>6BAF43BE121C1F3D008CFCDF</string>
<string>6BAF43D1121C2164008CFCDF</string>
<string>6BAF43D2121C2164008CFCDF</string>
<string>6BAF4453121C40AC008CFCDF</string>
<string>6BAF4456121C40AC008CFCDF</string>
<string>6B98477411E7406900FA177B</string>
<string>6BAF3861120A8A8E008CFCDF</string>
<string>6BAF410212197F3D008CFCDF</string>
<string>6BAF44FA121C5713008CFCDF</string>
<string>6BAF45E9121D7277008CFCDF</string>
<string>6BAF447E121C4895008CFCDF</string>
<string>6BAF473D121D9FBE008CFCDF</string>
<string>6BAF4749121D9FED008CFCDF</string>
<string>6BAF4762121DA31D008CFCDF</string>
@ -486,30 +485,89 @@
<string>6BAF4768121DA31D008CFCDF</string>
<string>6B1C8DDB121EA3470048697F</string>
<string>6B1C8E2A121EB6D30048697F</string>
<string>6B1C8E2B121EB6D30048697F</string>
<string>6B1C8E2D121EB6D30048697F</string>
<string>6B1C8E58121EBEBF0048697F</string>
<string>6BA6874E1222EADA00730711</string>
<string>6BA6874F1222EADA00730711</string>
<string>6BA687501222EADA00730711</string>
<string>6BA687511222EADA00730711</string>
<string>6BA687521222EADA00730711</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>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>
</dict>
<key>SplitCount</key>
@ -523,18 +581,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {994, 381}}</string>
<string>{{0, 0}, {994, 493}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1280 719 0 0 1280 778 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
<string>381pt</string>
<string>493pt</string>
</dict>
<dict>
<key>Proportion</key>
<string>292pt</string>
<string>180pt</string>
<key>Tabs</key>
<array>
<dict>
@ -548,7 +606,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {994, 304}}</string>
<string>{{10, 27}, {994, 81}}</string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@ -564,7 +622,9 @@
<key>GeometryConfiguration</key>
<dict>
<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>
<key>Module</key>
<string>PBXProjectFindModule</string>
@ -602,9 +662,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {994, 265}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1280 719 0 0 1280 778 </string>
<string>{{10, 27}, {994, 83}}</string>
</dict>
<key>Module</key>
<string>PBXBuildResultsModule</string>
@ -632,11 +690,11 @@
</array>
<key>TableOfContents</key>
<array>
<string>6BA687641222EAE200730711</string>
<string>6BD401FC1224235500995864</string>
<string>1CA23ED40692098700951B8B</string>
<string>6BA687651222EAE200730711</string>
<string>6BD401FD1224235500995864</string>
<string>6B8632A30F78115100E2684A</string>
<string>6BA687661222EAE200730711</string>
<string>6BD401FE1224235500995864</string>
<string>1CA23EDF0692099D00951B8B</string>
<string>1CA23EE00692099D00951B8B</string>
<string>1CA23EE10692099D00951B8B</string>
@ -687,12 +745,12 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {1280, 411}}</string>
<string>{{0, 0}, {1280, 328}}</string>
</dict>
<key>Module</key>
<string>PBXDebugCLIModule</string>
<key>Proportion</key>
<string>411pt</string>
<string>328pt</string>
</dict>
<dict>
<key>ContentConfiguration</key>
@ -711,8 +769,8 @@
<string>yes</string>
<key>sizes</key>
<array>
<string>{{0, 0}, {577, 109}}</string>
<string>{{577, 0}, {703, 109}}</string>
<string>{{0, 0}, {577, 144}}</string>
<string>{{577, 0}, {703, 144}}</string>
</array>
</dict>
<key>VerticalSplitView</key>
@ -727,8 +785,8 @@
<string>yes</string>
<key>sizes</key>
<array>
<string>{{0, 0}, {1280, 109}}</string>
<string>{{0, 109}, {1280, 153}}</string>
<string>{{0, 0}, {1280, 144}}</string>
<string>{{0, 144}, {1280, 201}}</string>
</array>
</dict>
</dict>
@ -748,7 +806,7 @@
<key>DebugSTDIOWindowFrame</key>
<string>{{200, 200}, {500, 300}}</string>
<key>Frame</key>
<string>{{0, 416}, {1280, 262}}</string>
<string>{{0, 333}, {1280, 345}}</string>
<key>PBXDebugSessionStackFrameViewKey</key>
<dict>
<key>DebugVariablesTableConfiguration</key>
@ -761,13 +819,13 @@
<real>410</real>
</array>
<key>Frame</key>
<string>{{577, 0}, {703, 109}}</string>
<string>{{577, 0}, {703, 144}}</string>
</dict>
</dict>
<key>Module</key>
<string>PBXDebugSessionModule</string>
<key>Proportion</key>
<string>262pt</string>
<string>345pt</string>
</dict>
</array>
<key>Name</key>
@ -785,14 +843,14 @@
</array>
<key>TableOfContents</key>
<array>
<string>6BA687671222EAE200730711</string>
<string>6BD402781224387200995864</string>
<string>1CCC7628064C1048000F2A68</string>
<string>1CCC7629064C1048000F2A68</string>
<string>6BA687681222EAE200730711</string>
<string>6BA687691222EAE200730711</string>
<string>6BA6876A1222EAE200730711</string>
<string>6BA6876B1222EAE200730711</string>
<string>6B8632A30F78115100E2684A</string>
<string>6BD402791224387200995864</string>
<string>6BD4027A1224387200995864</string>
<string>6BD4027B1224387200995864</string>
<string>6BD4027C1224387200995864</string>
<string>6BD4027D1224387200995864</string>
</array>
<key>ToolbarConfigUserDefaultsMinorVersion</key>
<string>2</string>

View File

@ -46,6 +46,7 @@
6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */; };
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.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 */; };
6BF5F2401174763B000502A6 /* SlideShow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5F23F1174763B000502A6 /* SlideShow.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; };
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; };
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; };
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; };
@ -188,6 +191,8 @@
6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */,
6BF7C13E11119520002B3F46 /* TestCase.h */,
6BF7C13F1111953A002B3F46 /* TestCase.cpp */,
6BD401FF1224278800995864 /* PerfTimer.h */,
6BD402001224279400995864 /* PerfTimer.cpp */,
);
name = Classes;
sourceTree = "<group>";
@ -441,6 +446,7 @@
6BAF3C591211663A008CFCDF /* CrowdTool.cpp in Sources */,
6BAF40DB12196A3D008CFCDF /* DetourNavMeshQuery.cpp in Sources */,
6BAF4442121C3D26008CFCDF /* SampleInterfaces.cpp in Sources */,
6BD402011224279400995864 /* PerfTimer.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -39,6 +39,8 @@ struct ObstacleBody
float dp[3], np[3]; // Use for side selection during sampling.
bool touch;
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
{
static const int MAX_SAMPLES = 512;
@ -211,6 +241,8 @@ class CrowdTool : public SampleTool
float m_targetPos[3];
bool m_targetPosSet;
Formation m_form;
bool m_expandDebugDraw;
bool m_showLabels;
bool m_showCorners;

View File

@ -55,9 +55,9 @@ public:
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);
// Method to return static mesh data.

View File

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

View File

@ -22,13 +22,15 @@
#include "DebugDraw.h"
#include "Recast.h"
#include "RecastDump.h"
#include "PerfTimer.h"
// These are example implementations of various interfaces used in Recast and Detour.
// 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;
const char* m_messages[MAX_MESSAGES];
@ -39,17 +41,8 @@ class BuildContext : public rcBuildContext
public:
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.
void dumpLog(const char* format, ...);
// Returns number of log messages.
@ -57,20 +50,16 @@ public:
// Returns log message text.
const char* getLogText(const int i) const;
// Resets build time collecting.
virtual void resetBuildTimes();
// Reports build time of specified label for accumulation.
virtual void reportBuildTime(const rcBuildTimeLabel label, const int time);
// Returns accumulated build time for specified label, or -1 if no time was reported.
virtual int getBuildTime(const rcBuildTimeLabel label);
protected:
// Virtual functions 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;
};
// 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.
class DebugDrawGL : public duDebugDraw
{

View File

@ -20,7 +20,6 @@
#define TESTCASE_H
#include "DetourNavMesh.h"
#include "Recast.h"
class TestCase
{
@ -49,9 +48,9 @@ class TestCase
dtPolyRef* polys;
int npolys;
rcTimeVal findNearestPolyTime;
rcTimeVal findPathTime;
rcTimeVal findStraightPathTime;
int findNearestPolyTime;
int findPathTime;
int findStraightPathTime;
Test* next;
};
@ -71,7 +70,7 @@ public:
inline const char* getSampleName() const { return m_sampleName; }
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();
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;
dtVcopy(b->p, pos);
dtVcopy(b->vel, vel);
dtVcopy(b->dvel, dvel);
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;
dtVcopy(b->p, pos);
dtVset(b->vel, 0,0,0);
dtVset(b->dvel, 0,0,0);
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;
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->dvel, 0,0,0);
b->rad = 0;
b->idx = -1;
}
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);
}
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() :
@ -571,12 +625,48 @@ static void calcSmoothSteerDirection(const float* pos, const float* corners, con
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)
{
if (!navquery)
return;
rcTimeVal startTime = getPerfTime();
TimeVal startTime = getPerfTime();
const float ext[3] = {2,4,2};
dtQueryFilter filter;
@ -716,7 +806,7 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
if (!ag->ncorners)
{
// No corner to steer to,
// No corner to steer to, stop.
dtVset(ag->dvel, 0,0,0);
}
else
@ -760,7 +850,7 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
}
// Velocity planning.
rcTimeVal rvoStartTime = getPerfTime();
TimeVal rvoStartTime = getPerfTime();
static const int MAX_BODIES = 32;
ObstacleBody bodies[MAX_BODIES];
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)
{
setDynCircleBody(&bodies[nbodies], nei->pos, nei->radius, nei->vel, nei->dvel);
nbodies++;
ObstacleBody* body = insertBody(dist, bodies, 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.
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;
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);
sampleRVO(&agent, ag->maxspeed, bodies, nbodies, &ag->rvo, 0.4f, ag->nvel);
// Normalize samples for debug draw
normalizeSamples(&ag->rvo);
sampleRVOAdaptive(&agent, ag->maxspeed, bodies, nbodies, &ag->rvo, 0.4f, ag->nvel);
}
else
{
dtVcopy(ag->nvel, ag->dvel);
}
}
rcTimeVal rvoEndTime = getPerfTime();
m_rvoTime.addSample(getPerfDeltaTimeUsec(rvoStartTime, rvoEndTime) / 1000.0f);
TimeVal rvoEndTime = getPerfTime();
// Integrate and update perceived velocity.
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_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() :
m_sample(0),
@ -989,6 +1183,7 @@ CrowdTool::CrowdTool() :
m_run(true),
m_mode(TOOLMODE_CREATE)
{
memset(&m_form, 0, sizeof(Formation));
}
CrowdTool::~CrowdTool()
@ -1105,9 +1300,77 @@ void CrowdTool::handleClick(const float* s, const float* p, bool shift)
else
{
// 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)
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)
@ -1306,6 +1569,91 @@ void CrowdTool::handleRender()
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 float vmin = 0.0f, vmax = 10.0f;
const float vmin = 0.0f, vmax = 2.0f;
drawGraphBackground(gx,gy,gw,gh, vmin,vmax, 4, "ms");
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;
}
bool InputGeom::loadMesh(rcBuildContext* ctx, const char* filepath)
bool InputGeom::loadMesh(rcContext* ctx, const char* filepath)
{
if (m_mesh)
{
@ -159,7 +159,7 @@ bool InputGeom::loadMesh(rcBuildContext* ctx, const char* filepath)
return true;
}
bool InputGeom::load(rcBuildContext* ctx, const char* filePath)
bool InputGeom::load(rcContext* ctx, const char* filePath)
{
char* buf = 0;
FILE* fp = fopen(filePath, "rb");

View File

@ -6,6 +6,7 @@
#include "Recast.h"
#include "RecastDebugDraw.h"
#include "DetourDebugDraw.h"
#include "PerfTimer.h"
#include "SDL.h"
#include "SDL_opengl.h"
@ -19,64 +20,23 @@ BuildContext::BuildContext() :
m_messageCount(0),
m_textPoolSize(0)
{
resetBuildTimes();
resetTimers();
}
BuildContext::~BuildContext()
{
}
#if defined(WIN32)
// 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()
// Virtual functions for custom implementations.
void BuildContext::doResetLog()
{
m_messageCount = 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)
return;
char* dst = &m_textPool[m_textPoolSize];
@ -87,15 +47,39 @@ void BuildContext::log(const rcLogCategory category, const char* format, ...)
*dst = (char)category;
n--;
// Store message
va_list ap;
va_start(ap, format);
int ret = vsnprintf(dst+1, n-1, format, ap);
va_end(ap);
if (ret > 0)
m_textPoolSize += ret+2;
const int count = rcMin(len+1, n);
memcpy(dst+1, msg, count);
dst[count+1] = '\0';
m_textPoolSize += count+1;
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, ...)
{
// Print header.
@ -150,70 +134,6 @@ const char* BuildContext::getLogText(const int i) const
{
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)
{
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);
@ -158,14 +158,14 @@ Sample_Debug::Sample_Debug() :
}
if (m_cset)
/* if (m_cset)
{
m_pmesh = rcAllocPolyMesh();
if (m_pmesh)
{
rcBuildPolyMesh(m_ctx, *m_cset, 6, *m_pmesh);
}
}
}*/
}
}
@ -214,7 +214,7 @@ void Sample_Debug::handleRender()
if (m_cset)
{
duDebugDrawRawContours(&dd, *m_cset, 0.25f);
// duDebugDrawContours(&dd, *m_cset);
duDebugDrawContours(&dd, *m_cset);
}
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);
// Reset build times gathering.
m_ctx->resetBuildTimes();
m_ctx->resetTimers();
// 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, " - %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.
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_totalBuildTimeMs = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f;
m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
if (m_tool)
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);
// Reset build times gathering.
m_ctx->resetBuildTimes();
m_ctx->resetTimers();
// 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.
m_tileSet = new TileSet;
@ -785,7 +785,7 @@ bool Sample_SoloMeshTiled::handleBuild()
{
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.x = x;
@ -920,8 +920,9 @@ bool Sample_SoloMeshTiled::handleBuild()
tile.cset = 0;
}
rcTimeVal endTime = m_ctx->getTime();
tile.buildTime += m_ctx->getDeltaTimeUsec(startTime, endTime);
m_ctx->stopTimer(RC_TIMER_TOTAL);
tile.buildTime += m_ctx->getAccumulatedTime(RC_TIMER_TOTAL);
// Some extra code to measure some per tile statistics,
// 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_totalBuildTimeMs = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f;
m_totalBuildTimeMs = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
if (m_tool)
m_tool->init(this);

View File

@ -818,8 +818,8 @@ void Sample_TileMesh::buildAllTiles()
const float tcs = m_tileSize*m_cellSize;
// Start the build process.
rcTimeVal totStartTime = m_ctx->getTime();
// Start the build process.
m_ctx->startTimer(RC_TIMER_TEMP);
for (int y = 0; y < th; ++y)
{
@ -847,9 +847,9 @@ void Sample_TileMesh::buildAllTiles()
}
// 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()
@ -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;
// Reset build times gathering.
m_ctx->resetBuildTimes();
m_ctx->resetTimers();
// Start the build process.
rcTimeVal totStartTime = m_ctx->getTime();
// Start the build process.
m_ctx->startTimer(RC_TIMER_TOTAL);
m_ctx->log(RC_LOG_PROGRESS, "Building navigation:");
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;
rcTimeVal totEndTime = m_ctx->getTime();
m_ctx->stopTimer(RC_TIMER_TOTAL);
// 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_tileBuildTime = m_ctx->getDeltaTimeUsec(totStartTime, totEndTime)/1000.0f;
m_tileBuildTime = m_ctx->getAccumulatedTime(RC_TIMER_TOTAL)/1000.0f;
dataSize = navDataSize;
return navData;

View File

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

View File

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