update recast

This commit is contained in:
Johxz 2018-02-28 22:15:31 -06:00
parent e079536122
commit 8aa48ff21b
34 changed files with 1138 additions and 407 deletions

View file

@ -293,6 +293,9 @@ struct rcSpanPool
/// @ingroup recast
struct rcHeightfield
{
rcHeightfield();
~rcHeightfield();
int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
@ -302,6 +305,11 @@ struct rcHeightfield
rcSpan** spans; ///< Heightfield of spans (width*height).
rcSpanPool* pools; ///< Linked list of span pools.
rcSpan* freelist; ///< The next free span.
private:
// Explicitly-disabled copy constructor and copy assignment operator.
rcHeightfield(const rcHeightfield&);
rcHeightfield& operator=(const rcHeightfield&);
};
/// Provides information on the content of a cell column in a compact heightfield.
@ -886,7 +894,7 @@ bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr = 1);
/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neihbor.
/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neighbor.
/// @ingroup recast
/// @param[in,out] ctx The build context to use during the operation.
/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.

View file

@ -123,7 +123,6 @@ public:
template<class T> class rcScopedDelete
{
T* ptr;
inline T* operator=(T* p);
public:
/// Constructs an instance with a null pointer.

View file

@ -23,11 +23,34 @@
// Feel free to change the file and include your own implementation instead.
#ifdef NDEBUG
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
# define rcAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false)
# define rcAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false)
#else
/// An assertion failure function.
// @param[in] expression asserted expression.
// @param[in] file Filename of the failed assertion.
// @param[in] line Line number of the failed assertion.
/// @see rcAssertFailSetCustom
typedef void (rcAssertFailFunc)(const char* expression, const char* file, int line);
/// Sets the base custom assertion failure function to be used by Recast.
/// @param[in] assertFailFunc The function to be used in case of failure of #dtAssert
void rcAssertFailSetCustom(rcAssertFailFunc *assertFailFunc);
/// Gets the base custom assertion failure function to be used by Recast.
rcAssertFailFunc* rcAssertFailGetCustom();
# include <assert.h>
# define rcAssert assert
# define rcAssert(expression) \
{ \
rcAssertFailFunc* failFunc = rcAssertFailGetCustom(); \
if(failFunc == NULL) { assert(expression); } \
else if(!(expression)) { (*failFunc)(#expression, __FILE__, __LINE__); } \
}
#endif
#endif // RECASTASSERT_H

View file

@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <new>
#include "Recast.h"
#include "RecastAlloc.h"
#include "RecastAssert.h"
@ -72,23 +73,39 @@ void rcContext::log(const rcLogCategory category, const char* format, ...)
rcHeightfield* rcAllocHeightfield()
{
rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM);
memset(hf, 0, sizeof(rcHeightfield));
return hf;
return new (rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM)) rcHeightfield;
}
rcHeightfield::rcHeightfield()
: width()
, height()
, bmin()
, bmax()
, cs()
, ch()
, spans()
, pools()
, freelist()
{
}
rcHeightfield::~rcHeightfield()
{
// Delete span array.
rcFree(spans);
// Delete span pools.
while (pools)
{
rcSpanPool* next = pools->next;
rcFree(pools);
pools = next;
}
}
void rcFreeHeightField(rcHeightfield* hf)
{
if (!hf) return;
// Delete span array.
rcFree(hf->spans);
// Delete span pools.
while (hf->pools)
{
rcSpanPool* next = hf->pools->next;
rcFree(hf->pools);
hf->pools = next;
}
hf->~rcHeightfield();
rcFree(hf);
}
@ -109,7 +126,6 @@ void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
rcFree(chf);
}
rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
{
rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM);
@ -245,11 +261,12 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
///
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
const float* verts, int /*nv*/,
const float* verts, int nv,
const int* tris, int nt,
unsigned char* areas)
{
rcIgnoreUnused(ctx);
rcIgnoreUnused(nv);
const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);

View file

@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>
#include "RecastAlloc.h"
#include "RecastAssert.h"
static void *rcAllocDefault(size_t size, rcAllocHint)
{
@ -77,6 +78,7 @@ void rcIntArray::doResize(int n)
if (!m_cap) m_cap = n;
while (m_cap < n) m_cap *= 2;
int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP);
rcAssert(newData);
if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int));
rcFree(m_data);
m_data = newData;

View file

@ -0,0 +1,35 @@
//
// 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 "RecastAssert.h"
#ifndef NDEBUG
static rcAssertFailFunc* sRecastAssertFailFunc = 0;
void rcAssertFailSetCustom(rcAssertFailFunc *assertFailFunc)
{
sRecastAssertFailFunc = assertFailFunc;
}
rcAssertFailFunc* rcAssertFailGetCustom()
{
return sRecastAssertFailFunc;
}
#endif

View file

@ -27,7 +27,9 @@
#include "RecastAssert.h"
static const int RC_MAX_LAYERS = RC_NOT_CONNECTED;
// Must be 255 or smaller (not 256) because layer IDs are stored as
// a byte where 255 is a special value.
static const int RC_MAX_LAYERS = 63;
static const int RC_MAX_NEIS = 16;
struct rcLayerRegion
@ -42,25 +44,31 @@ struct rcLayerRegion
};
static void addUnique(unsigned char* a, unsigned char& an, unsigned char v)
{
const int n = (int)an;
for (int i = 0; i < n; ++i)
if (a[i] == v)
return;
a[an] = v;
an++;
}
static bool contains(const unsigned char* a, const unsigned char an, const unsigned char v)
{
const int n = (int)an;
for (int i = 0; i < n; ++i)
{
if (a[i] == v)
return true;
}
return false;
}
static bool addUnique(unsigned char* a, unsigned char& an, int anMax, unsigned char v)
{
if (contains(a, an, v))
return true;
if ((int)an >= anMax)
return false;
a[an] = v;
an++;
return true;
}
inline bool overlapRange(const unsigned short amin, const unsigned short amax,
const unsigned short bmin, const unsigned short bmax)
{
@ -258,8 +266,13 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
const int ay = y + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
const unsigned char rai = srcReg[ai];
if (rai != 0xff && rai != ri && regs[ri].nneis < RC_MAX_NEIS)
addUnique(regs[ri].neis, regs[ri].nneis, rai);
if (rai != 0xff && rai != ri)
{
// Don't check return value -- if we cannot add the neighbor
// it will just cause a few more regions to be created, which
// is fine.
addUnique(regs[ri].neis, regs[ri].nneis, RC_MAX_NEIS, rai);
}
}
}
@ -274,8 +287,13 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
{
rcLayerRegion& ri = regs[lregs[i]];
rcLayerRegion& rj = regs[lregs[j]];
addUnique(ri.layers, ri.nlayers, lregs[j]);
addUnique(rj.layers, rj.nlayers, lregs[i]);
if (!addUnique(ri.layers, ri.nlayers, RC_MAX_LAYERS, lregs[j]) ||
!addUnique(rj.layers, rj.nlayers, RC_MAX_LAYERS, lregs[i]))
{
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: layer overflow (too many overlapping walkable platforms). Try increasing RC_MAX_LAYERS.");
return false;
}
}
}
}
@ -338,7 +356,13 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
regn.layerId = layerId;
// Merge current layers to root.
for (int k = 0; k < regn.nlayers; ++k)
addUnique(root.layers, root.nlayers, regn.layers[k]);
{
if (!addUnique(root.layers, root.nlayers, RC_MAX_LAYERS, regn.layers[k]))
{
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: layer overflow (too many overlapping walkable platforms). Try increasing RC_MAX_LAYERS.");
return false;
}
}
root.ymin = rcMin(root.ymin, regn.ymin);
root.ymax = rcMax(root.ymax, regn.ymax);
}
@ -416,7 +440,14 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
rj.layerId = newId;
// Add overlaid layers from 'rj' to 'ri'.
for (int k = 0; k < rj.nlayers; ++k)
addUnique(ri.layers, ri.nlayers, rj.layers[k]);
{
if (!addUnique(ri.layers, ri.nlayers, RC_MAX_LAYERS, rj.layers[k]))
{
ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: layer overflow (too many overlapping walkable platforms). Try increasing RC_MAX_LAYERS.");
return false;
}
}
// Update height bounds.
ri.ymin = rcMin(ri.ymin, rj.ymin);
ri.ymax = rcMax(ri.ymax, rj.ymax);

View file

@ -379,7 +379,7 @@ static int triangulate(int n, const int* verts, int* indices, int* tris)
// We might get here because the contour has overlapping segments, like this:
//
// A o-o=====o---o B
// / |C D| \
// / |C D| \.
// o o o o
// : : : :
// We'll try to recover by loosing up the inCone test a bit so that a diagonal

View file

@ -647,11 +647,10 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
int hull[MAX_VERTS];
int nhull = 0;
nverts = 0;
nverts = nin;
for (int i = 0; i < nin; ++i)
rcVcopy(&verts[i*3], &in[i*3]);
nverts = nin;
edges.resize(0);
tris.resize(0);
@ -777,7 +776,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
// Tessellate the base mesh.
// We're using the triangulateHull instead of delaunayHull as it tends to
// create a bit better triangulation for long thing triangles when there
// create a bit better triangulation for long thin triangles when there
// are no internal points.
triangulateHull(nverts, verts, nhull, hull, tris);

View file

@ -1575,12 +1575,6 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
// Make sure border will not overflow.
const int bw = rcMin(w, borderSize);
const int bh = rcMin(h, borderSize);
if (regionId > 0xFFFB)
{
ctx->log(RC_LOG_ERROR, "rcBuildRegions: Region ID overflow");
return false;
}
// Paint regions
paintRectRegion(0, bw, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
@ -1690,7 +1684,7 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf,
rcScopedDelete<unsigned short> srcReg((unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP));
if (!srcReg)
{
ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'src' (%d).", chf.spanCount);
ctx->log(RC_LOG_ERROR, "rcBuildLayerRegions: Out of memory 'src' (%d).", chf.spanCount);
return false;
}
memset(srcReg,0,sizeof(unsigned short)*chf.spanCount);
@ -1699,7 +1693,7 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf,
rcScopedDelete<rcSweepSpan> sweeps((rcSweepSpan*)rcAlloc(sizeof(rcSweepSpan)*nsweeps, RC_ALLOC_TEMP));
if (!sweeps)
{
ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'sweeps' (%d).", nsweeps);
ctx->log(RC_LOG_ERROR, "rcBuildLayerRegions: Out of memory 'sweeps' (%d).", nsweeps);
return false;
}