Removed Recast timer and log, added rcBuildContext, improved build time printout, fixed issue 67, issue 77, issue 87

This commit is contained in:
Mikko Mononen 2010-08-19 09:26:55 +00:00
parent 5f7ac70cba
commit 613d61f453
13 changed files with 390 additions and 643 deletions

View File

@ -19,6 +19,72 @@
#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,
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

View File

@ -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 <stdint.h>
typedef int64_t rcTimeVal;
#ifndef RECASTASSERT_H
#define RECASTASSERT_H
#ifdef NDEBUG
# define rcAssert(x)
#else
typedef __int64 rcTimeVal;
# include <assert.h>
# define rcAssert assert
#endif
rcTimeVal rcGetPerformanceTimer();
int rcGetDeltaTimeUsec(rcTimeVal start, rcTimeVal end);
#endif // RECAST_TIMER_H
#endif // RECASTASSERT_H

View File

@ -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

View File

@ -23,9 +23,8 @@
#include <stdlib.h>
#include <stdio.h>
#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;
}

View File

@ -23,21 +23,25 @@
#include <stdlib.h>
#include <stdio.h>
#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));
}

View File

@ -21,9 +21,8 @@
#include <string.h>
#include <stdio.h>
#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<unsigned char> 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;
}

View File

@ -20,13 +20,15 @@
#include <math.h>
#include <stdio.h>
#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));
}

View File

@ -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 <stdio.h>
#include <stdarg.h>
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;
}

View File

@ -21,9 +21,8 @@
#include <string.h>
#include <stdio.h>
#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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<unsigned short> 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<unsigned short> 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<unsigned char> 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<unsigned char> 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<int> 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<int> 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<int> 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<int> 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<unsigned short> 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<int> 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<int> 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<unsigned short> 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;
}

View File

@ -23,9 +23,8 @@
#include <stdlib.h>
#include <stdio.h>
#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<int> 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<float> 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;
}

View File

@ -20,9 +20,8 @@
#include <math.h>
#include <stdio.h>
#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));
}

View File

@ -23,9 +23,8 @@
#include <stdlib.h>
#include <stdio.h>
#include "Recast.h"
#include "RecastLog.h"
#include "RecastTimer.h"
#include "RecastAlloc.h"
#include "RecastAssert.h"
#include <new>
@ -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<unsigned short> 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<rcSweepSpan> 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<unsigned short> 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;
}

View File

@ -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 <windows.h>
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 <sys/time.h>
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