diff --git a/Recast/Include/Recast.h b/Recast/Include/Recast.h index 2208269..1af8cd5 100644 --- a/Recast/Include/Recast.h +++ b/Recast/Include/Recast.h @@ -19,6 +19,72 @@ #ifndef RECAST_H #define RECAST_H +#ifdef __GNUC__ +#include +typedef int64_t rcTimeVal; +#else +typedef __int64 rcTimeVal; +#endif + +enum rcLogCategory +{ + RC_LOG_PROGRESS = 1, + RC_LOG_WARNING, + RC_LOG_ERROR, +}; + +enum rcBuilTimeLabel +{ + 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 +}; + +// Build context provides several optional utilities needed for the build process, +// such as timing, logging, and build time collecting. +struct rcBuildContext +{ + // 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; } + + // Resets log. + virtual void resetLog() {} + // Logs a message. + virtual 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 rcBuilTimeLabel /*label*/, const int /*time*/) {} + // Returns accumulated build time for specified label, or -1 if no time was reported. + virtual int getBuildTime(const rcBuilTimeLabel /*label*/) { return -1; } +}; + + // The units of the parameters are specified in parenthesis as follows: // (vx) voxels, (wu) world units struct rcConfig @@ -190,12 +256,6 @@ rcPolyMeshDetail* rcAllocPolyMeshDetail(); void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh); -/*enum rcSpanFlags -{ - RC_WALKABLE = 0x01, - RC_LEDGE = 0x02, -};*/ - // If heightfield region ID has the following bit set, the region is on border area // and excluded from many calculations. static const unsigned short RC_BORDER_REG = 0x8000; @@ -348,11 +408,6 @@ inline bool rcVequal(const float* p0, const float* p1) return d < thr; } -// Alloc helpers for different Recast objects. -rcHeightfield* rcAllocHeightfield(); -void rcFreeHeightField(rcHeightfield* hf); - - // Calculated bounding box of array of vertices. // Params: // verts - (in) array of vertices @@ -376,7 +431,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(rcHeightfield& hf, int width, int height, +bool rcCreateHeightfield(rcBuildContext* ctx, rcHeightfield& hf, int width, int height, const float* bmin, const float* bmax, float cs, float ch); @@ -389,10 +444,8 @@ bool rcCreateHeightfield(rcHeightfield& hf, int width, int height, // tris - (in) array of triangle vertex indices // nt - (in) triangle count // areas - (out) array of triangle area types -void rcMarkWalkableTriangles(const float walkableSlopeAngle, - const float* verts, int nv, - const int* tris, int nt, - unsigned char* areas); +void rcMarkWalkableTriangles(rcBuildContext* 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 // the maximun walkable slope angle. @@ -403,10 +456,8 @@ void rcMarkWalkableTriangles(const float walkableSlopeAngle, // tris - (in) array of triangle vertex indices // nt - (in) triangle count // areas - (out) array of triangle are types -void rcClearUnwalkableTriangles(const float walkableSlopeAngle, - const float* verts, int nv, - const int* tris, int nt, - unsigned char* areas); +void rcClearUnwalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, + const int* tris, int nt, unsigned char* areas); // Adds span to heighfield. // The span addition can set to favor flags. If the span is merged to @@ -418,7 +469,7 @@ void rcClearUnwalkableTriangles(const float walkableSlopeAngle, // smin,smax - (in) spans min/max height // flags - (in) span flags (zero or WALKABLE) // flagMergeThr - (in) merge threshold. -void rcAddSpan(rcHeightfield& solid, const int x, const int y, +void rcAddSpan(rcBuildContext* ctx, rcHeightfield& solid, const int x, const int y, const unsigned short smin, const unsigned short smax, const unsigned short area, const int flagMergeThr); @@ -428,7 +479,7 @@ void rcAddSpan(rcHeightfield& solid, const int x, const int y, // 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(const float* v0, const float* v1, const float* v2, +void rcRasterizeTriangle(rcBuildContext* ctx, const float* v0, const float* v1, const float* v2, const unsigned char area, rcHeightfield& solid, const int flagMergeThr = 1); @@ -441,7 +492,7 @@ void rcRasterizeTriangle(const float* v0, const float* v1, const float* v2, // 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(const float* verts, const int nv, +void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv, const int* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr = 1); @@ -454,7 +505,7 @@ void rcRasterizeTriangles(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(const float* verts, const int nv, +void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int nv, const unsigned short* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr = 1); @@ -464,7 +515,7 @@ void rcRasterizeTriangles(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(const float* verts, const unsigned char* areas, const int nt, +void rcRasterizeTriangles(rcBuildContext* 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 @@ -474,7 +525,7 @@ void rcRasterizeTriangles(const float* verts, const unsigned char* areas, const // 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(const int walkableClimb, rcHeightfield& solid); +void rcFilterLowHangingWalkableObstacles(rcBuildContext* 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 @@ -483,23 +534,20 @@ void rcFilterLowHangingWalkableObstacles(const int walkableClimb, rcHeightfield& // 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(const int walkableHeight, - const int walkableClimb, - rcHeightfield& solid); +void rcFilterLedgeSpans(rcBuildContext* 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(int walkableHeight, - rcHeightfield& solid); +void rcFilterWalkableLowHeightSpans(rcBuildContext* 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(rcHeightfield& hf); +int rcGetHeightFieldSpanCount(rcBuildContext* ctx, rcHeightfield& hf); // Builds compact representation of the heightfield. // Params: @@ -509,7 +557,7 @@ int rcGetHeightFieldSpanCount(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(const int walkableHeight, const int walkableClimb, +bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& hf, rcCompactHeightfield& chf); // Erodes walkable area. @@ -517,20 +565,20 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb // radius - (in) radius of erosion (max 255). // chf - (in/out) compact heightfield to erode. // Returns false if operation ran out of memory. -bool rcErodeWalkableArea(int radius, rcCompactHeightfield& chf); +bool rcErodeWalkableArea(rcBuildContext* 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(rcCompactHeightfield& chf); +bool rcMedianFilterWalkableArea(rcBuildContext* 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(const float* bmin, const float* bmax, unsigned char areaId, +void rcMarkBoxArea(rcBuildContext* 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. @@ -540,7 +588,7 @@ void rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId, // 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(const float* verts, const int nverts, +void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nverts, const float hmin, const float hmax, unsigned char areaId, rcCompactHeightfield& chf); @@ -548,7 +596,7 @@ void rcMarkConvexPolyArea(const float* verts, const int nverts, // Params: // chf - (in/out) compact heightfield representing the open space. // Returns false if operation ran out of memory. -bool rcBuildDistanceField(rcCompactHeightfield& chf); +bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf); // Divides the walkable heighfied into simple regions using watershed partitioning. // Each region has only one contour and no overlaps. @@ -563,7 +611,7 @@ bool rcBuildDistanceField(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(rcCompactHeightfield& chf, +bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionSize, const int mergeRegionSize); // Divides the walkable heighfied into simple regions using simple monotone partitioning. @@ -579,7 +627,7 @@ bool rcBuildRegions(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(rcCompactHeightfield& chf, +bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionSize, const int mergeRegionSize); // Builds simplified contours from the regions outlines. @@ -590,7 +638,7 @@ bool rcBuildRegionsMonotone(rcCompactHeightfield& chf, // cset - (out) Resulting contour set. // flags - (in) build flags, see rcBuildContoursFlags. // Returns false if operation ran out of memory. -bool rcBuildContours(rcCompactHeightfield& chf, +bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf, const float maxError, const int maxEdgeLen, rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES); @@ -600,9 +648,9 @@ bool rcBuildContours(rcCompactHeightfield& chf, // nvp - (in) maximum number of vertices per polygon. // mesh - (out) poly mesh. // Returns false if operation ran out of memory. -bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh); +bool rcBuildPolyMesh(rcBuildContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh); -bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); +bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); // Builds detail triangle mesh for each polygon in the poly mesh. // Params: @@ -612,11 +660,11 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) // 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(const rcPolyMesh& mesh, const rcCompactHeightfield& chf, +bool rcBuildPolyMeshDetail(rcBuildContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& dmesh); -bool rcMergePolyMeshDetails(rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); +bool rcMergePolyMeshDetails(rcBuildContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); #endif // RECAST_H diff --git a/Recast/Include/RecastTimer.h b/Recast/Include/RecastAssert.h similarity index 78% rename from Recast/Include/RecastTimer.h rename to Recast/Include/RecastAssert.h index 909cbfa..fc4d1d3 100644 --- a/Recast/Include/RecastTimer.h +++ b/Recast/Include/RecastAssert.h @@ -15,17 +15,15 @@ // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. // -#ifndef RECAST_TIMER_H -#define RECAST_TIMER_H -#ifdef __GNUC__ -#include -typedef int64_t rcTimeVal; +#ifndef RECASTASSERT_H +#define RECASTASSERT_H + +#ifdef NDEBUG +# define rcAssert(x) #else -typedef __int64 rcTimeVal; +# include +# define rcAssert assert #endif -rcTimeVal rcGetPerformanceTimer(); -int rcGetDeltaTimeUsec(rcTimeVal start, rcTimeVal end); - -#endif // RECAST_TIMER_H +#endif // RECASTASSERT_H diff --git a/Recast/Include/RecastLog.h b/Recast/Include/RecastLog.h deleted file mode 100644 index 7d97aa2..0000000 --- a/Recast/Include/RecastLog.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef RECAST_LOG_H -#define RECAST_LOG_H - -enum rcLogCategory -{ - RC_LOG_PROGRESS = 1, - RC_LOG_WARNING, - RC_LOG_ERROR, -}; - -class rcLog -{ -public: - rcLog(); - ~rcLog(); - - void log(rcLogCategory category, const char* format, ...); - inline void clear() { m_messageCount = 0; m_textPoolSize = 0; } - inline int getMessageCount() const { return m_messageCount; } - inline char getMessageType(int i) const { return *m_messages[i]; } - inline const char* getMessageText(int i) const { return m_messages[i]+1; } - -private: - static const int MAX_MESSAGES = 1000; - const char* m_messages[MAX_MESSAGES]; - int m_messageCount; - static const int TEXT_POOL_SIZE = 8000; - char m_textPool[TEXT_POOL_SIZE]; - int m_textPoolSize; -}; - -struct rcBuildTimes -{ - int rasterizeTriangles; - int buildCompact; - int buildContours; - int buildContoursTrace; - int buildContoursSimplify; - int filterBorder; - int filterWalkable; - int filterMarkReachable; - int filterMedian; - int buildPolymesh; - int erodeArea; - int buildDistanceField; - int buildDistanceFieldDist; - int buildDistanceFieldBlur; - int buildRegions; - int buildRegionsReg; - int buildRegionsExp; - int buildRegionsFlood; - int buildRegionsFilter; - int buildDetailMesh; - int mergePolyMesh; - int mergePolyMeshDetail; -}; - -void rcSetLog(rcLog* log); -rcLog* rcGetLog(); - -void rcSetBuildTimes(rcBuildTimes* btimes); -rcBuildTimes* rcGetBuildTimes(); - -#endif // RECAST_LOG_H diff --git a/Recast/Source/Recast.cpp b/Recast/Source/Recast.cpp index 440aa0a..7df231f 100644 --- a/Recast/Source/Recast.cpp +++ b/Recast/Source/Recast.cpp @@ -23,9 +23,8 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" #include "RecastAlloc.h" +#include "RecastAssert.h" float rcSqrt(float x) { @@ -144,10 +143,12 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* *h = (int)((bmax[2] - bmin[2])/cs+0.5f); } -bool rcCreateHeightfield(rcHeightfield& hf, int width, int height, +bool rcCreateHeightfield(rcBuildContext* ctx, rcHeightfield& hf, int width, int height, const float* bmin, const float* bmax, float cs, float ch) { + rcAssert(ctx); + hf.width = width; hf.height = height; rcVcopy(hf.bmin, bmin); @@ -170,11 +171,13 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo rcVnormalize(norm); } -void rcMarkWalkableTriangles(const float walkableSlopeAngle, +void rcMarkWalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAngle, const float* verts, int /*nv*/, const int* tris, int nt, unsigned char* areas) { + rcAssert(ctx); + const float walkableThr = cosf(walkableSlopeAngle/180.0f*(float)M_PI); float norm[3]; @@ -189,11 +192,13 @@ void rcMarkWalkableTriangles(const float walkableSlopeAngle, } } -void rcClearUnwalkableTriangles(const float walkableSlopeAngle, +void rcClearUnwalkableTriangles(rcBuildContext* ctx, const float walkableSlopeAngle, const float* verts, int /*nv*/, const int* tris, int nt, unsigned char* areas) { + rcAssert(ctx); + const float walkableThr = cosf(walkableSlopeAngle/180.0f*(float)M_PI); float norm[3]; @@ -208,8 +213,10 @@ void rcClearUnwalkableTriangles(const float walkableSlopeAngle, } } -int rcGetHeightFieldSpanCount(rcHeightfield& hf) +int rcGetHeightFieldSpanCount(rcBuildContext* ctx, rcHeightfield& hf) { + rcAssert(ctx); + const int w = hf.width; const int h = hf.height; int spanCount = 0; @@ -227,14 +234,16 @@ int rcGetHeightFieldSpanCount(rcHeightfield& hf) return spanCount; } -bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb, +bool rcBuildCompactHeightfield(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& hf, rcCompactHeightfield& chf) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const int w = hf.width; const int h = hf.height; - const int spanCount = rcGetHeightFieldSpanCount(hf); + const int spanCount = rcGetHeightFieldSpanCount(ctx, hf); // Fill in header. chf.width = w; @@ -251,24 +260,21 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM); if (!chf.cells) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h); + ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h); return false; } memset(chf.cells, 0, sizeof(rcCompactCell)*w*h); chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM); if (!chf.spans) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount); + ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount); return false; } memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount); chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM); if (!chf.areas) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount); + ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount); return false; } memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount); @@ -357,14 +363,13 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb if (tooHighNeighbour > MAX_LAYERS) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heighfield has too many layers %d (max: %d)", tooHighNeighbour, MAX_LAYERS); + ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heighfield has too many layers %d (max: %d)", + tooHighNeighbour, MAX_LAYERS); } - - rcTimeVal endTime = rcGetPerformanceTimer(); - - if (rcGetBuildTimes()) - rcGetBuildTimes()->buildCompact += rcGetDeltaTimeUsec(startTime, endTime); + + rcTimeVal endTime = ctx->getTime(); + + ctx->reportBuildTime(RC_TIME_BUILD_COMPACTHEIGHFIELD, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } diff --git a/Recast/Source/RecastArea.cpp b/Recast/Source/RecastArea.cpp index 5842da0..07180c8 100644 --- a/Recast/Source/RecastArea.cpp +++ b/Recast/Source/RecastArea.cpp @@ -23,21 +23,25 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" #include "RecastAlloc.h" +#include "RecastAssert.h" -bool rcErodeWalkableArea(int radius, rcCompactHeightfield& chf) +bool rcErodeWalkableArea(rcBuildContext* ctx, int radius, rcCompactHeightfield& chf) { + rcAssert(ctx); + const int w = chf.width; const int h = chf.height; - rcTimeVal startTime = rcGetPerformanceTimer(); + rcTimeVal startTime = ctx->getTime(); unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!dist) + { + ctx->log(RC_LOG_ERROR, "erodeWalkableArea: Out of memory 'dist' (%d).", chf.spanCount); return false; + } // Init distance. memset(dist, 0xff, sizeof(unsigned char)*chf.spanCount); @@ -192,12 +196,9 @@ bool rcErodeWalkableArea(int radius, rcCompactHeightfield& chf) rcFree(dist); - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - { - rcGetBuildTimes()->erodeArea += rcGetDeltaTimeUsec(startTime, endTime); - } + ctx->reportBuildTime(RC_TIME_ERODE_AREA, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } @@ -215,16 +216,21 @@ static void insertSort(unsigned char* a, const int n) } -bool rcMedianFilterWalkableArea(rcCompactHeightfield& chf) +bool rcMedianFilterWalkableArea(rcBuildContext* ctx, rcCompactHeightfield& chf) { + rcAssert(ctx); + const int w = chf.width; const int h = chf.height; - rcTimeVal startTime = rcGetPerformanceTimer(); + rcTimeVal startTime = ctx->getTime(); unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!areas) + { + ctx->log(RC_LOG_ERROR, "medianFilterWalkableArea: Out of memory 'areas' (%d).", chf.spanCount); return false; + } // Init distance. memset(areas, 0xff, sizeof(unsigned char)*chf.spanCount); @@ -279,19 +285,20 @@ bool rcMedianFilterWalkableArea(rcCompactHeightfield& chf) rcFree(areas); - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - { - rcGetBuildTimes()->filterMedian += rcGetDeltaTimeUsec(startTime, endTime); - } + ctx->reportBuildTime(RC_TIME_MEDIAN_AREA, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } -void rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId, +void rcMarkBoxArea(rcBuildContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, rcCompactHeightfield& chf) { + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); + int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs); @@ -325,6 +332,11 @@ void rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId, } } } + + rcTimeVal endTime = ctx->getTime(); + + ctx->reportBuildTime(RC_TIME_MARK_BOX_AREA, ctx->getDeltaTimeUsec(startTime, endTime)); + } @@ -342,10 +354,14 @@ static int pointInPoly(int nvert, const float* verts, const float* p) return c; } -void rcMarkConvexPolyArea(const float* verts, const int nverts, +void rcMarkConvexPolyArea(rcBuildContext* ctx, const float* verts, const int nverts, const float hmin, const float hmax, unsigned char areaId, rcCompactHeightfield& chf) { + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); + float bmin[3], bmax[3]; rcVcopy(bmin, verts); rcVcopy(bmax, verts); @@ -402,5 +418,8 @@ void rcMarkConvexPolyArea(const float* verts, const int nverts, } } } + + rcTimeVal endTime = ctx->getTime(); + ctx->reportBuildTime(RC_TIME_MARK_CONVEXPOLY_AREA, ctx->getDeltaTimeUsec(startTime, endTime)); } diff --git a/Recast/Source/RecastContour.cpp b/Recast/Source/RecastContour.cpp index 6a58f48..043c535 100644 --- a/Recast/Source/RecastContour.cpp +++ b/Recast/Source/RecastContour.cpp @@ -21,9 +21,8 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" #include "RecastAlloc.h" +#include "RecastAssert.h" static int getCornerHeight(int x, int y, int i, int dir, @@ -593,14 +592,16 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib) return true; } -bool rcBuildContours(rcCompactHeightfield& chf, +bool rcBuildContours(rcBuildContext* ctx, rcCompactHeightfield& chf, const float maxError, const int maxEdgeLen, rcContourSet& cset, const int buildFlags) { + rcAssert(ctx); + const int w = chf.width; const int h = chf.height; - rcTimeVal startTime = rcGetPerformanceTimer(); + rcTimeVal startTime = ctx->getTime(); rcVcopy(cset.bmin, chf.bmin); rcVcopy(cset.bmax, chf.bmax); @@ -616,12 +617,11 @@ bool rcBuildContours(rcCompactHeightfield& chf, rcScopedDelete flags = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!flags) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount); + ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount); return false; } - rcTimeVal traceStartTime = rcGetPerformanceTimer(); + rcTimeVal traceStartTime = ctx->getTime(); // Mark boundaries. @@ -657,9 +657,9 @@ bool rcBuildContours(rcCompactHeightfield& chf, } } - rcTimeVal traceEndTime = rcGetPerformanceTimer(); + rcTimeVal traceEndTime = ctx->getTime(); - rcTimeVal simplifyStartTime = rcGetPerformanceTimer(); + rcTimeVal simplifyStartTime = ctx->getTime(); rcIntArray verts(256); rcIntArray simplified(64); @@ -708,8 +708,7 @@ bool rcBuildContours(rcCompactHeightfield& chf, rcFree(cset.conts); cset.conts = newConts; - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours); + ctx->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours); } rcContour* cont = &cset.conts[cset.nconts++]; @@ -718,8 +717,7 @@ bool rcBuildContours(rcCompactHeightfield& chf, cont->verts = (int*)rcAlloc(sizeof(int)*cont->nverts*4, RC_ALLOC_PERM); if (!cont->verts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'verts' (%d).", cont->nverts); + ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'verts' (%d).", cont->nverts); return false; } memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4); @@ -728,8 +726,7 @@ bool rcBuildContours(rcCompactHeightfield& chf, cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM); if (!cont->rverts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'rverts' (%d).", cont->nrverts); + ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'rverts' (%d).", cont->nrverts); return false; } memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4); @@ -778,8 +775,7 @@ bool rcBuildContours(rcCompactHeightfield& chf, } if (mergeIdx == -1) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i); + ctx->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i); } else { @@ -789,37 +785,25 @@ bool rcBuildContours(rcCompactHeightfield& chf, getClosestIndices(mcont.verts, mcont.nverts, cont.verts, cont.nverts, ia, ib); if (ia == -1 || ib == -1) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "rcBuildContours: Failed to find merge points for %d and %d.", i, mergeIdx); + ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to find merge points for %d and %d.", i, mergeIdx); continue; } if (!mergeContours(mcont, cont, ia, ib)) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx); + ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx); continue; } } } } - rcTimeVal simplifyEndTime = rcGetPerformanceTimer(); + rcTimeVal simplifyEndTime = ctx->getTime(); - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); -// if (rcGetLog()) -// { -// rcGetLog()->log(RC_LOG_PROGRESS, "Create contours: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); -// rcGetLog()->log(RC_LOG_PROGRESS, " - boundary: %.3f ms", rcGetDeltaTimeUsec(boundaryStartTime, boundaryEndTime)/1000.0f); -// rcGetLog()->log(RC_LOG_PROGRESS, " - contour: %.3f ms", rcGetDeltaTimeUsec(contourStartTime, contourEndTime)/1000.0f); -// } - - if (rcGetBuildTimes()) - { - rcGetBuildTimes()->buildContours += rcGetDeltaTimeUsec(startTime, endTime); - rcGetBuildTimes()->buildContoursTrace += rcGetDeltaTimeUsec(traceStartTime, traceEndTime); - rcGetBuildTimes()->buildContoursSimplify += rcGetDeltaTimeUsec(simplifyStartTime, simplifyEndTime); - } + ctx->reportBuildTime(RC_TIME_BUILD_CONTOURS, ctx->getDeltaTimeUsec(startTime, endTime)); + ctx->reportBuildTime(RC_TIME_BUILD_CONTOURS_TRACE, ctx->getDeltaTimeUsec(traceStartTime, traceEndTime)); + ctx->reportBuildTime(RC_TIME_BUILD_CONTOURS_SIMPLIFY, ctx->getDeltaTimeUsec(simplifyStartTime, simplifyEndTime)); return true; } diff --git a/Recast/Source/RecastFilter.cpp b/Recast/Source/RecastFilter.cpp index 63ec2cc..f843ecf 100644 --- a/Recast/Source/RecastFilter.cpp +++ b/Recast/Source/RecastFilter.cpp @@ -20,13 +20,15 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" +#include "RecastAssert.h" -// TODO: Missuses ledge flag, must be called before rcFilterLedgeSpans! -void rcFilterLowHangingWalkableObstacles(const int walkableClimb, rcHeightfield& solid) +void rcFilterLowHangingWalkableObstacles(rcBuildContext* ctx, const int walkableClimb, rcHeightfield& solid) { + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); + const int w = solid.width; const int h = solid.height; @@ -51,39 +53,20 @@ void rcFilterLowHangingWalkableObstacles(const int walkableClimb, rcHeightfield& // past multiple non-walkable objects. previousWalkable = walkable; } - -/* rcSpan* ps = 0; - for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next) - { - const bool walkable = s->flags != RC_NULL_AREA; - const bool previousWalkable = ps && ps->flags != RC_NULL_AREA; - // If current span is not walkable, but there is walkable - // span just below it, mark the span above it walkable too. - // Missuse the edge flag so that walkable flag cannot propagate - // past multiple non-walkable objects. - if (!walkable && previousWalkable) - { - if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb) - s->flags |= 1; - } - } - // Transfer "fake ledges" to walkables. - for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next) - { - if (s->flags & RC_LEDGE) - s->flags |= RC_WALKABLE; - s->flags &= ~RC_LEDGE; - }*/ - } } + + rcTimeVal endTime = ctx->getTime(); + + ctx->reportBuildTime(RC_TIME_FILTER_LOW_OBSTACLES, ctx->getDeltaTimeUsec(startTime, endTime)); } -void rcFilterLedgeSpans(const int walkableHeight, - const int walkableClimb, +void rcFilterLedgeSpans(rcBuildContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& solid) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const int w = solid.width; const int h = solid.height; @@ -165,17 +148,16 @@ void rcFilterLedgeSpans(const int walkableHeight, } } - rcTimeVal endTime = rcGetPerformanceTimer(); -// if (rcGetLog()) -// rcGetLog()->log(RC_LOG_PROGRESS, "Filter border: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); - if (rcGetBuildTimes()) - rcGetBuildTimes()->filterBorder += rcGetDeltaTimeUsec(startTime, endTime); + rcTimeVal endTime = ctx->getTime(); + + ctx->reportBuildTime(RC_TIME_FILTER_BORDER, ctx->getDeltaTimeUsec(startTime, endTime)); } -void rcFilterWalkableLowHeightSpans(int walkableHeight, - rcHeightfield& solid) +void rcFilterWalkableLowHeightSpans(rcBuildContext* ctx, int walkableHeight, rcHeightfield& solid) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const int w = solid.width; const int h = solid.height; @@ -197,10 +179,7 @@ void rcFilterWalkableLowHeightSpans(int walkableHeight, } } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); -// if (rcGetLog()) -// rcGetLog()->log(RC_LOG_PROGRESS, "Filter walkable: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); - if (rcGetBuildTimes()) - rcGetBuildTimes()->filterWalkable += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_FILTER_WALKABLE, ctx->getDeltaTimeUsec(startTime, endTime)); } diff --git a/Recast/Source/RecastLog.cpp b/Recast/Source/RecastLog.cpp deleted file mode 100644 index ac01195..0000000 --- a/Recast/Source/RecastLog.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#include "RecastLog.h" -#include -#include - -static rcLog* g_log = 0; -static rcBuildTimes* g_btimes = 0; - -rcLog::rcLog() : - m_messageCount(0), - m_textPoolSize(0) -{ -} - -rcLog::~rcLog() -{ - if (g_log == this) - g_log = 0; -} - -void rcLog::log(rcLogCategory category, const char* format, ...) -{ - if (m_messageCount >= MAX_MESSAGES) - return; - char* dst = &m_textPool[m_textPoolSize]; - int n = TEXT_POOL_SIZE - m_textPoolSize; - if (n < 2) - return; - // Store category - *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; - m_messages[m_messageCount++] = dst; -} - -void rcSetLog(rcLog* log) -{ - g_log = log; -} - -rcLog* rcGetLog() -{ - return g_log; -} - -void rcSetBuildTimes(rcBuildTimes* btimes) -{ - g_btimes = btimes; -} - -rcBuildTimes* rcGetBuildTimes() -{ - return g_btimes; -} diff --git a/Recast/Source/RecastMesh.cpp b/Recast/Source/RecastMesh.cpp index 28af472..0504bd2 100644 --- a/Recast/Source/RecastMesh.cpp +++ b/Recast/Source/RecastMesh.cpp @@ -21,9 +21,8 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" #include "RecastAlloc.h" +#include "RecastAssert.h" struct rcEdge { @@ -287,7 +286,7 @@ static bool diagonal(int i, int j, int n, const int* verts, int* indices) return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices); } -int triangulate(int n, const int* verts, int* indices, int* tris) +static int triangulate(int n, const int* verts, int* indices, int* tris) { int ntris = 0; int* dst = tris; @@ -328,8 +327,6 @@ int triangulate(int n, const int* verts, int* indices, int* tris) if (mini == -1) { // Should not happen. - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "triangulate: Failed to triangulate polygon."); /* printf("mini == -1 ntris=%d n=%d\n", ntris, n); for (int i = 0; i < n; i++) { @@ -486,7 +483,7 @@ static void pushBack(int v, int* arr, int& an) an++; } -static bool canRemoveVertex(rcPolyMesh& mesh, const unsigned short rem) +static bool canRemoveVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigned short rem) { const int nvp = mesh.nvp; @@ -529,8 +526,7 @@ static bool canRemoveVertex(rcPolyMesh& mesh, const unsigned short rem) rcScopedDelete edges = (int*)rcAlloc(sizeof(int)*maxEdges*3, RC_ALLOC_TEMP); if (!edges) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "canRemoveVertex: Out of memory 'edges' (%d).", maxEdges*3); + ctx->log(RC_LOG_WARNING, "canRemoveVertex: Out of memory 'edges' (%d).", maxEdges*3); return false; } @@ -589,7 +585,7 @@ static bool canRemoveVertex(rcPolyMesh& mesh, const unsigned short rem) return true; } -static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int maxTris) +static bool removeVertex(rcBuildContext* ctx, rcPolyMesh& mesh, const unsigned short rem, const int maxTris) { const int nvp = mesh.nvp; @@ -610,8 +606,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m rcScopedDelete edges = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp*4, RC_ALLOC_TEMP); if (!edges) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'edges' (%d).", numRemovedVerts*nvp*4); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'edges' (%d).", numRemovedVerts*nvp*4); return false; } @@ -619,8 +614,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m rcScopedDelete hole = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); if (!hole) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hole' (%d).", numRemovedVerts*nvp); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hole' (%d).", numRemovedVerts*nvp); return false; } @@ -628,8 +622,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m rcScopedDelete hreg = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); if (!hreg) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hreg' (%d).", numRemovedVerts*nvp); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hreg' (%d).", numRemovedVerts*nvp); return false; } @@ -637,8 +630,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m rcScopedDelete harea = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); if (!harea) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'harea' (%d).", numRemovedVerts*nvp); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'harea' (%d).", numRemovedVerts*nvp); return false; } @@ -754,24 +746,21 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m rcScopedDelete tris = (int*)rcAlloc(sizeof(int)*nhole*3, RC_ALLOC_TEMP); if (!tris) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tris' (%d).", nhole*3); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tris' (%d).", nhole*3); return false; } rcScopedDelete tverts = (int*)rcAlloc(sizeof(int)*nhole*4, RC_ALLOC_TEMP); if (!tverts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tverts' (%d).", nhole*4); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tverts' (%d).", nhole*4); return false; } rcScopedDelete thole = (int*)rcAlloc(sizeof(int)*nhole, RC_ALLOC_TEMP); if (!tverts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: Out of memory 'thole' (%d).", nhole); + ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'thole' (%d).", nhole); return false; } @@ -791,30 +780,26 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m if (ntris < 0) { ntris = -ntris; - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "removeVertex: triangulate() returned bad results."); + ctx->log(RC_LOG_WARNING, "removeVertex: triangulate() returned bad results."); } // Merge the hole triangles back to polygons. rcScopedDelete polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*(ntris+1)*nvp, RC_ALLOC_TEMP); if (!polys) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Out of memory 'polys' (%d).", (ntris+1)*nvp); + ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'polys' (%d).", (ntris+1)*nvp); return false; } rcScopedDelete pregs = (unsigned short*)rcAlloc(sizeof(unsigned short)*ntris, RC_ALLOC_TEMP); if (!pregs) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pregs' (%d).", ntris); + ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pregs' (%d).", ntris); return false; } rcScopedDelete pareas = (unsigned char*)rcAlloc(sizeof(unsigned char)*ntris, RC_ALLOC_TEMP); if (!pregs) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pareas' (%d).", ntris); + ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pareas' (%d).", ntris); return false; } @@ -899,8 +884,7 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m mesh.npolys++; if (mesh.npolys > maxTris) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "removeVertex: Too many polygons %d (max:%d).", mesh.npolys, maxTris); + ctx->log(RC_LOG_ERROR, "removeVertex: Too many polygons %d (max:%d).", mesh.npolys, maxTris); return false; } } @@ -909,9 +893,11 @@ static bool removeVertex(rcPolyMesh& mesh, const unsigned short rem, const int m } -bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) +bool rcBuildPolyMesh(rcBuildContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); rcVcopy(mesh.bmin, cset.bmin); rcVcopy(mesh.bmax, cset.bmax); @@ -932,16 +918,14 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) if (maxVertices >= 0xfffe) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Too many vertices %d.", maxVertices); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Too many vertices %d.", maxVertices); return false; } rcScopedDelete vflags = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxVertices, RC_ALLOC_TEMP); if (!vflags) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); return false; } memset(vflags, 0, maxVertices); @@ -949,29 +933,25 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) mesh.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVertices*3, RC_ALLOC_PERM); if (!mesh.verts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); return false; } mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2*2, RC_ALLOC_PERM); if (!mesh.polys) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.polys' (%d).", maxTris*nvp*2); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.polys' (%d).", maxTris*nvp*2); return false; } mesh.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris, RC_ALLOC_PERM); if (!mesh.regs) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.regs' (%d).", maxTris); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.regs' (%d).", maxTris); return false; } mesh.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxTris, RC_ALLOC_PERM); if (!mesh.areas) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.areas' (%d).", maxTris); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.areas' (%d).", maxTris); return false; } @@ -988,8 +968,7 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) rcScopedDelete nextVert = (int*)rcAlloc(sizeof(int)*maxVertices, RC_ALLOC_TEMP); if (!nextVert) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'nextVert' (%d).", maxVertices); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'nextVert' (%d).", maxVertices); return false; } memset(nextVert, 0, sizeof(int)*maxVertices); @@ -997,8 +976,7 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) rcScopedDelete firstVert = (int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP); if (!firstVert) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); return false; } for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i) @@ -1007,22 +985,19 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) rcScopedDelete indices = (int*)rcAlloc(sizeof(int)*maxVertsPerCont, RC_ALLOC_TEMP); if (!indices) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'indices' (%d).", maxVertsPerCont); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'indices' (%d).", maxVertsPerCont); return false; } rcScopedDelete tris = (int*)rcAlloc(sizeof(int)*maxVertsPerCont*3, RC_ALLOC_TEMP); if (!tris) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'tris' (%d).", maxVertsPerCont*3); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'tris' (%d).", maxVertsPerCont*3); return false; } rcScopedDelete polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*(maxVertsPerCont+1)*nvp, RC_ALLOC_TEMP); if (!polys) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'polys' (%d).", maxVertsPerCont*nvp); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'polys' (%d).", maxVertsPerCont*nvp); return false; } unsigned short* tmpPoly = &polys[maxVertsPerCont*nvp]; @@ -1053,8 +1028,7 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) printf("\t\t%d,%d,%d,%d,\n", v[0], v[1], v[2], v[3]); } printf("\t};\n\tconst int nverts = sizeof(verts)/(sizeof(int)*4);\n");*/ - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "rcBuildPolyMesh: Bad triangulation Contour %d.", i); + ctx->log(RC_LOG_WARNING, "rcBuildPolyMesh: Bad triangulation Contour %d.", i); ntris = -ntris; } @@ -1145,8 +1119,7 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) mesh.npolys++; if (mesh.npolys > maxTris) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Too many polygons %d (max:%d).", mesh.npolys, maxTris); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Too many polygons %d (max:%d).", mesh.npolys, maxTris); return false; } } @@ -1158,13 +1131,12 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) { if (vflags[i]) { - if (!canRemoveVertex(mesh, (unsigned short)i)) + if (!canRemoveVertex(ctx, mesh, (unsigned short)i)) continue; - if (!removeVertex(mesh, (unsigned short)i, maxTris)) + if (!removeVertex(ctx, mesh, (unsigned short)i, maxTris)) { // Failed to remove vertex - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Failed to remove edge vertex %d.", i); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Failed to remove edge vertex %d.", i); return false; } // Remove vertex @@ -1178,8 +1150,7 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) // Calculate adjacency. if (!buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, nvp)) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed."); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed."); return false; } @@ -1187,28 +1158,26 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh) mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*mesh.npolys, RC_ALLOC_PERM); if (!mesh.flags) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.flags' (%d).", mesh.npolys); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.flags' (%d).", mesh.npolys); return false; } memset(mesh.flags, 0, sizeof(unsigned short) * mesh.npolys); - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); -// if (rcGetLog()) -// rcGetLog()->log(RC_LOG_PROGRESS, "Build polymesh: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); - if (rcGetBuildTimes()) - rcGetBuildTimes()->buildPolymesh += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_BUILD_POLYMESH, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } -bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) +bool rcMergePolyMeshes(rcBuildContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) { + rcAssert(ctx); + if (!nmeshes || !meshes) return true; - rcTimeVal startTime = rcGetPerformanceTimer(); + rcTimeVal startTime = ctx->getTime(); mesh.nvp = meshes[0]->nvp; mesh.cs = meshes[0]->cs; @@ -1232,8 +1201,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) mesh.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVerts*3, RC_ALLOC_PERM); if (!mesh.verts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.verts' (%d).", maxVerts*3); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.verts' (%d).", maxVerts*3); return false; } @@ -1241,8 +1209,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxPolys*2*mesh.nvp, RC_ALLOC_PERM); if (!mesh.polys) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.polys' (%d).", maxPolys*2*mesh.nvp); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.polys' (%d).", maxPolys*2*mesh.nvp); return false; } memset(mesh.polys, 0xff, sizeof(unsigned short)*maxPolys*2*mesh.nvp); @@ -1250,8 +1217,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) mesh.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxPolys, RC_ALLOC_PERM); if (!mesh.regs) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.regs' (%d).", maxPolys); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.regs' (%d).", maxPolys); return false; } memset(mesh.regs, 0, sizeof(unsigned short)*maxPolys); @@ -1259,8 +1225,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) mesh.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxPolys, RC_ALLOC_PERM); if (!mesh.areas) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.areas' (%d).", maxPolys); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.areas' (%d).", maxPolys); return false; } memset(mesh.areas, 0, sizeof(unsigned char)*maxPolys); @@ -1268,8 +1233,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxPolys, RC_ALLOC_PERM); if (!mesh.flags) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.flags' (%d).", maxPolys); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.flags' (%d).", maxPolys); return false; } memset(mesh.flags, 0, sizeof(unsigned short)*maxPolys); @@ -1277,8 +1241,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) rcScopedDelete nextVert = (int*)rcAlloc(sizeof(int)*maxVerts, RC_ALLOC_TEMP); if (!nextVert) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'nextVert' (%d).", maxVerts); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'nextVert' (%d).", maxVerts); return false; } memset(nextVert, 0, sizeof(int)*maxVerts); @@ -1286,8 +1249,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) rcScopedDelete firstVert = (int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP); if (!firstVert) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); return false; } for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i) @@ -1296,8 +1258,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) rcScopedDelete vremap = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVertsPerMesh, RC_ALLOC_PERM); if (!vremap) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'vremap' (%d).", maxVertsPerMesh); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'vremap' (%d).", maxVertsPerMesh); return false; } memset(nextVert, 0, sizeof(int)*maxVerts); @@ -1335,16 +1296,14 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) // Calculate adjacency. if (!buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, mesh.nvp)) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Adjacency failed."); + ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Adjacency failed."); return false; } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->mergePolyMesh += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_MERGE_POLYMESH, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } diff --git a/Recast/Source/RecastMeshDetail.cpp b/Recast/Source/RecastMeshDetail.cpp index 8c9e476..afac285 100644 --- a/Recast/Source/RecastMeshDetail.cpp +++ b/Recast/Source/RecastMeshDetail.cpp @@ -23,9 +23,8 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" #include "RecastAlloc.h" +#include "RecastAssert.h" static const unsigned RC_UNSET_HEIGHT = 0xffff; @@ -256,12 +255,11 @@ static int findEdge(const int* edges, int nedges, int s, int t) return UNDEF; } -static int addEdge(int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r) +static int addEdge(rcBuildContext* ctx, int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r) { if (nedges >= maxEdges) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "addEdge: Too many edges (%d/%d).", nedges, maxEdges); + ctx->log(RC_LOG_ERROR, "addEdge: Too many edges (%d/%d).", nedges, maxEdges); return UNDEF; } @@ -319,7 +317,7 @@ static bool overlapEdges(const float* pts, const int* edges, int nedges, int s1, return false; } -static void completeFacet(const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e) +static void completeFacet(rcBuildContext* ctx, const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e) { static const float EPS = 1e-5f; @@ -396,14 +394,14 @@ static void completeFacet(const float* pts, int npts, int* edges, int& nedges, c // Add new edge or update face info of old edge. e = findEdge(edges, nedges, pt, s); if (e == UNDEF) - addEdge(edges, nedges, maxEdges, pt, s, nfaces, UNDEF); + addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, UNDEF); else updateLeftFace(&edges[e*4], pt, s, nfaces); // Add new edge or update face info of old edge. e = findEdge(edges, nedges, t, pt); if (e == UNDEF) - addEdge(edges, nedges, maxEdges, t, pt, nfaces, UNDEF); + addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, UNDEF); else updateLeftFace(&edges[e*4], t, pt, nfaces); @@ -415,7 +413,7 @@ static void completeFacet(const float* pts, int npts, int* edges, int& nedges, c } } -static void delaunayHull(const int npts, const float* pts, +static void delaunayHull(rcBuildContext* ctx, const int npts, const float* pts, const int nhull, const int* hull, rcIntArray& tris, rcIntArray& edges) { @@ -425,15 +423,15 @@ static void delaunayHull(const int npts, const float* pts, edges.resize(maxEdges*4); for (int i = 0, j = nhull-1; i < nhull; j=i++) - addEdge(&edges[0], nedges, maxEdges, hull[j],hull[i], HULL, UNDEF); + addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], HULL, UNDEF); int currentEdge = 0; while (currentEdge < nedges) { if (edges[currentEdge*4+2] == UNDEF) - completeFacet(pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); + completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); if (edges[currentEdge*4+3] == UNDEF) - completeFacet(pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); + completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); currentEdge++; } @@ -480,8 +478,7 @@ static void delaunayHull(const int npts, const float* pts, int* t = &tris[i*4]; if (t[0] == -1 || t[1] == -1 || t[2] == -1) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "delaunayHull: Removing dangling face %d [%d,%d,%d].", i, t[0],t[1],t[2]); + ctx->log(RC_LOG_WARNING, "delaunayHull: Removing dangling face %d [%d,%d,%d].", i, t[0],t[1],t[2]); t[0] = tris[tris.size()-4]; t[1] = tris[tris.size()-3]; t[2] = tris[tris.size()-2]; @@ -494,7 +491,7 @@ static void delaunayHull(const int npts, const float* pts, -static bool buildPolyDetail(const float* in, const int nin, +static bool buildPolyDetail(rcBuildContext* 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, @@ -625,13 +622,12 @@ static bool buildPolyDetail(const float* in, const int nin, edges.resize(0); tris.resize(0); - delaunayHull(nverts, verts, nhull, hull, tris, edges); + delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges); if (tris.size() == 0) { // Could not triangulate the poly, make sure there is some valid data there. - if (rcGetLog()) - rcGetLog()->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon, adding default data."); + ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon, adding default data."); for (int i = 2; i < nverts; ++i) { tris.push(0); @@ -709,7 +705,7 @@ static bool buildPolyDetail(const float* in, const int nin, // TODO: Incremental add instead of full rebuild. edges.resize(0); tris.resize(0); - delaunayHull(nverts, verts, nhull, hull, tris, edges); + delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges); if (nverts >= MAX_VERTS) break; @@ -918,11 +914,13 @@ static unsigned char getTriFlags(const float* va, const float* vb, const float* -bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& chf, +bool rcBuildPolyMeshDetail(rcBuildContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& dmesh) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); if (mesh.nverts == 0 || mesh.npolys == 0) return true; @@ -944,15 +942,13 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c rcScopedDelete bounds = (int*)rcAlloc(sizeof(int)*mesh.npolys*4, RC_ALLOC_TEMP); if (!bounds) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4); return false; } rcScopedDelete poly = (float*)rcAlloc(sizeof(float)*nvp*3, RC_ALLOC_TEMP); if (!poly) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3); return false; } @@ -990,8 +986,7 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c hp.data = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxhw*maxhh, RC_ALLOC_TEMP); if (!hp.data) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh); return false; } @@ -1001,8 +996,7 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c dmesh.meshes = (unsigned short*)rcAlloc(sizeof(unsigned short)*dmesh.nmeshes*4, RC_ALLOC_PERM); if (!dmesh.meshes) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4); return false; } @@ -1013,16 +1007,14 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c dmesh.verts = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); if (!dmesh.verts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3); return false; } dmesh.ntris = 0; dmesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char*)*tcap*4, RC_ALLOC_PERM); if (!dmesh.tris) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4); return false; } @@ -1051,7 +1043,7 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c // Build detail mesh. int nverts = 0; - if (!buildPolyDetail(poly, npoly, + if (!buildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, chf, hp, verts, nverts, tris, edges, samples)) @@ -1091,8 +1083,7 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c float* newv = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); if (!newv) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3); return false; } if (dmesh.nverts) @@ -1116,8 +1107,7 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c unsigned char* newt = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM); if (!newt) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4); return false; } if (dmesh.ntris) @@ -1136,17 +1126,18 @@ bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& c } } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->buildDetailMesh += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_BUILD_POLYMESHDETAIL, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } -bool rcMergePolyMeshDetails(rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh) +bool rcMergePolyMeshDetails(rcBuildContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); int maxVerts = 0; int maxTris = 0; @@ -1164,8 +1155,7 @@ bool rcMergePolyMeshDetails(rcPolyMeshDetail** meshes, const int nmeshes, rcPoly mesh.meshes = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxMeshes*4, RC_ALLOC_PERM); if (!mesh.meshes) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'pmdtl.meshes' (%d).", maxMeshes*4); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'pmdtl.meshes' (%d).", maxMeshes*4); return false; } @@ -1173,8 +1163,7 @@ bool rcMergePolyMeshDetails(rcPolyMeshDetail** meshes, const int nmeshes, rcPoly mesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxTris*4, RC_ALLOC_PERM); if (!mesh.tris) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", maxTris*4); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", maxTris*4); return false; } @@ -1182,8 +1171,7 @@ bool rcMergePolyMeshDetails(rcPolyMeshDetail** meshes, const int nmeshes, rcPoly mesh.verts = (float*)rcAlloc(sizeof(float)*maxVerts*3, RC_ALLOC_PERM); if (!mesh.verts) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", maxVerts*3); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", maxVerts*3); return false; } @@ -1218,10 +1206,9 @@ bool rcMergePolyMeshDetails(rcPolyMeshDetail** meshes, const int nmeshes, rcPoly } } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->mergePolyMeshDetail += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_MERGE_POLYMESHDETAIL, ctx->getDeltaTimeUsec(startTime, endTime)); return true; } diff --git a/Recast/Source/RecastRasterization.cpp b/Recast/Source/RecastRasterization.cpp index bffe8bb..72904e7 100644 --- a/Recast/Source/RecastRasterization.cpp +++ b/Recast/Source/RecastRasterization.cpp @@ -20,9 +20,8 @@ #include #include #include "Recast.h" -#include "RecastTimer.h" -#include "RecastLog.h" #include "RecastAlloc.h" +#include "RecastAssert.h" inline bool overlapBounds(const float* amin, const float* amax, const float* bmin, const float* bmax) { @@ -83,10 +82,11 @@ static void freeSpan(rcHeightfield& hf, rcSpan* ptr) hf.freelist = ptr; } -void rcAddSpan(rcHeightfield& hf, const int x, const int y, - const unsigned short smin, const unsigned short smax, - const unsigned char area, const int flagMergeThr) +static void addSpan(rcHeightfield& hf, const int x, const int y, + const unsigned short smin, const unsigned short smax, + const unsigned char area, const int flagMergeThr) { + int idx = x + y*hf.width; rcSpan* s = allocSpan(hf); @@ -154,6 +154,14 @@ void rcAddSpan(rcHeightfield& hf, const int x, const int y, } } +void rcAddSpan(rcBuildContext* ctx, rcHeightfield& hf, const int x, const int y, + const unsigned short smin, const unsigned short smax, + const unsigned char area, const int flagMergeThr) +{ + rcAssert(ctx); + addSpan(hf, x,y, smin, smax, area, flagMergeThr); +} + static int clipPoly(const float* in, int n, float* out, float pnx, float pnz, float pd) { float d[12]; @@ -263,32 +271,35 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2, unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, RC_SPAN_MAX_HEIGHT); unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), (int)ismin+1, RC_SPAN_MAX_HEIGHT); - rcAddSpan(hf, x, y, ismin, ismax, area, flagMergeThr); + addSpan(hf, x, y, ismin, ismax, area, flagMergeThr); } } } -void rcRasterizeTriangle(const float* v0, const float* v1, const float* v2, +void rcRasterizeTriangle(rcBuildContext* ctx, const float* v0, const float* v1, const float* v2, const unsigned char area, rcHeightfield& solid, const int flagMergeThr) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); 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 = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime)); } -void rcRasterizeTriangles(const float* verts, const int /*nv*/, +void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int /*nv*/, const int* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -302,17 +313,18 @@ void rcRasterizeTriangles(const float* verts, const int /*nv*/, rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime)); } -void rcRasterizeTriangles(const float* verts, const int /*nv*/, +void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const int /*nv*/, const unsigned short* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -326,16 +338,17 @@ void rcRasterizeTriangles(const float* verts, const int /*nv*/, rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime)); } -void rcRasterizeTriangles(const float* verts, const unsigned char* areas, const int nt, +void rcRasterizeTriangles(rcBuildContext* ctx, const float* verts, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -349,8 +362,7 @@ void rcRasterizeTriangles(const float* verts, const unsigned char* areas, const rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); } - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - rcGetBuildTimes()->rasterizeTriangles += rcGetDeltaTimeUsec(startTime, endTime); + ctx->reportBuildTime(RC_TIME_RASTERIZE_TRIANGLES, ctx->getDeltaTimeUsec(startTime, endTime)); } diff --git a/Recast/Source/RecastRegion.cpp b/Recast/Source/RecastRegion.cpp index 120b046..91e700a 100644 --- a/Recast/Source/RecastRegion.cpp +++ b/Recast/Source/RecastRegion.cpp @@ -23,9 +23,8 @@ #include #include #include "Recast.h" -#include "RecastLog.h" -#include "RecastTimer.h" #include "RecastAlloc.h" +#include "RecastAssert.h" #include @@ -688,7 +687,7 @@ static void walkContour(int x, int y, int i, int dir, } } -static bool filterSmallRegions(int minRegionSize, int mergeRegionSize, +static bool filterSmallRegions(rcBuildContext* ctx, int minRegionSize, int mergeRegionSize, unsigned short& maxRegionId, rcCompactHeightfield& chf, unsigned short* srcReg) @@ -700,8 +699,7 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize, rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP); if (!regions) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "filterSmallRegions: Out of memory 'regions' (%d).", nreg); + ctx->log(RC_LOG_ERROR, "filterSmallRegions: Out of memory 'regions' (%d).", nreg); return false; } @@ -888,9 +886,11 @@ static bool filterSmallRegions(int minRegionSize, int mergeRegionSize, } -bool rcBuildDistanceField(rcCompactHeightfield& chf) +bool rcBuildDistanceField(rcBuildContext* ctx, rcCompactHeightfield& chf) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); if (chf.dist) { @@ -901,29 +901,27 @@ bool rcBuildDistanceField(rcCompactHeightfield& chf) unsigned short* src = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!src) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'src' (%d).", chf.spanCount); + ctx->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'src' (%d).", chf.spanCount); return false; } unsigned short* dst = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!dst) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'dst' (%d).", chf.spanCount); + ctx->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'dst' (%d).", chf.spanCount); rcFree(src); return false; } unsigned short maxDist = 0; - rcTimeVal distStartTime = rcGetPerformanceTimer(); + rcTimeVal distStartTime = ctx->getTime(); calculateDistanceField(chf, src, maxDist); chf.maxDistance = maxDist; - rcTimeVal distEndTime = rcGetPerformanceTimer(); + rcTimeVal distEndTime = ctx->getTime(); - rcTimeVal blurStartTime = rcGetPerformanceTimer(); + rcTimeVal blurStartTime = ctx->getTime(); // Blur if (boxBlur(chf, 1, src, dst) != src) @@ -932,24 +930,15 @@ bool rcBuildDistanceField(rcCompactHeightfield& chf) // Store distance. chf.dist = src; - rcTimeVal blurEndTime = rcGetPerformanceTimer(); + rcTimeVal blurEndTime = ctx->getTime(); rcFree(dst); - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); -/* if (rcGetLog()) - { - rcGetLog()->log(RC_LOG_PROGRESS, "Build distance field: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); - rcGetLog()->log(RC_LOG_PROGRESS, " - dist: %.3f ms", rcGetDeltaTimeUsec(distStartTime, distEndTime)/1000.0f); - rcGetLog()->log(RC_LOG_PROGRESS, " - blur: %.3f ms", rcGetDeltaTimeUsec(blurStartTime, blurEndTime)/1000.0f); - }*/ - if (rcGetBuildTimes()) - { - rcGetBuildTimes()->buildDistanceField += rcGetDeltaTimeUsec(startTime, endTime); - rcGetBuildTimes()->buildDistanceFieldDist += rcGetDeltaTimeUsec(distStartTime, distEndTime); - rcGetBuildTimes()->buildDistanceFieldBlur += rcGetDeltaTimeUsec(blurStartTime, blurEndTime); - } + 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; } @@ -984,10 +973,12 @@ struct rcSweepSpan unsigned short nei; // neighbour id }; -bool rcBuildRegionsMonotone(rcCompactHeightfield& chf, +bool rcBuildRegionsMonotone(rcBuildContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionSize, const int mergeRegionSize) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const int w = chf.width; const int h = chf.height; @@ -996,8 +987,7 @@ bool rcBuildRegionsMonotone(rcCompactHeightfield& chf, rcScopedDelete srcReg = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!srcReg) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'src' (%d).", chf.spanCount); + ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'src' (%d).", chf.spanCount); return false; } memset(srcReg,0,sizeof(unsigned short)*chf.spanCount); @@ -1006,8 +996,7 @@ bool rcBuildRegionsMonotone(rcCompactHeightfield& chf, rcScopedDelete sweeps = (rcSweepSpan*)rcAlloc(sizeof(rcSweepSpan)*nsweeps, RC_ALLOC_TEMP); if (!sweeps) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'sweeps' (%d).", nsweeps); + ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'sweeps' (%d).", nsweeps); return false; } @@ -1112,34 +1101,33 @@ bool rcBuildRegionsMonotone(rcCompactHeightfield& chf, } } - rcTimeVal filterStartTime = rcGetPerformanceTimer(); + rcTimeVal filterStartTime = ctx->getTime(); // Filter out small regions. chf.maxRegions = id; - if (!filterSmallRegions(minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg)) + if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg)) return false; - rcTimeVal filterEndTime = rcGetPerformanceTimer(); + rcTimeVal filterEndTime = ctx->getTime(); // Store the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); - if (rcGetBuildTimes()) - { - rcGetBuildTimes()->buildRegions += rcGetDeltaTimeUsec(startTime, endTime); - rcGetBuildTimes()->buildRegionsFilter += rcGetDeltaTimeUsec(filterStartTime, filterEndTime); - } + ctx->reportBuildTime(RC_TIME_BUILD_REGIONS, ctx->getDeltaTimeUsec(startTime, endTime)); + ctx->reportBuildTime(RC_TIME_BUILD_REGIONS_FILTER, ctx->getDeltaTimeUsec(filterStartTime, filterEndTime)); return true; } -bool rcBuildRegions(rcCompactHeightfield& chf, +bool rcBuildRegions(rcBuildContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionSize, const int mergeRegionSize) { - rcTimeVal startTime = rcGetPerformanceTimer(); + rcAssert(ctx); + + rcTimeVal startTime = ctx->getTime(); const int w = chf.width; const int h = chf.height; @@ -1147,12 +1135,11 @@ bool rcBuildRegions(rcCompactHeightfield& chf, rcScopedDelete buf = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount*4, RC_ALLOC_TEMP); if (!buf) { - if (rcGetLog()) - rcGetLog()->log(RC_LOG_ERROR, "rcBuildRegions: Out of memory 'tmp' (%d).", chf.spanCount*4); + ctx->log(RC_LOG_ERROR, "rcBuildRegions: Out of memory 'tmp' (%d).", chf.spanCount*4); return false; } - rcTimeVal regStartTime = rcGetPerformanceTimer(); + rcTimeVal regStartTime = ctx->getTime(); rcIntArray stack(1024); rcIntArray visited(1024); @@ -1187,7 +1174,7 @@ bool rcBuildRegions(rcCompactHeightfield& chf, { level = level >= 2 ? level-2 : 0; - rcTimeVal expStartTime = rcGetPerformanceTimer(); + rcTimeVal expStartTime = ctx->getTime(); // Expand current regions until no empty connected cells found. if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg) @@ -1196,9 +1183,9 @@ bool rcBuildRegions(rcCompactHeightfield& chf, rcSwap(srcDist, dstDist); } - expTime += rcGetPerformanceTimer() - expStartTime; + expTime += ctx->getTime() - expStartTime; - rcTimeVal floodStartTime = rcGetPerformanceTimer(); + rcTimeVal floodStartTime = ctx->getTime(); // Mark new regions with IDs. for (int y = 0; y < h; ++y) @@ -1217,7 +1204,7 @@ bool rcBuildRegions(rcCompactHeightfield& chf, } } - floodTime += rcGetPerformanceTimer() - floodStartTime; + floodTime += ctx->getTime() - floodStartTime; } @@ -1228,40 +1215,28 @@ bool rcBuildRegions(rcCompactHeightfield& chf, rcSwap(srcDist, dstDist); } - rcTimeVal regEndTime = rcGetPerformanceTimer(); + rcTimeVal regEndTime = ctx->getTime(); - rcTimeVal filterStartTime = rcGetPerformanceTimer(); + rcTimeVal filterStartTime = ctx->getTime(); // Filter out small regions. chf.maxRegions = regionId; - if (!filterSmallRegions(minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg)) + if (!filterSmallRegions(ctx, minRegionSize, mergeRegionSize, chf.maxRegions, chf, srcReg)) return false; - rcTimeVal filterEndTime = rcGetPerformanceTimer(); + rcTimeVal filterEndTime = ctx->getTime(); // Write the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - rcTimeVal endTime = rcGetPerformanceTimer(); + rcTimeVal endTime = ctx->getTime(); -/* if (rcGetLog()) - { - rcGetLog()->log(RC_LOG_PROGRESS, "Build regions: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); - rcGetLog()->log(RC_LOG_PROGRESS, " - reg: %.3f ms", rcGetDeltaTimeUsec(regStartTime, regEndTime)/1000.0f); - rcGetLog()->log(RC_LOG_PROGRESS, " - exp: %.3f ms", rcGetDeltaTimeUsec(0, expTime)/1000.0f); - rcGetLog()->log(RC_LOG_PROGRESS, " - flood: %.3f ms", rcGetDeltaTimeUsec(0, floodTime)/1000.0f); - rcGetLog()->log(RC_LOG_PROGRESS, " - filter: %.3f ms", rcGetDeltaTimeUsec(filterStartTime, filterEndTime)/1000.0f); - } -*/ - if (rcGetBuildTimes()) - { - rcGetBuildTimes()->buildRegions += rcGetDeltaTimeUsec(startTime, endTime); - rcGetBuildTimes()->buildRegionsReg += rcGetDeltaTimeUsec(regStartTime, regEndTime); - rcGetBuildTimes()->buildRegionsExp += rcGetDeltaTimeUsec(0, expTime); - rcGetBuildTimes()->buildRegionsFlood += rcGetDeltaTimeUsec(0, floodTime); - rcGetBuildTimes()->buildRegionsFilter += rcGetDeltaTimeUsec(filterStartTime, filterEndTime); - } + 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; } diff --git a/Recast/Source/RecastTimer.cpp b/Recast/Source/RecastTimer.cpp deleted file mode 100644 index 376eae1..0000000 --- a/Recast/Source/RecastTimer.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#include "RecastTimer.h" - -#if defined(WIN32) - -// Win32 -#include - -rcTimeVal rcGetPerformanceTimer() -{ - __int64 count; - QueryPerformanceCounter((LARGE_INTEGER*)&count); - return count; -} - -int rcGetDeltaTimeUsec(rcTimeVal start, 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 - -rcTimeVal rcGetPerformanceTimer() -{ - timeval now; - gettimeofday(&now, 0); - return (rcTimeVal)now.tv_sec*1000000L + (rcTimeVal)now.tv_usec; -} - -int rcGetDeltaTimeUsec(rcTimeVal start, rcTimeVal end) -{ - return (int)(end - start); -} - -#endif