Removed Recast timer and log, added rcBuildContext, improved build time printout, fixed issue 67, issue 77, issue 87
This commit is contained in:
parent
5f7ac70cba
commit
613d61f453
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user