Ver código fonte

recast: Update to upstream version 1.6.0

Release notes:
- https://github.com/recastnavigation/recastnavigation/releases/tag/v1.6.0
Rémi Verschelde 2 anos atrás
pai
commit
2058b63067

+ 1 - 1
thirdparty/README.md

@@ -617,7 +617,7 @@ in 10.40, it can be found in the `patches` folder.
 ## recastnavigation
 ## recastnavigation
 
 
 - Upstream: https://github.com/recastnavigation/recastnavigation
 - Upstream: https://github.com/recastnavigation/recastnavigation
-- Version: git (4fef0446609b23d6ac180ed822817571525528a1, 2022)
+- Version: 1.6.0 (6dc1667f580357e8a2154c28b7867bea7e8ad3a7, 2023)
 - License: zlib
 - License: zlib
 
 
 Files extracted from upstream source:
 Files extracted from upstream source:

Diferenças do arquivo suprimidas por serem muito extensas
+ 493 - 362
thirdparty/recastnavigation/Recast/Include/Recast.h


+ 19 - 10
thirdparty/recastnavigation/Recast/Include/RecastAlloc.h

@@ -19,11 +19,11 @@
 #ifndef RECASTALLOC_H
 #ifndef RECASTALLOC_H
 #define RECASTALLOC_H
 #define RECASTALLOC_H
 
 
-#include <stddef.h>
-#include <stdint.h>
-
 #include "RecastAssert.h"
 #include "RecastAssert.h"
 
 
+#include <stdlib.h>
+#include <stdint.h>
+
 /// Provides hint values to the memory allocator on how long the
 /// Provides hint values to the memory allocator on how long the
 /// memory is expected to be used.
 /// memory is expected to be used.
 enum rcAllocHint
 enum rcAllocHint
@@ -47,18 +47,27 @@ typedef void (rcFreeFunc)(void* ptr);
 /// Sets the base custom allocation functions to be used by Recast.
 /// Sets the base custom allocation functions to be used by Recast.
 ///  @param[in]		allocFunc	The memory allocation function to be used by #rcAlloc
 ///  @param[in]		allocFunc	The memory allocation function to be used by #rcAlloc
 ///  @param[in]		freeFunc	The memory de-allocation function to be used by #rcFree
 ///  @param[in]		freeFunc	The memory de-allocation function to be used by #rcFree
+///  
+/// @see rcAlloc, rcFree
 void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc);
 void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc);
 
 
 /// Allocates a memory block.
 /// Allocates a memory block.
-///  @param[in]		size	The size, in bytes of memory, to allocate.
-///  @param[in]		hint	A hint to the allocator on how long the memory is expected to be in use.
-///  @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
-/// @see rcFree
+/// 
+/// @param[in]		size	The size, in bytes of memory, to allocate.
+/// @param[in]		hint	A hint to the allocator on how long the memory is expected to be in use.
+/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
+/// 
+/// @see rcFree, rcAllocSetCustom
 void* rcAlloc(size_t size, rcAllocHint hint);
 void* rcAlloc(size_t size, rcAllocHint hint);
 
 
-/// Deallocates a memory block.
-///  @param[in]		ptr		A pointer to a memory block previously allocated using #rcAlloc.
-/// @see rcAlloc
+/// Deallocates a memory block.  If @p ptr is NULL, this does nothing.
+///
+/// @warning This function leaves the value of @p ptr unchanged.  So it still
+/// points to the same (now invalid) location, and not to null.
+/// 
+/// @param[in]		ptr		A pointer to a memory block previously allocated using #rcAlloc.
+/// 
+/// @see rcAlloc, rcAllocSetCustom
 void rcFree(void* ptr);
 void rcFree(void* ptr);
 
 
 /// An implementation of operator new usable for placement new. The default one is part of STL (which we don't use).
 /// An implementation of operator new usable for placement new. The default one is part of STL (which we don't use).

+ 5 - 8
thirdparty/recastnavigation/Recast/Include/RecastAssert.h

@@ -19,13 +19,10 @@
 #ifndef RECASTASSERT_H
 #ifndef RECASTASSERT_H
 #define RECASTASSERT_H
 #define RECASTASSERT_H
 
 
-// Note: This header file's only purpose is to include define assert.
-// Feel free to change the file and include your own implementation instead.
-
 #ifdef NDEBUG
 #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)
+// From https://web.archive.org/web/20210117002833/http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
+#	define rcAssert(x) do { (void)sizeof(x); } while ((void)(__LINE__==-1), false)
 
 
 #else
 #else
 
 
@@ -38,7 +35,7 @@ typedef void (rcAssertFailFunc)(const char* expression, const char* file, int li
 
 
 /// Sets the base custom assertion failure function to be used by Recast.
 /// 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
 ///  @param[in]		assertFailFunc	The function to be used in case of failure of #dtAssert
-void rcAssertFailSetCustom(rcAssertFailFunc *assertFailFunc);
+void rcAssertFailSetCustom(rcAssertFailFunc* assertFailFunc);
 
 
 /// Gets the base custom assertion failure function to be used by Recast.
 /// Gets the base custom assertion failure function to be used by Recast.
 rcAssertFailFunc* rcAssertFailGetCustom();
 rcAssertFailFunc* rcAssertFailGetCustom();
@@ -47,8 +44,8 @@ rcAssertFailFunc* rcAssertFailGetCustom();
 #	define rcAssert(expression) \
 #	define rcAssert(expression) \
 		{ \
 		{ \
 			rcAssertFailFunc* failFunc = rcAssertFailGetCustom(); \
 			rcAssertFailFunc* failFunc = rcAssertFailGetCustom(); \
-			if(failFunc == NULL) { assert(expression); } \
-			else if(!(expression)) { (*failFunc)(#expression, __FILE__, __LINE__); } \
+			if (failFunc == NULL) { assert(expression); } \
+			else if (!(expression)) { (*failFunc)(#expression, __FILE__, __LINE__); } \
 		}
 		}
 
 
 #endif
 #endif

+ 287 - 325
thirdparty/recastnavigation/Recast/Source/Recast.cpp

@@ -16,81 +16,65 @@
 // 3. This notice may not be removed or altered from any source distribution.
 // 3. This notice may not be removed or altered from any source distribution.
 //
 //
 
 
-#include <float.h>
-#define _USE_MATH_DEFINES
+#include "Recast.h"
+#include "RecastAlloc.h"
+#include "RecastAssert.h"
+
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
-#include <stdlib.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdarg.h>
-#include "Recast.h"
-#include "RecastAlloc.h"
-#include "RecastAssert.h"
 
 
 namespace
 namespace
 {
 {
 /// Allocates and constructs an object of the given type, returning a pointer.
 /// Allocates and constructs an object of the given type, returning a pointer.
-/// TODO: Support constructor args.
-/// @param[in]		hint	Hint to the allocator.
-template <typename T>
-T* rcNew(rcAllocHint hint) {
-	T* ptr = (T*)rcAlloc(sizeof(T), hint);
+/// @param[in]		allocLifetime	Allocation lifetime hint
+template<typename T>
+T* rcNew(const rcAllocHint allocLifetime)
+{
+	T* ptr = (T*)rcAlloc(sizeof(T), allocLifetime);
 	::new(rcNewTag(), (void*)ptr) T();
 	::new(rcNewTag(), (void*)ptr) T();
 	return ptr;
 	return ptr;
 }
 }
 
 
 /// Destroys and frees an object allocated with rcNew.
 /// Destroys and frees an object allocated with rcNew.
 /// @param[in]     ptr    The object pointer to delete.
 /// @param[in]     ptr    The object pointer to delete.
-template <typename T>
-void rcDelete(T* ptr) {
-	if (ptr) {
+template<typename T>
+void rcDelete(T* ptr)
+{
+	if (ptr)
+	{
 		ptr->~T();
 		ptr->~T();
 		rcFree((void*)ptr);
 		rcFree((void*)ptr);
 	}
 	}
 }
 }
-}  // namespace
-
+} // anonymous namespace
 
 
 float rcSqrt(float x)
 float rcSqrt(float x)
 {
 {
 	return sqrtf(x);
 	return sqrtf(x);
 }
 }
 
 
-/// @class rcContext
-/// @par
-///
-/// This class does not provide logging or timer functionality on its 
-/// own.  Both must be provided by a concrete implementation 
-/// by overriding the protected member functions.  Also, this class does not 
-/// provide an interface for extracting log messages. (Only adding them.) 
-/// So concrete implementations must provide one.
-///
-/// If no logging or timers are required, just pass an instance of this 
-/// class through the Recast build process.
-///
-
-/// @par
-///
-/// Example:
-/// @code
-/// // Where ctx is an instance of rcContext and filepath is a char array.
-/// ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath);
-/// @endcode
 void rcContext::log(const rcLogCategory category, const char* format, ...)
 void rcContext::log(const rcLogCategory category, const char* format, ...)
 {
 {
 	if (!m_logEnabled)
 	if (!m_logEnabled)
+	{
 		return;
 		return;
+	}
 	static const int MSG_SIZE = 512;
 	static const int MSG_SIZE = 512;
 	char msg[MSG_SIZE];
 	char msg[MSG_SIZE];
-	va_list ap;
-	va_start(ap, format);
-	int len = vsnprintf(msg, MSG_SIZE, format, ap);
+	va_list argList;
+	va_start(argList, format);
+	int len = vsnprintf(msg, MSG_SIZE, format, argList);
 	if (len >= MSG_SIZE)
 	if (len >= MSG_SIZE)
 	{
 	{
-		len = MSG_SIZE-1;
-		msg[MSG_SIZE-1] = '\0';
+		len = MSG_SIZE - 1;
+		msg[MSG_SIZE - 1] = '\0';
+
+		const char* errorMessage = "Log message was truncated";
+		doLog(RC_LOG_ERROR, errorMessage, (int)strlen(errorMessage));
 	}
 	}
-	va_end(ap);
+	va_end(argList);
 	doLog(category, msg, len);
 	doLog(category, msg, len);
 }
 }
 
 
@@ -103,16 +87,22 @@ rcHeightfield* rcAllocHeightfield()
 {
 {
 	return rcNew<rcHeightfield>(RC_ALLOC_PERM);
 	return rcNew<rcHeightfield>(RC_ALLOC_PERM);
 }
 }
+
+void rcFreeHeightField(rcHeightfield* heightfield)
+{
+	rcDelete(heightfield);
+}
+
 rcHeightfield::rcHeightfield()
 rcHeightfield::rcHeightfield()
-	: width()
-	, height()
-	, bmin()
-	, bmax()
-	, cs()
-	, ch()
-	, spans()
-	, pools()
-	, freelist()
+: width()
+, height()
+, bmin()
+, bmax()
+, cs()
+, ch()
+, spans()
+, pools()
+, freelist()
 {
 {
 }
 }
 
 
@@ -129,40 +119,36 @@ rcHeightfield::~rcHeightfield()
 	}
 	}
 }
 }
 
 
-void rcFreeHeightField(rcHeightfield* hf)
-{
-	rcDelete(hf);
-}
-
 rcCompactHeightfield* rcAllocCompactHeightfield()
 rcCompactHeightfield* rcAllocCompactHeightfield()
 {
 {
 	return rcNew<rcCompactHeightfield>(RC_ALLOC_PERM);
 	return rcNew<rcCompactHeightfield>(RC_ALLOC_PERM);
 }
 }
 
 
-void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
+void rcFreeCompactHeightfield(rcCompactHeightfield* compactHeightfield)
 {
 {
-	rcDelete(chf);
+	rcDelete(compactHeightfield);
 }
 }
 
 
 rcCompactHeightfield::rcCompactHeightfield()
 rcCompactHeightfield::rcCompactHeightfield()
-	: width(),
-	height(),
-	spanCount(),
-	walkableHeight(),
-	walkableClimb(),
-	borderSize(),
-	maxDistance(),
-	maxRegions(),
-	bmin(),
-	bmax(),
-	cs(),
-	ch(),
-	cells(),
-	spans(),
-	dist(),
-	areas()
+: width()
+, height()
+, spanCount()
+, walkableHeight()
+, walkableClimb()
+, borderSize()
+, maxDistance()
+, maxRegions()
+, bmin()
+, bmax()
+, cs()
+, ch()
+, cells()
+, spans()
+, dist()
+, areas()
 {
 {
 }
 }
+
 rcCompactHeightfield::~rcCompactHeightfield()
 rcCompactHeightfield::~rcCompactHeightfield()
 {
 {
 	rcFree(cells);
 	rcFree(cells);
@@ -175,13 +161,18 @@ rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
 {
 {
 	return rcNew<rcHeightfieldLayerSet>(RC_ALLOC_PERM);
 	return rcNew<rcHeightfieldLayerSet>(RC_ALLOC_PERM);
 }
 }
-void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
+
+void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* layerSet)
 {
 {
-	rcDelete(lset);
+	rcDelete(layerSet);
 }
 }
 
 
 rcHeightfieldLayerSet::rcHeightfieldLayerSet()
 rcHeightfieldLayerSet::rcHeightfieldLayerSet()
-	: layers(),	nlayers() {}
+: layers()
+, nlayers()
+{
+}
+
 rcHeightfieldLayerSet::~rcHeightfieldLayerSet()
 rcHeightfieldLayerSet::~rcHeightfieldLayerSet()
 {
 {
 	for (int i = 0; i < nlayers; ++i)
 	for (int i = 0; i < nlayers; ++i)
@@ -198,22 +189,26 @@ rcContourSet* rcAllocContourSet()
 {
 {
 	return rcNew<rcContourSet>(RC_ALLOC_PERM);
 	return rcNew<rcContourSet>(RC_ALLOC_PERM);
 }
 }
-void rcFreeContourSet(rcContourSet* cset)
+
+void rcFreeContourSet(rcContourSet* contourSet)
 {
 {
-	rcDelete(cset);
+	rcDelete(contourSet);
 }
 }
 
 
 rcContourSet::rcContourSet()
 rcContourSet::rcContourSet()
-	: conts(),
-	nconts(),
-	bmin(),
-	bmax(),
-	cs(),
-	ch(),
-	width(),
-	height(),
-	borderSize(),
-	maxError() {}
+: conts()
+, nconts()
+, bmin()
+, bmax()
+, cs()
+, ch()
+, width()
+, height()
+, borderSize()
+, maxError()
+{
+}
+
 rcContourSet::~rcContourSet()
 rcContourSet::~rcContourSet()
 {
 {
 	for (int i = 0; i < nconts; ++i)
 	for (int i = 0; i < nconts; ++i)
@@ -224,32 +219,34 @@ rcContourSet::~rcContourSet()
 	rcFree(conts);
 	rcFree(conts);
 }
 }
 
 
-
 rcPolyMesh* rcAllocPolyMesh()
 rcPolyMesh* rcAllocPolyMesh()
 {
 {
 	return rcNew<rcPolyMesh>(RC_ALLOC_PERM);
 	return rcNew<rcPolyMesh>(RC_ALLOC_PERM);
 }
 }
-void rcFreePolyMesh(rcPolyMesh* pmesh)
+
+void rcFreePolyMesh(rcPolyMesh* polyMesh)
 {
 {
-	rcDelete(pmesh);
+	rcDelete(polyMesh);
 }
 }
 
 
 rcPolyMesh::rcPolyMesh()
 rcPolyMesh::rcPolyMesh()
-	: verts(),
-	polys(),
-	regs(),
-	flags(),
-	areas(),
-	nverts(),
-	npolys(),
-	maxpolys(),
-	nvp(),
-	bmin(),
-	bmax(),
-	cs(),
-	ch(),
-	borderSize(),
-	maxEdgeError() {}
+: verts()
+, polys()
+, regs()
+, flags()
+, areas()
+, nverts()
+, npolys()
+, maxpolys()
+, nvp()
+, bmin()
+, bmax()
+, cs()
+, ch()
+, borderSize()
+, maxEdgeError()
+{
+}
 
 
 rcPolyMesh::~rcPolyMesh()
 rcPolyMesh::~rcPolyMesh()
 {
 {
@@ -262,319 +259,284 @@ rcPolyMesh::~rcPolyMesh()
 
 
 rcPolyMeshDetail* rcAllocPolyMeshDetail()
 rcPolyMeshDetail* rcAllocPolyMeshDetail()
 {
 {
-	rcPolyMeshDetail* dmesh = (rcPolyMeshDetail*)rcAlloc(sizeof(rcPolyMeshDetail), RC_ALLOC_PERM);
-	memset(dmesh, 0, sizeof(rcPolyMeshDetail));
-	return dmesh;
+	return rcNew<rcPolyMeshDetail>(RC_ALLOC_PERM);
 }
 }
 
 
-void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
+void rcFreePolyMeshDetail(rcPolyMeshDetail* detailMesh)
+{
+	if (detailMesh == NULL)
+	{
+		return;
+	}
+	rcFree(detailMesh->meshes);
+	rcFree(detailMesh->verts);
+	rcFree(detailMesh->tris);
+	rcFree(detailMesh);
+}
+
+rcPolyMeshDetail::rcPolyMeshDetail()
+: meshes()
+, verts()
+, tris()
+, nmeshes()
+, nverts()
+, ntris()
 {
 {
-	if (!dmesh) return;
-	rcFree(dmesh->meshes);
-	rcFree(dmesh->verts);
-	rcFree(dmesh->tris);
-	rcFree(dmesh);
 }
 }
 
 
-void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
+void rcCalcBounds(const float* verts, int numVerts, float* minBounds, float* maxBounds)
 {
 {
 	// Calculate bounding box.
 	// Calculate bounding box.
-	rcVcopy(bmin, verts);
-	rcVcopy(bmax, verts);
-	for (int i = 1; i < nv; ++i)
+	rcVcopy(minBounds, verts);
+	rcVcopy(maxBounds, verts);
+	for (int i = 1; i < numVerts; ++i)
 	{
 	{
-		const float* v = &verts[i*3];
-		rcVmin(bmin, v);
-		rcVmax(bmax, v);
+		const float* v = &verts[i * 3];
+		rcVmin(minBounds, v);
+		rcVmax(maxBounds, v);
 	}
 	}
 }
 }
 
 
-void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h)
+void rcCalcGridSize(const float* minBounds, const float* maxBounds, const float cellSize, int* sizeX, int* sizeZ)
 {
 {
-	*w = (int)((bmax[0] - bmin[0])/cs+0.5f);
-	*h = (int)((bmax[2] - bmin[2])/cs+0.5f);
+	*sizeX = (int)((maxBounds[0] - minBounds[0]) / cellSize + 0.5f);
+	*sizeZ = (int)((maxBounds[2] - minBounds[2]) / cellSize + 0.5f);
 }
 }
 
 
-/// @par
-///
-/// See the #rcConfig documentation for more information on the configuration parameters.
-/// 
-/// @see rcAllocHeightfield, rcHeightfield 
-bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height,
-						 const float* bmin, const float* bmax,
-						 float cs, float ch)
+bool rcCreateHeightfield(rcContext* context, rcHeightfield& heightfield, int sizeX, int sizeZ,
+                         const float* minBounds, const float* maxBounds,
+                         float cellSize, float cellHeight)
 {
 {
-	rcIgnoreUnused(ctx);
-	
-	hf.width = width;
-	hf.height = height;
-	rcVcopy(hf.bmin, bmin);
-	rcVcopy(hf.bmax, bmax);
-	hf.cs = cs;
-	hf.ch = ch;
-	hf.spans = (rcSpan**)rcAlloc(sizeof(rcSpan*)*hf.width*hf.height, RC_ALLOC_PERM);
-	if (!hf.spans)
+	rcIgnoreUnused(context);
+
+	heightfield.width = sizeX;
+	heightfield.height = sizeZ;
+	rcVcopy(heightfield.bmin, minBounds);
+	rcVcopy(heightfield.bmax, maxBounds);
+	heightfield.cs = cellSize;
+	heightfield.ch = cellHeight;
+	heightfield.spans = (rcSpan**)rcAlloc(sizeof(rcSpan*) * heightfield.width * heightfield.height, RC_ALLOC_PERM);
+	if (!heightfield.spans)
+	{
 		return false;
 		return false;
-	memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height);
+	}
+	memset(heightfield.spans, 0, sizeof(rcSpan*) * heightfield.width * heightfield.height);
 	return true;
 	return true;
 }
 }
 
 
-static void calcTriNormal(const float* v0, const float* v1, const float* v2, float* norm)
+static void calcTriNormal(const float* v0, const float* v1, const float* v2, float* faceNormal)
 {
 {
 	float e0[3], e1[3];
 	float e0[3], e1[3];
 	rcVsub(e0, v1, v0);
 	rcVsub(e0, v1, v0);
 	rcVsub(e1, v2, v0);
 	rcVsub(e1, v2, v0);
-	rcVcross(norm, e0, e1);
-	rcVnormalize(norm);
-}
-
-/// @par
-///
-/// Only sets the area id's for the walkable triangles.  Does not alter the
-/// area id's for unwalkable triangles.
-/// 
-/// See the #rcConfig documentation for more information on the configuration parameters.
-/// 
-/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
-void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
-							 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);
+	rcVcross(faceNormal, e0, e1);
+	rcVnormalize(faceNormal);
+}
+
+void rcMarkWalkableTriangles(rcContext* context, const float walkableSlopeAngle,
+                             const float* verts, const int numVerts,
+                             const int* tris, const int numTris,
+                             unsigned char* triAreaIDs)
+{
+	rcIgnoreUnused(context);
+	rcIgnoreUnused(numVerts);
+
+	const float walkableThr = cosf(walkableSlopeAngle / 180.0f * RC_PI);
 
 
 	float norm[3];
 	float norm[3];
-	
-	for (int i = 0; i < nt; ++i)
+
+	for (int i = 0; i < numTris; ++i)
 	{
 	{
-		const int* tri = &tris[i*3];
-		calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
+		const int* tri = &tris[i * 3];
+		calcTriNormal(&verts[tri[0] * 3], &verts[tri[1] * 3], &verts[tri[2] * 3], norm);
 		// Check if the face is walkable.
 		// Check if the face is walkable.
 		if (norm[1] > walkableThr)
 		if (norm[1] > walkableThr)
-			areas[i] = RC_WALKABLE_AREA;
+		{
+			triAreaIDs[i] = RC_WALKABLE_AREA;
+		}
 	}
 	}
 }
 }
 
 
-/// @par
-///
-/// Only sets the area id's for the unwalkable triangles.  Does not alter the
-/// area id's for walkable triangles.
-/// 
-/// See the #rcConfig documentation for more information on the configuration parameters.
-/// 
-/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
-void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
-								const float* verts, int /*nv*/,
-								const int* tris, int nt,
-								unsigned char* areas)
-{
-	rcIgnoreUnused(ctx);
-	
-	const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
-	
-	float norm[3];
-	
-	for (int i = 0; i < nt; ++i)
+void rcClearUnwalkableTriangles(rcContext* context, const float walkableSlopeAngle,
+                                const float* verts, int numVerts,
+                                const int* tris, int numTris,
+                                unsigned char* triAreaIDs)
+{
+	rcIgnoreUnused(context);
+	rcIgnoreUnused(numVerts);
+
+	// The minimum Y value for a face normal of a triangle with a walkable slope.
+	const float walkableLimitY = cosf(walkableSlopeAngle / 180.0f * RC_PI);
+
+	float faceNormal[3];
+	for (int i = 0; i < numTris; ++i)
 	{
 	{
-		const int* tri = &tris[i*3];
-		calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
+		const int* tri = &tris[i * 3];
+		calcTriNormal(&verts[tri[0] * 3], &verts[tri[1] * 3], &verts[tri[2] * 3], faceNormal);
 		// Check if the face is walkable.
 		// Check if the face is walkable.
-		if (norm[1] <= walkableThr)
-			areas[i] = RC_NULL_AREA;
+		if (faceNormal[1] <= walkableLimitY)
+		{
+			triAreaIDs[i] = RC_NULL_AREA;
+		}
 	}
 	}
 }
 }
 
 
-int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf)
+int rcGetHeightFieldSpanCount(rcContext* context, const rcHeightfield& heightfield)
 {
 {
-	rcIgnoreUnused(ctx);
-	
-	const int w = hf.width;
-	const int h = hf.height;
+	rcIgnoreUnused(context);
+
+	const int numCols = heightfield.width * heightfield.height;
 	int spanCount = 0;
 	int spanCount = 0;
-	for (int y = 0; y < h; ++y)
+	for (int columnIndex = 0; columnIndex < numCols; ++columnIndex)
 	{
 	{
-		for (int x = 0; x < w; ++x)
+		for (rcSpan* span = heightfield.spans[columnIndex]; span != NULL; span = span->next)
 		{
 		{
-			for (rcSpan* s = hf.spans[x + y*w]; s; s = s->next)
+			if (span->area != RC_NULL_AREA)
 			{
 			{
-				if (s->area != RC_NULL_AREA)
-					spanCount++;
+				spanCount++;
 			}
 			}
 		}
 		}
 	}
 	}
 	return spanCount;
 	return spanCount;
 }
 }
 
 
-/// @par
-///
-/// This is just the beginning of the process of fully building a compact heightfield.
-/// Various filters may be applied, then the distance field and regions built.
-/// E.g: #rcBuildDistanceField and #rcBuildRegions
-///
-/// See the #rcConfig documentation for more information on the configuration parameters.
-///
-/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig
-bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
-							   rcHeightfield& hf, rcCompactHeightfield& chf)
+bool rcBuildCompactHeightfield(rcContext* context, const int walkableHeight, const int walkableClimb,
+                               const rcHeightfield& heightfield, rcCompactHeightfield& compactHeightfield)
 {
 {
-	rcAssert(ctx);
-	
-	rcScopedTimer timer(ctx, RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
-	
-	const int w = hf.width;
-	const int h = hf.height;
-	const int spanCount = rcGetHeightFieldSpanCount(ctx, hf);
+	rcAssert(context);
+
+	rcScopedTimer timer(context, RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
+
+	const int xSize = heightfield.width;
+	const int zSize = heightfield.height;
+	const int spanCount = rcGetHeightFieldSpanCount(context, heightfield);
 
 
 	// Fill in header.
 	// Fill in header.
-	chf.width = w;
-	chf.height = h;
-	chf.spanCount = spanCount;
-	chf.walkableHeight = walkableHeight;
-	chf.walkableClimb = walkableClimb;
-	chf.maxRegions = 0;
-	rcVcopy(chf.bmin, hf.bmin);
-	rcVcopy(chf.bmax, hf.bmax);
-	chf.bmax[1] += walkableHeight*hf.ch;
-	chf.cs = hf.cs;
-	chf.ch = hf.ch;
-	chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM);
-	if (!chf.cells)
+	compactHeightfield.width = xSize;
+	compactHeightfield.height = zSize;
+	compactHeightfield.spanCount = spanCount;
+	compactHeightfield.walkableHeight = walkableHeight;
+	compactHeightfield.walkableClimb = walkableClimb;
+	compactHeightfield.maxRegions = 0;
+	rcVcopy(compactHeightfield.bmin, heightfield.bmin);
+	rcVcopy(compactHeightfield.bmax, heightfield.bmax);
+	compactHeightfield.bmax[1] += walkableHeight * heightfield.ch;
+	compactHeightfield.cs = heightfield.cs;
+	compactHeightfield.ch = heightfield.ch;
+	compactHeightfield.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell) * xSize * zSize, RC_ALLOC_PERM);
+	if (!compactHeightfield.cells)
 	{
 	{
-		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h);
+		context->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", xSize * zSize);
 		return false;
 		return false;
 	}
 	}
-	memset(chf.cells, 0, sizeof(rcCompactCell)*w*h);
-	chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM);
-	if (!chf.spans)
+	memset(compactHeightfield.cells, 0, sizeof(rcCompactCell) * xSize * zSize);
+	compactHeightfield.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan) * spanCount, RC_ALLOC_PERM);
+	if (!compactHeightfield.spans)
 	{
 	{
-		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
+		context->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
 		return false;
 		return false;
 	}
 	}
-	memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount);
-	chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM);
-	if (!chf.areas)
+	memset(compactHeightfield.spans, 0, sizeof(rcCompactSpan) * spanCount);
+	compactHeightfield.areas = (unsigned char*)rcAlloc(sizeof(unsigned char) * spanCount, RC_ALLOC_PERM);
+	if (!compactHeightfield.areas)
 	{
 	{
-		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount);
+		context->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount);
 		return false;
 		return false;
 	}
 	}
-	memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount);
-	
+	memset(compactHeightfield.areas, RC_NULL_AREA, sizeof(unsigned char) * spanCount);
+
 	const int MAX_HEIGHT = 0xffff;
 	const int MAX_HEIGHT = 0xffff;
-	
+
 	// Fill in cells and spans.
 	// Fill in cells and spans.
-	int idx = 0;
-	for (int y = 0; y < h; ++y)
+	int currentCellIndex = 0;
+	const int numColumns = xSize * zSize;
+	for (int columnIndex = 0; columnIndex < numColumns; ++columnIndex)
 	{
 	{
-		for (int x = 0; x < w; ++x)
+		const rcSpan* span = heightfield.spans[columnIndex];
+			
+		// If there are no spans at this cell, just leave the data to index=0, count=0.
+		if (span == NULL)
+		{
+			continue;
+		}
+			
+		rcCompactCell& cell = compactHeightfield.cells[columnIndex];
+		cell.index = currentCellIndex;
+		cell.count = 0;
+
+		for (; span != NULL; span = span->next)
 		{
 		{
-			const rcSpan* s = hf.spans[x + y*w];
-			// If there are no spans at this cell, just leave the data to index=0, count=0.
-			if (!s) continue;
-			rcCompactCell& c = chf.cells[x+y*w];
-			c.index = idx;
-			c.count = 0;
-			while (s)
+			if (span->area != RC_NULL_AREA)
 			{
 			{
-				if (s->area != RC_NULL_AREA)
-				{
-					const int bot = (int)s->smax;
-					const int top = s->next ? (int)s->next->smin : MAX_HEIGHT;
-					chf.spans[idx].y = (unsigned short)rcClamp(bot, 0, 0xffff);
-					chf.spans[idx].h = (unsigned char)rcClamp(top - bot, 0, 0xff);
-					chf.areas[idx] = s->area;
-					idx++;
-					c.count++;
-				}
-				s = s->next;
+				const int bot = (int)span->smax;
+				const int top = span->next ? (int)span->next->smin : MAX_HEIGHT;
+				compactHeightfield.spans[currentCellIndex].y = (unsigned short)rcClamp(bot, 0, 0xffff);
+				compactHeightfield.spans[currentCellIndex].h = (unsigned char)rcClamp(top - bot, 0, 0xff);
+				compactHeightfield.areas[currentCellIndex] = span->area;
+				currentCellIndex++;
+				cell.count++;
 			}
 			}
 		}
 		}
 	}
 	}
-
+	
 	// Find neighbour connections.
 	// Find neighbour connections.
-	const int MAX_LAYERS = RC_NOT_CONNECTED-1;
-	int tooHighNeighbour = 0;
-	for (int y = 0; y < h; ++y)
+	const int MAX_LAYERS = RC_NOT_CONNECTED - 1;
+	int maxLayerIndex = 0;
+	const int zStride = xSize; // for readability
+	for (int z = 0; z < zSize; ++z)
 	{
 	{
-		for (int x = 0; x < w; ++x)
+		for (int x = 0; x < xSize; ++x)
 		{
 		{
-			const rcCompactCell& c = chf.cells[x+y*w];
-			for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
+			const rcCompactCell& cell = compactHeightfield.cells[x + z * zStride];
+			for (int i = (int)cell.index, ni = (int)(cell.index + cell.count); i < ni; ++i)
 			{
 			{
-				rcCompactSpan& s = chf.spans[i];
-				
+				rcCompactSpan& span = compactHeightfield.spans[i];
+
 				for (int dir = 0; dir < 4; ++dir)
 				for (int dir = 0; dir < 4; ++dir)
 				{
 				{
-					rcSetCon(s, dir, RC_NOT_CONNECTED);
-					const int nx = x + rcGetDirOffsetX(dir);
-					const int ny = y + rcGetDirOffsetY(dir);
+					rcSetCon(span, dir, RC_NOT_CONNECTED);
+					const int neighborX = x + rcGetDirOffsetX(dir);
+					const int neighborZ = z + rcGetDirOffsetY(dir);
 					// First check that the neighbour cell is in bounds.
 					// First check that the neighbour cell is in bounds.
-					if (nx < 0 || ny < 0 || nx >= w || ny >= h)
+					if (neighborX < 0 || neighborZ < 0 || neighborX >= xSize || neighborZ >= zSize)
+					{
 						continue;
 						continue;
-						
+					}
+
 					// Iterate over all neighbour spans and check if any of the is
 					// Iterate over all neighbour spans and check if any of the is
 					// accessible from current cell.
 					// accessible from current cell.
-					const rcCompactCell& nc = chf.cells[nx+ny*w];
-					for (int k = (int)nc.index, nk = (int)(nc.index+nc.count); k < nk; ++k)
+					const rcCompactCell& neighborCell = compactHeightfield.cells[neighborX + neighborZ * zStride];
+					for (int k = (int)neighborCell.index, nk = (int)(neighborCell.index + neighborCell.count); k < nk; ++k)
 					{
 					{
-						const rcCompactSpan& ns = chf.spans[k];
-						const int bot = rcMax(s.y, ns.y);
-						const int top = rcMin(s.y+s.h, ns.y+ns.h);
+						const rcCompactSpan& neighborSpan = compactHeightfield.spans[k];
+						const int bot = rcMax(span.y, neighborSpan.y);
+						const int top = rcMin(span.y + span.h, neighborSpan.y + neighborSpan.h);
 
 
 						// Check that the gap between the spans is walkable,
 						// Check that the gap between the spans is walkable,
 						// and that the climb height between the gaps is not too high.
 						// and that the climb height between the gaps is not too high.
-						if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb)
+						if ((top - bot) >= walkableHeight && rcAbs((int)neighborSpan.y - (int)span.y) <= walkableClimb)
 						{
 						{
 							// Mark direction as walkable.
 							// Mark direction as walkable.
-							const int lidx = k - (int)nc.index;
-							if (lidx < 0 || lidx > MAX_LAYERS)
+							const int layerIndex = k - (int)neighborCell.index;
+							if (layerIndex < 0 || layerIndex > MAX_LAYERS)
 							{
 							{
-								tooHighNeighbour = rcMax(tooHighNeighbour, lidx);
+								maxLayerIndex = rcMax(maxLayerIndex, layerIndex);
 								continue;
 								continue;
 							}
 							}
-							rcSetCon(s, dir, lidx);
+							rcSetCon(span, dir, layerIndex);
 							break;
 							break;
 						}
 						}
 					}
 					}
-					
 				}
 				}
 			}
 			}
 		}
 		}
 	}
 	}
-	
-	if (tooHighNeighbour > MAX_LAYERS)
-	{
-		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)",
-				 tooHighNeighbour, MAX_LAYERS);
-	}
-	
-	return true;
-}
 
 
-/*
-static int getHeightfieldMemoryUsage(const rcHeightfield& hf)
-{
-	int size = 0;
-	size += sizeof(hf);
-	size += hf.width * hf.height * sizeof(rcSpan*);
-	
-	rcSpanPool* pool = hf.pools;
-	while (pool)
+	if (maxLayerIndex > MAX_LAYERS)
 	{
 	{
-		size += (sizeof(rcSpanPool) - sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL;
-		pool = pool->next;
+		context->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)",
+		         maxLayerIndex, MAX_LAYERS);
 	}
 	}
-	return size;
-}
 
 
-static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf)
-{
-	int size = 0;
-	size += sizeof(rcCompactHeightfield);
-	size += sizeof(rcCompactSpan) * chf.spanCount;
-	size += sizeof(rcCompactCell) * chf.width * chf.height;
-	return size;
+	return true;
 }
 }
-*/

+ 5 - 14
thirdparty/recastnavigation/Recast/Source/RecastAlloc.cpp

@@ -16,12 +16,9 @@
 // 3. This notice may not be removed or altered from any source distribution.
 // 3. This notice may not be removed or altered from any source distribution.
 //
 //
 
 
-#include <stdlib.h>
-#include <string.h>
 #include "RecastAlloc.h"
 #include "RecastAlloc.h"
-#include "RecastAssert.h"
 
 
-static void *rcAllocDefault(size_t size, rcAllocHint)
+static void* rcAllocDefault(size_t size, rcAllocHint)
 {
 {
 	return malloc(size);
 	return malloc(size);
 }
 }
@@ -34,27 +31,21 @@ static void rcFreeDefault(void *ptr)
 static rcAllocFunc* sRecastAllocFunc = rcAllocDefault;
 static rcAllocFunc* sRecastAllocFunc = rcAllocDefault;
 static rcFreeFunc* sRecastFreeFunc = rcFreeDefault;
 static rcFreeFunc* sRecastFreeFunc = rcFreeDefault;
 
 
-/// @see rcAlloc, rcFree
-void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc)
+void rcAllocSetCustom(rcAllocFunc* allocFunc, rcFreeFunc* freeFunc)
 {
 {
 	sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault;
 	sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault;
 	sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault;
 	sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault;
 }
 }
 
 
-/// @see rcAllocSetCustom
 void* rcAlloc(size_t size, rcAllocHint hint)
 void* rcAlloc(size_t size, rcAllocHint hint)
 {
 {
 	return sRecastAllocFunc(size, hint);
 	return sRecastAllocFunc(size, hint);
 }
 }
 
 
-/// @par
-///
-/// @warning This function leaves the value of @p ptr unchanged.  So it still
-/// points to the same (now invalid) location, and not to null.
-/// 
-/// @see rcAllocSetCustom
 void rcFree(void* ptr)
 void rcFree(void* ptr)
 {
 {
-	if (ptr)
+	if (ptr != NULL)
+	{
 		sRecastFreeFunc(ptr);
 		sRecastFreeFunc(ptr);
+	}
 }
 }

+ 0 - 1
thirdparty/recastnavigation/Recast/Source/RecastArea.cpp

@@ -17,7 +17,6 @@
 //
 //
 
 
 #include <float.h>
 #include <float.h>
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>

+ 1 - 1
thirdparty/recastnavigation/Recast/Source/RecastAssert.cpp

@@ -22,7 +22,7 @@
 
 
 static rcAssertFailFunc* sRecastAssertFailFunc = 0;
 static rcAssertFailFunc* sRecastAssertFailFunc = 0;
 
 
-void rcAssertFailSetCustom(rcAssertFailFunc *assertFailFunc)
+void rcAssertFailSetCustom(rcAssertFailFunc* assertFailFunc)
 {
 {
 	sRecastAssertFailFunc = assertFailFunc;
 	sRecastAssertFailFunc = assertFailFunc;
 }
 }

+ 5 - 6
thirdparty/recastnavigation/Recast/Source/RecastContour.cpp

@@ -16,7 +16,6 @@
 // 3. This notice may not be removed or altered from any source distribution.
 // 3. This notice may not be removed or altered from any source distribution.
 //
 //
 
 
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -102,7 +101,7 @@ static int getCornerHeight(int x, int y, int i, int dir,
 }
 }
 
 
 static void walkContour(int x, int y, int i,
 static void walkContour(int x, int y, int i,
-						rcCompactHeightfield& chf,
+						const rcCompactHeightfield& chf,
 						unsigned char* flags, rcIntArray& points)
 						unsigned char* flags, rcIntArray& points)
 {
 {
 	// Choose the first non-connected edge
 	// Choose the first non-connected edge
@@ -542,7 +541,7 @@ static bool vequal(const int* a, const int* b)
 	return a[0] == b[0] && a[2] == b[2];
 	return a[0] == b[0] && a[2] == b[2];
 }
 }
 
 
-static bool intersectSegCountour(const int* d0, const int* d1, int i, int n, const int* verts)
+static bool intersectSegContour(const int* d0, const int* d1, int i, int n, const int* verts)
 {
 {
 	// For each edge (k,k+1) of P
 	// For each edge (k,k+1) of P
 	for (int k = 0; k < n; k++)
 	for (int k = 0; k < n; k++)
@@ -778,9 +777,9 @@ static void mergeRegionHoles(rcContext* ctx, rcContourRegion& region)
 			for (int j = 0; j < ndiags; j++)
 			for (int j = 0; j < ndiags; j++)
 			{
 			{
 				const int* pt = &outline->verts[diags[j].vert*4];
 				const int* pt = &outline->verts[diags[j].vert*4];
-				bool intersect = intersectSegCountour(pt, corner, diags[i].vert, outline->nverts, outline->verts);
+				bool intersect = intersectSegContour(pt, corner, diags[i].vert, outline->nverts, outline->verts);
 				for (int k = i; k < region.nholes && !intersect; k++)
 				for (int k = i; k < region.nholes && !intersect; k++)
-					intersect |= intersectSegCountour(pt, corner, -1, region.holes[k].contour->nverts, region.holes[k].contour->verts);
+					intersect |= intersectSegContour(pt, corner, -1, region.holes[k].contour->nverts, region.holes[k].contour->verts);
 				if (!intersect)
 				if (!intersect)
 				{
 				{
 					index = diags[j].vert;
 					index = diags[j].vert;
@@ -821,7 +820,7 @@ static void mergeRegionHoles(rcContext* ctx, rcContourRegion& region)
 /// See the #rcConfig documentation for more information on the configuration parameters.
 /// See the #rcConfig documentation for more information on the configuration parameters.
 ///
 ///
 /// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
 /// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
-bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
+bool rcBuildContours(rcContext* ctx, const rcCompactHeightfield& chf,
 					 const float maxError, const int maxEdgeLen,
 					 const float maxError, const int maxEdgeLen,
 					 rcContourSet& cset, const int buildFlags)
 					 rcContourSet& cset, const int buildFlags)
 {
 {

+ 88 - 106
thirdparty/recastnavigation/Recast/Source/RecastFilter.cpp

@@ -16,186 +16,168 @@
 // 3. This notice may not be removed or altered from any source distribution.
 // 3. This notice may not be removed or altered from any source distribution.
 //
 //
 
 
-#define _USE_MATH_DEFINES
-#include <math.h>
-#include <stdio.h>
 #include "Recast.h"
 #include "Recast.h"
 #include "RecastAssert.h"
 #include "RecastAssert.h"
 
 
-/// @par
-///
-/// Allows the formation of walkable regions that will flow over low lying 
-/// objects such as curbs, and up structures such as stairways. 
-/// 
-/// Two neighboring spans are walkable if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt>
-/// 
-/// @warning Will override the effect of #rcFilterLedgeSpans.  So if both filters are used, call
-/// #rcFilterLedgeSpans after calling this filter. 
-///
-/// @see rcHeightfield, rcConfig
-void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid)
+#include <stdlib.h>
+
+void rcFilterLowHangingWalkableObstacles(rcContext* context, const int walkableClimb, rcHeightfield& heightfield)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context);
 
 
-	rcScopedTimer timer(ctx, RC_TIMER_FILTER_LOW_OBSTACLES);
-	
-	const int w = solid.width;
-	const int h = solid.height;
-	
-	for (int y = 0; y < h; ++y)
+	rcScopedTimer timer(context, RC_TIMER_FILTER_LOW_OBSTACLES);
+
+	const int xSize = heightfield.width;
+	const int zSize = heightfield.height;
+
+	for (int z = 0; z < zSize; ++z)
 	{
 	{
-		for (int x = 0; x < w; ++x)
+		for (int x = 0; x < xSize; ++x)
 		{
 		{
-			rcSpan* ps = 0;
-			bool previousWalkable = false;
+			rcSpan* previousSpan = NULL;
+			bool previousWasWalkable = false;
 			unsigned char previousArea = RC_NULL_AREA;
 			unsigned char previousArea = RC_NULL_AREA;
-			
-			for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next)
+
+			for (rcSpan* span = heightfield.spans[x + z * xSize]; span != NULL; previousSpan = span, span = span->next)
 			{
 			{
-				const bool walkable = s->area != RC_NULL_AREA;
+				const bool walkable = span->area != RC_NULL_AREA;
 				// If current span is not walkable, but there is walkable
 				// If current span is not walkable, but there is walkable
 				// span just below it, mark the span above it walkable too.
 				// span just below it, mark the span above it walkable too.
-				if (!walkable && previousWalkable)
+				if (!walkable && previousWasWalkable)
 				{
 				{
-					if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb)
-						s->area = previousArea;
+					if (rcAbs((int)span->smax - (int)previousSpan->smax) <= walkableClimb)
+					{
+						span->area = previousArea;
+					}
 				}
 				}
 				// Copy walkable flag so that it cannot propagate
 				// Copy walkable flag so that it cannot propagate
 				// past multiple non-walkable objects.
 				// past multiple non-walkable objects.
-				previousWalkable = walkable;
-				previousArea = s->area;
+				previousWasWalkable = walkable;
+				previousArea = span->area;
 			}
 			}
 		}
 		}
 	}
 	}
 }
 }
 
 
-/// @par
-///
-/// A ledge is a span with one or more neighbors whose maximum is further away than @p walkableClimb
-/// from the current span's maximum.
-/// This method removes the impact of the overestimation of conservative voxelization 
-/// so the resulting mesh will not have regions hanging in the air over ledges.
-/// 
-/// A span is a ledge if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
-/// 
-/// @see rcHeightfield, rcConfig
-void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb,
-						rcHeightfield& solid)
+void rcFilterLedgeSpans(rcContext* context, const int walkableHeight, const int walkableClimb,
+                        rcHeightfield& heightfield)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context);
 	
 	
-	rcScopedTimer timer(ctx, RC_TIMER_FILTER_BORDER);
+	rcScopedTimer timer(context, RC_TIMER_FILTER_BORDER);
 
 
-	const int w = solid.width;
-	const int h = solid.height;
-	const int MAX_HEIGHT = 0xffff;
+	const int xSize = heightfield.width;
+	const int zSize = heightfield.height;
+	const int MAX_HEIGHT = 0xffff; // TODO (graham): Move this to a more visible constant and update usages.
 	
 	
 	// Mark border spans.
 	// Mark border spans.
-	for (int y = 0; y < h; ++y)
+	for (int z = 0; z < zSize; ++z)
 	{
 	{
-		for (int x = 0; x < w; ++x)
+		for (int x = 0; x < xSize; ++x)
 		{
 		{
-			for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next)
+			for (rcSpan* span = heightfield.spans[x + z * xSize]; span; span = span->next)
 			{
 			{
 				// Skip non walkable spans.
 				// Skip non walkable spans.
-				if (s->area == RC_NULL_AREA)
+				if (span->area == RC_NULL_AREA)
+				{
 					continue;
 					continue;
-				
-				const int bot = (int)(s->smax);
-				const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT;
-				
+				}
+
+				const int bot = (int)(span->smax);
+				const int top = span->next ? (int)(span->next->smin) : MAX_HEIGHT;
+
 				// Find neighbours minimum height.
 				// Find neighbours minimum height.
-				int minh = MAX_HEIGHT;
+				int minNeighborHeight = MAX_HEIGHT;
 
 
 				// Min and max height of accessible neighbours.
 				// Min and max height of accessible neighbours.
-				int asmin = s->smax;
-				int asmax = s->smax;
+				int accessibleNeighborMinHeight = span->smax;
+				int accessibleNeighborMaxHeight = span->smax;
 
 
-				for (int dir = 0; dir < 4; ++dir)
+				for (int direction = 0; direction < 4; ++direction)
 				{
 				{
-					int dx = x + rcGetDirOffsetX(dir);
-					int dy = y + rcGetDirOffsetY(dir);
+					int dx = x + rcGetDirOffsetX(direction);
+					int dy = z + rcGetDirOffsetY(direction);
 					// Skip neighbours which are out of bounds.
 					// Skip neighbours which are out of bounds.
-					if (dx < 0 || dy < 0 || dx >= w || dy >= h)
+					if (dx < 0 || dy < 0 || dx >= xSize || dy >= zSize)
 					{
 					{
-						minh = rcMin(minh, -walkableClimb - bot);
+						minNeighborHeight = rcMin(minNeighborHeight, -walkableClimb - bot);
 						continue;
 						continue;
 					}
 					}
 
 
 					// From minus infinity to the first span.
 					// From minus infinity to the first span.
-					rcSpan* ns = solid.spans[dx + dy*w];
-					int nbot = -walkableClimb;
-					int ntop = ns ? (int)ns->smin : MAX_HEIGHT;
-					// Skip neightbour if the gap between the spans is too small.
-					if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
-						minh = rcMin(minh, nbot - bot);
+					const rcSpan* neighborSpan = heightfield.spans[dx + dy * xSize];
+					int neighborBot = -walkableClimb;
+					int neighborTop = neighborSpan ? (int)neighborSpan->smin : MAX_HEIGHT;
 					
 					
+					// Skip neighbour if the gap between the spans is too small.
+					if (rcMin(top, neighborTop) - rcMax(bot, neighborBot) > walkableHeight)
+					{
+						minNeighborHeight = rcMin(minNeighborHeight, neighborBot - bot);
+					}
+
 					// Rest of the spans.
 					// Rest of the spans.
-					for (ns = solid.spans[dx + dy*w]; ns; ns = ns->next)
+					for (neighborSpan = heightfield.spans[dx + dy * xSize]; neighborSpan; neighborSpan = neighborSpan->next)
 					{
 					{
-						nbot = (int)ns->smax;
-						ntop = ns->next ? (int)ns->next->smin : MAX_HEIGHT;
-						// Skip neightbour if the gap between the spans is too small.
-						if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight)
-						{
-							minh = rcMin(minh, nbot - bot);
+						neighborBot = (int)neighborSpan->smax;
+						neighborTop = neighborSpan->next ? (int)neighborSpan->next->smin : MAX_HEIGHT;
 						
 						
+						// Skip neighbour if the gap between the spans is too small.
+						if (rcMin(top, neighborTop) - rcMax(bot, neighborBot) > walkableHeight)
+						{
+							minNeighborHeight = rcMin(minNeighborHeight, neighborBot - bot);
+
 							// Find min/max accessible neighbour height. 
 							// Find min/max accessible neighbour height. 
-							if (rcAbs(nbot - bot) <= walkableClimb)
+							if (rcAbs(neighborBot - bot) <= walkableClimb)
 							{
 							{
-								if (nbot < asmin) asmin = nbot;
-								if (nbot > asmax) asmax = nbot;
+								if (neighborBot < accessibleNeighborMinHeight) accessibleNeighborMinHeight = neighborBot;
+								if (neighborBot > accessibleNeighborMaxHeight) accessibleNeighborMaxHeight = neighborBot;
 							}
 							}
-							
+
 						}
 						}
 					}
 					}
 				}
 				}
-				
+
 				// The current span is close to a ledge if the drop to any
 				// The current span is close to a ledge if the drop to any
 				// neighbour span is less than the walkableClimb.
 				// neighbour span is less than the walkableClimb.
-				if (minh < -walkableClimb)
+				if (minNeighborHeight < -walkableClimb)
 				{
 				{
-					s->area = RC_NULL_AREA;
+					span->area = RC_NULL_AREA;
 				}
 				}
 				// If the difference between all neighbours is too large,
 				// If the difference between all neighbours is too large,
 				// we are at steep slope, mark the span as ledge.
 				// we are at steep slope, mark the span as ledge.
-				else if ((asmax - asmin) > walkableClimb)
+				else if ((accessibleNeighborMaxHeight - accessibleNeighborMinHeight) > walkableClimb)
 				{
 				{
-					s->area = RC_NULL_AREA;
+					span->area = RC_NULL_AREA;
 				}
 				}
 			}
 			}
 		}
 		}
 	}
 	}
 }
 }
 
 
-/// @par
-///
-/// For this filter, the clearance above the span is the distance from the span's 
-/// maximum to the next higher span's minimum. (Same grid column.)
-/// 
-/// @see rcHeightfield, rcConfig
-void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid)
+void rcFilterWalkableLowHeightSpans(rcContext* context, const int walkableHeight, rcHeightfield& heightfield)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context);
 	
 	
-	rcScopedTimer timer(ctx, RC_TIMER_FILTER_WALKABLE);
+	rcScopedTimer timer(context, RC_TIMER_FILTER_WALKABLE);
 	
 	
-	const int w = solid.width;
-	const int h = solid.height;
+	const int xSize = heightfield.width;
+	const int zSize = heightfield.height;
 	const int MAX_HEIGHT = 0xffff;
 	const int MAX_HEIGHT = 0xffff;
 	
 	
 	// Remove walkable flag from spans which do not have enough
 	// Remove walkable flag from spans which do not have enough
 	// space above them for the agent to stand there.
 	// space above them for the agent to stand there.
-	for (int y = 0; y < h; ++y)
+	for (int z = 0; z < zSize; ++z)
 	{
 	{
-		for (int x = 0; x < w; ++x)
+		for (int x = 0; x < xSize; ++x)
 		{
 		{
-			for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next)
+			for (rcSpan* span = heightfield.spans[x + z*xSize]; span; span = span->next)
 			{
 			{
-				const int bot = (int)(s->smax);
-				const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT;
-				if ((top - bot) <= walkableHeight)
-					s->area = RC_NULL_AREA;
+				const int bot = (int)(span->smax);
+				const int top = span->next ? (int)(span->next->smin) : MAX_HEIGHT;
+				if ((top - bot) < walkableHeight)
+				{
+					span->area = RC_NULL_AREA;
+				}
 			}
 			}
 		}
 		}
 	}
 	}

+ 16 - 4
thirdparty/recastnavigation/Recast/Source/RecastLayers.cpp

@@ -17,7 +17,6 @@
 //
 //
 
 
 #include <float.h>
 #include <float.h>
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -29,8 +28,21 @@
 
 
 // Must be 255 or smaller (not 256) because layer IDs are stored as
 // Must be 255 or smaller (not 256) because layer IDs are stored as
 // a byte where 255 is a special value.
 // a byte where 255 is a special value.
-static const int RC_MAX_LAYERS = 63;
-static const int RC_MAX_NEIS = 16;
+#ifndef RC_MAX_LAYERS_DEF
+#define RC_MAX_LAYERS_DEF 63
+#endif
+
+#if RC_MAX_LAYERS_DEF > 255
+#error RC_MAX_LAYERS_DEF must be 255 or smaller
+#endif
+
+#ifndef RC_MAX_NEIS_DEF
+#define RC_MAX_NEIS_DEF 16
+#endif
+
+// Keep type checking.
+static const int RC_MAX_LAYERS = RC_MAX_LAYERS_DEF;
+static const int RC_MAX_NEIS = RC_MAX_NEIS_DEF;
 
 
 struct rcLayerRegion
 struct rcLayerRegion
 {
 {
@@ -89,7 +101,7 @@ struct rcLayerSweepSpan
 /// See the #rcConfig documentation for more information on the configuration parameters.
 /// See the #rcConfig documentation for more information on the configuration parameters.
 /// 
 /// 
 /// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig
 /// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig
-bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
+bool rcBuildHeightfieldLayers(rcContext* ctx, const rcCompactHeightfield& chf,
 							  const int borderSize, const int walkableHeight,
 							  const int borderSize, const int walkableHeight,
 							  rcHeightfieldLayerSet& lset)
 							  rcHeightfieldLayerSet& lset)
 {
 {

+ 2 - 3
thirdparty/recastnavigation/Recast/Source/RecastMesh.cpp

@@ -16,7 +16,6 @@
 // 3. This notice may not be removed or altered from any source distribution.
 // 3. This notice may not be removed or altered from any source distribution.
 //
 //
 
 
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -35,7 +34,7 @@ static bool buildMeshAdjacency(unsigned short* polys, const int npolys,
 							   const int nverts, const int vertsPerPoly)
 							   const int nverts, const int vertsPerPoly)
 {
 {
 	// Based on code by Eric Lengyel from:
 	// Based on code by Eric Lengyel from:
-	// http://www.terathon.com/code/edges.php
+	// https://web.archive.org/web/20080704083314/http://www.terathon.com/code/edges.php
 	
 	
 	int maxEdgeCount = npolys*vertsPerPoly;
 	int maxEdgeCount = npolys*vertsPerPoly;
 	unsigned short* firstEdge = (unsigned short*)rcAlloc(sizeof(unsigned short)*(nverts + maxEdgeCount), RC_ALLOC_TEMP);
 	unsigned short* firstEdge = (unsigned short*)rcAlloc(sizeof(unsigned short)*(nverts + maxEdgeCount), RC_ALLOC_TEMP);
@@ -987,7 +986,7 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short
 /// limit must be retricted to <= #DT_VERTS_PER_POLYGON.
 /// limit must be retricted to <= #DT_VERTS_PER_POLYGON.
 ///
 ///
 /// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
 /// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
-bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh)
+bool rcBuildPolyMesh(rcContext* ctx, const rcContourSet& cset, const int nvp, rcPolyMesh& mesh)
 {
 {
 	rcAssert(ctx);
 	rcAssert(ctx);
 	
 	

+ 0 - 1
thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp

@@ -17,7 +17,6 @@
 //
 //
 
 
 #include <float.h>
 #include <float.h>
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>

+ 378 - 280
thirdparty/recastnavigation/Recast/Source/RecastRasterization.cpp

@@ -16,377 +16,485 @@
 // 3. This notice may not be removed or altered from any source distribution.
 // 3. This notice may not be removed or altered from any source distribution.
 //
 //
 
 
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdio.h>
 #include "Recast.h"
 #include "Recast.h"
 #include "RecastAlloc.h"
 #include "RecastAlloc.h"
 #include "RecastAssert.h"
 #include "RecastAssert.h"
 
 
-inline bool overlapBounds(const float* amin, const float* amax, const float* bmin, const float* bmax)
+/// Check whether two bounding boxes overlap
+///
+/// @param[in]	aMin	Min axis extents of bounding box A
+/// @param[in]	aMax	Max axis extents of bounding box A
+/// @param[in]	bMin	Min axis extents of bounding box B
+/// @param[in]	bMax	Max axis extents of bounding box B
+/// @returns true if the two bounding boxes overlap.  False otherwise.
+static bool overlapBounds(const float* aMin, const float* aMax, const float* bMin, const float* bMax)
 {
 {
-	bool overlap = true;
-	overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
-	overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
-	overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
-	return overlap;
+	return
+		aMin[0] <= bMax[0] && aMax[0] >= bMin[0] &&
+		aMin[1] <= bMax[1] && aMax[1] >= bMin[1] &&
+		aMin[2] <= bMax[2] && aMax[2] >= bMin[2];
 }
 }
 
 
-inline bool overlapInterval(unsigned short amin, unsigned short amax,
-							unsigned short bmin, unsigned short bmax)
-{
-	if (amax < bmin) return false;
-	if (amin > bmax) return false;
-	return true;
-}
-
-
+/// Allocates a new span in the heightfield.
+/// Use a memory pool and free list to minimize actual allocations.
+/// 
+/// @param[in]	hf		The heightfield
+/// @returns A pointer to the allocated or re-used span memory. 
 static rcSpan* allocSpan(rcHeightfield& hf)
 static rcSpan* allocSpan(rcHeightfield& hf)
 {
 {
-	// If running out of memory, allocate new page and update the freelist.
-	if (!hf.freelist || !hf.freelist->next)
+	// If necessary, allocate new page and update the freelist.
+	if (hf.freelist == NULL || hf.freelist->next == NULL)
 	{
 	{
 		// Create new page.
 		// Create new page.
 		// Allocate memory for the new pool.
 		// Allocate memory for the new pool.
-		rcSpanPool* pool = (rcSpanPool*)rcAlloc(sizeof(rcSpanPool), RC_ALLOC_PERM);
-		if (!pool) return 0;
+		rcSpanPool* spanPool = (rcSpanPool*)rcAlloc(sizeof(rcSpanPool), RC_ALLOC_PERM);
+		if (spanPool == NULL)
+		{
+			return NULL;
+		}
 
 
 		// Add the pool into the list of pools.
 		// Add the pool into the list of pools.
-		pool->next = hf.pools;
-		hf.pools = pool;
-		// Add new items to the free list.
-		rcSpan* freelist = hf.freelist;
-		rcSpan* head = &pool->items[0];
-		rcSpan* it = &pool->items[RC_SPANS_PER_POOL];
+		spanPool->next = hf.pools;
+		hf.pools = spanPool;
+		
+		// Add new spans to the free list.
+		rcSpan* freeList = hf.freelist;
+		rcSpan* head = &spanPool->items[0];
+		rcSpan* it = &spanPool->items[RC_SPANS_PER_POOL];
 		do
 		do
 		{
 		{
 			--it;
 			--it;
-			it->next = freelist;
-			freelist = it;
+			it->next = freeList;
+			freeList = it;
 		}
 		}
 		while (it != head);
 		while (it != head);
 		hf.freelist = it;
 		hf.freelist = it;
 	}
 	}
-	
-	// Pop item from in front of the free list.
-	rcSpan* it = hf.freelist;
+
+	// Pop item from the front of the free list.
+	rcSpan* newSpan = hf.freelist;
 	hf.freelist = hf.freelist->next;
 	hf.freelist = hf.freelist->next;
-	return it;
+	return newSpan;
 }
 }
 
 
-static void freeSpan(rcHeightfield& hf, rcSpan* ptr)
+/// Releases the memory used by the span back to the heightfield, so it can be re-used for new spans.
+/// @param[in]	hf		The heightfield.
+/// @param[in]	span	A pointer to the span to free
+static void freeSpan(rcHeightfield& hf, rcSpan* span)
 {
 {
-	if (!ptr) return;
-	// Add the node in front of the free list.
-	ptr->next = hf.freelist;
-	hf.freelist = ptr;
+	if (span == NULL)
+	{
+		return;
+	}
+	// Add the span to the front of the free list.
+	span->next = hf.freelist;
+	hf.freelist = span;
 }
 }
 
 
-static bool addSpan(rcHeightfield& hf, const int x, const int y,
-					const unsigned short smin, const unsigned short smax,
-					const unsigned char area, const int flagMergeThr)
+/// Adds a span to the heightfield.  If the new span overlaps existing spans,
+/// it will merge the new span with the existing ones.
+///
+/// @param[in]	hf					Heightfield to add spans to
+/// @param[in]	x					The new span's column cell x index
+/// @param[in]	z					The new span's column cell z index
+/// @param[in]	min					The new span's minimum cell index
+/// @param[in]	max					The new span's maximum cell index
+/// @param[in]	areaID				The new span's area type ID
+/// @param[in]	flagMergeThreshold	How close two spans maximum extents need to be to merge area type IDs
+static bool addSpan(rcHeightfield& hf,
+                    const int x, const int z,
+                    const unsigned short min, const unsigned short max,
+                    const unsigned char areaID, const int flagMergeThreshold)
 {
 {
-	
-	int idx = x + y*hf.width;
-	
-	rcSpan* s = allocSpan(hf);
-	if (!s)
-		return false;
-	s->smin = smin;
-	s->smax = smax;
-	s->area = area;
-	s->next = 0;
-	
-	// Empty cell, add the first span.
-	if (!hf.spans[idx])
+	// Create the new span.
+	rcSpan* newSpan = allocSpan(hf);
+	if (newSpan == NULL)
 	{
 	{
-		hf.spans[idx] = s;
-		return true;
+		return false;
 	}
 	}
-	rcSpan* prev = 0;
-	rcSpan* cur = hf.spans[idx];
+	newSpan->smin = min;
+	newSpan->smax = max;
+	newSpan->area = areaID;
+	newSpan->next = NULL;
+	
+	const int columnIndex = x + z * hf.width;
+	rcSpan* previousSpan = NULL;
+	rcSpan* currentSpan = hf.spans[columnIndex];
 	
 	
-	// Insert and merge spans.
-	while (cur)
+	// Insert the new span, possibly merging it with existing spans.
+	while (currentSpan != NULL)
 	{
 	{
-		if (cur->smin > s->smax)
+		if (currentSpan->smin > newSpan->smax)
 		{
 		{
-			// Current span is further than the new span, break.
+			// Current span is completely after the new span, break.
 			break;
 			break;
 		}
 		}
-		else if (cur->smax < s->smin)
+		
+		if (currentSpan->smax < newSpan->smin)
 		{
 		{
-			// Current span is before the new span advance.
-			prev = cur;
-			cur = cur->next;
+			// Current span is completely before the new span.  Keep going.
+			previousSpan = currentSpan;
+			currentSpan = currentSpan->next;
 		}
 		}
 		else
 		else
 		{
 		{
-			// Merge spans.
-			if (cur->smin < s->smin)
-				s->smin = cur->smin;
-			if (cur->smax > s->smax)
-				s->smax = cur->smax;
+			// The new span overlaps with an existing span.  Merge them.
+			if (currentSpan->smin < newSpan->smin)
+			{
+				newSpan->smin = currentSpan->smin;
+			}
+			if (currentSpan->smax > newSpan->smax)
+			{
+				newSpan->smax = currentSpan->smax;
+			}
 			
 			
 			// Merge flags.
 			// Merge flags.
-			if (rcAbs((int)s->smax - (int)cur->smax) <= flagMergeThr)
-				s->area = rcMax(s->area, cur->area);
+			if (rcAbs((int)newSpan->smax - (int)currentSpan->smax) <= flagMergeThreshold)
+			{
+				// Higher area ID numbers indicate higher resolution priority.
+				newSpan->area = rcMax(newSpan->area, currentSpan->area);
+			}
 			
 			
-			// Remove current span.
-			rcSpan* next = cur->next;
-			freeSpan(hf, cur);
-			if (prev)
-				prev->next = next;
+			// Remove the current span since it's now merged with newSpan.
+			// Keep going because there might be other overlapping spans that also need to be merged.
+			rcSpan* next = currentSpan->next;
+			freeSpan(hf, currentSpan);
+			if (previousSpan)
+			{
+				previousSpan->next = next;
+			}
 			else
 			else
-				hf.spans[idx] = next;
-			cur = next;
+			{
+				hf.spans[columnIndex] = next;
+			}
+			currentSpan = next;
 		}
 		}
 	}
 	}
 	
 	
-	// Insert new span.
-	if (prev)
+	// Insert new span after prev
+	if (previousSpan != NULL)
 	{
 	{
-		s->next = prev->next;
-		prev->next = s;
+		newSpan->next = previousSpan->next;
+		previousSpan->next = newSpan;
 	}
 	}
 	else
 	else
 	{
 	{
-		s->next = hf.spans[idx];
-		hf.spans[idx] = s;
+		// This span should go before the others in the list
+		newSpan->next = hf.spans[columnIndex];
+		hf.spans[columnIndex] = newSpan;
 	}
 	}
 
 
 	return true;
 	return true;
 }
 }
 
 
-/// @par
-///
-/// The span addition can be set to favor flags. If the span is merged to
-/// another span and the new @p smax is within @p flagMergeThr units
-/// from the existing span, the span flags are merged.
-///
-/// @see rcHeightfield, rcSpan.
-bool rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y,
-			   const unsigned short smin, const unsigned short smax,
-			   const unsigned char area, const int flagMergeThr)
+bool rcAddSpan(rcContext* context, rcHeightfield& heightfield,
+               const int x, const int z,
+               const unsigned short spanMin, const unsigned short spanMax,
+               const unsigned char areaID, const int flagMergeThreshold)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context);
 
 
-	if (!addSpan(hf, x, y, smin, smax, area, flagMergeThr))
+	if (!addSpan(heightfield, x, z, spanMin, spanMax, areaID, flagMergeThreshold))
 	{
 	{
-		ctx->log(RC_LOG_ERROR, "rcAddSpan: Out of memory.");
+		context->log(RC_LOG_ERROR, "rcAddSpan: Out of memory.");
 		return false;
 		return false;
 	}
 	}
 
 
 	return true;
 	return true;
 }
 }
 
 
-// divides a convex polygons into two convex polygons on both sides of a line
-static void dividePoly(const float* in, int nin,
-					  float* out1, int* nout1,
-					  float* out2, int* nout2,
-					  float x, int axis)
+enum rcAxis
+{
+	RC_AXIS_X = 0,
+	RC_AXIS_Y = 1,
+	RC_AXIS_Z = 2
+};
+
+/// Divides a convex polygon of max 12 vertices into two convex polygons
+/// across a separating axis.
+/// 
+/// @param[in]	inVerts			The input polygon vertices
+/// @param[in]	inVertsCount	The number of input polygon vertices
+/// @param[out]	outVerts1		Resulting polygon 1's vertices
+/// @param[out]	outVerts1Count	The number of resulting polygon 1 vertices
+/// @param[out]	outVerts2		Resulting polygon 2's vertices
+/// @param[out]	outVerts2Count	The number of resulting polygon 2 vertices
+/// @param[in]	axisOffset		THe offset along the specified axis
+/// @param[in]	axis			The separating axis
+static void dividePoly(const float* inVerts, int inVertsCount,
+                       float* outVerts1, int* outVerts1Count,
+                       float* outVerts2, int* outVerts2Count,
+                       float axisOffset, rcAxis axis)
 {
 {
-	float d[12];
-	for (int i = 0; i < nin; ++i)
-		d[i] = x - in[i*3+axis];
+	rcAssert(inVertsCount <= 12);
+	
+	// How far positive or negative away from the separating axis is each vertex.
+	float inVertAxisDelta[12];
+	for (int inVert = 0; inVert < inVertsCount; ++inVert)
+	{
+		inVertAxisDelta[inVert] = axisOffset - inVerts[inVert * 3 + axis];
+	}
 
 
-	int m = 0, n = 0;
-	for (int i = 0, j = nin-1; i < nin; j=i, ++i)
+	int poly1Vert = 0;
+	int poly2Vert = 0;
+	for (int inVertA = 0, inVertB = inVertsCount - 1; inVertA < inVertsCount; inVertB = inVertA, ++inVertA)
 	{
 	{
-		bool ina = d[j] >= 0;
-		bool inb = d[i] >= 0;
-		if (ina != inb)
+		// If the two vertices are on the same side of the separating axis
+		bool sameSide = (inVertAxisDelta[inVertA] >= 0) == (inVertAxisDelta[inVertB] >= 0);
+
+		if (!sameSide)
 		{
 		{
-			float s = d[j] / (d[j] - d[i]);
-			out1[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s;
-			out1[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s;
-			out1[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s;
-			rcVcopy(out2 + n*3, out1 + m*3);
-			m++;
-			n++;
-			// add the i'th point to the right polygon. Do NOT add points that are on the dividing line
+			float s = inVertAxisDelta[inVertB] / (inVertAxisDelta[inVertB] - inVertAxisDelta[inVertA]);
+			outVerts1[poly1Vert * 3 + 0] = inVerts[inVertB * 3 + 0] + (inVerts[inVertA * 3 + 0] - inVerts[inVertB * 3 + 0]) * s;
+			outVerts1[poly1Vert * 3 + 1] = inVerts[inVertB * 3 + 1] + (inVerts[inVertA * 3 + 1] - inVerts[inVertB * 3 + 1]) * s;
+			outVerts1[poly1Vert * 3 + 2] = inVerts[inVertB * 3 + 2] + (inVerts[inVertA * 3 + 2] - inVerts[inVertB * 3 + 2]) * s;
+			rcVcopy(&outVerts2[poly2Vert * 3], &outVerts1[poly1Vert * 3]);
+			poly1Vert++;
+			poly2Vert++;
+			
+			// add the inVertA point to the right polygon. Do NOT add points that are on the dividing line
 			// since these were already added above
 			// since these were already added above
-			if (d[i] > 0)
+			if (inVertAxisDelta[inVertA] > 0)
 			{
 			{
-				rcVcopy(out1 + m*3, in + i*3);
-				m++;
+				rcVcopy(&outVerts1[poly1Vert * 3], &inVerts[inVertA * 3]);
+				poly1Vert++;
 			}
 			}
-			else if (d[i] < 0)
+			else if (inVertAxisDelta[inVertA] < 0)
 			{
 			{
-				rcVcopy(out2 + n*3, in + i*3);
-				n++;
+				rcVcopy(&outVerts2[poly2Vert * 3], &inVerts[inVertA * 3]);
+				poly2Vert++;
 			}
 			}
 		}
 		}
-		else // same side
+		else
 		{
 		{
-			// add the i'th point to the right polygon. Addition is done even for points on the dividing line
-			if (d[i] >= 0)
+			// add the inVertA point to the right polygon. Addition is done even for points on the dividing line
+			if (inVertAxisDelta[inVertA] >= 0)
 			{
 			{
-				rcVcopy(out1 + m*3, in + i*3);
-				m++;
-				if (d[i] != 0)
+				rcVcopy(&outVerts1[poly1Vert * 3], &inVerts[inVertA * 3]);
+				poly1Vert++;
+				if (inVertAxisDelta[inVertA] != 0)
+				{
 					continue;
 					continue;
+				}
 			}
 			}
-			rcVcopy(out2 + n*3, in + i*3);
-			n++;
+			rcVcopy(&outVerts2[poly2Vert * 3], &inVerts[inVertA * 3]);
+			poly2Vert++;
 		}
 		}
 	}
 	}
 
 
-	*nout1 = m;
-	*nout2 = n;
+	*outVerts1Count = poly1Vert;
+	*outVerts2Count = poly2Vert;
 }
 }
 
 
-
-
+///	Rasterize a single triangle to the heightfield.
+///
+///	This code is extremely hot, so much care should be given to maintaining maximum perf here.
+/// 
+/// @param[in] 	v0					Triangle vertex 0
+/// @param[in] 	v1					Triangle vertex 1
+/// @param[in] 	v2					Triangle vertex 2
+/// @param[in] 	areaID				The area ID to assign to the rasterized spans
+/// @param[in] 	hf					Heightfield to rasterize into
+/// @param[in] 	hfBBMin				The min extents of the heightfield bounding box
+/// @param[in] 	hfBBMax				The max extents of the heightfield bounding box
+/// @param[in] 	cellSize			The x and z axis size of a voxel in the heightfield
+/// @param[in] 	inverseCellSize		1 / cellSize
+/// @param[in] 	inverseCellHeight	1 / cellHeight
+/// @param[in] 	flagMergeThreshold	The threshold in which area flags will be merged 
+/// @returns true if the operation completes successfully.  false if there was an error adding spans to the heightfield.
 static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
 static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
-						 const unsigned char area, rcHeightfield& hf,
-						 const float* bmin, const float* bmax,
-						 const float cs, const float ics, const float ich,
-						 const int flagMergeThr)
+                         const unsigned char areaID, rcHeightfield& hf,
+                         const float* hfBBMin, const float* hfBBMax,
+                         const float cellSize, const float inverseCellSize, const float inverseCellHeight,
+                         const int flagMergeThreshold)
 {
 {
-	const int w = hf.width;
-	const int h = hf.height;
-	float tmin[3], tmax[3];
-	const float by = bmax[1] - bmin[1];
-	
 	// Calculate the bounding box of the triangle.
 	// Calculate the bounding box of the triangle.
-	rcVcopy(tmin, v0);
-	rcVcopy(tmax, v0);
-	rcVmin(tmin, v1);
-	rcVmin(tmin, v2);
-	rcVmax(tmax, v1);
-	rcVmax(tmax, v2);
-	
-	// If the triangle does not touch the bbox of the heightfield, skip the triagle.
-	if (!overlapBounds(bmin, bmax, tmin, tmax))
+	float triBBMin[3];
+	rcVcopy(triBBMin, v0);
+	rcVmin(triBBMin, v1);
+	rcVmin(triBBMin, v2);
+
+	float triBBMax[3];
+	rcVcopy(triBBMax, v0);
+	rcVmax(triBBMax, v1);
+	rcVmax(triBBMax, v2);
+
+	// If the triangle does not touch the bounding box of the heightfield, skip the triangle.
+	if (!overlapBounds(triBBMin, triBBMax, hfBBMin, hfBBMax))
+	{
 		return true;
 		return true;
-	
-	// Calculate the footprint of the triangle on the grid's y-axis
-	int y0 = (int)((tmin[2] - bmin[2])*ics);
-	int y1 = (int)((tmax[2] - bmin[2])*ics);
+	}
+
+	const int w = hf.width;
+	const int h = hf.height;
+	const float by = hfBBMax[1] - hfBBMin[1];
+
+	// Calculate the footprint of the triangle on the grid's z-axis
+	int z0 = (int)((triBBMin[2] - hfBBMin[2]) * inverseCellSize);
+	int z1 = (int)((triBBMax[2] - hfBBMin[2]) * inverseCellSize);
+
 	// use -1 rather than 0 to cut the polygon properly at the start of the tile
 	// use -1 rather than 0 to cut the polygon properly at the start of the tile
-	y0 = rcClamp(y0, -1, h-1);
-	y1 = rcClamp(y1, 0, h-1);
-	
+	z0 = rcClamp(z0, -1, h - 1);
+	z1 = rcClamp(z1, 0, h - 1);
+
 	// Clip the triangle into all grid cells it touches.
 	// Clip the triangle into all grid cells it touches.
-	float buf[7*3*4];
-	float *in = buf, *inrow = buf+7*3, *p1 = inrow+7*3, *p2 = p1+7*3;
+	float buf[7 * 3 * 4];
+	float* in = buf;
+	float* inRow = buf + 7 * 3;
+	float* p1 = inRow + 7 * 3;
+	float* p2 = p1 + 7 * 3;
 
 
 	rcVcopy(&in[0], v0);
 	rcVcopy(&in[0], v0);
-	rcVcopy(&in[1*3], v1);
-	rcVcopy(&in[2*3], v2);
-	int nvrow, nvIn = 3;
-	
-	for (int y = y0; y <= y1; ++y)
+	rcVcopy(&in[1 * 3], v1);
+	rcVcopy(&in[2 * 3], v2);
+	int nvRow;
+	int nvIn = 3;
+
+	for (int z = z0; z <= z1; ++z)
 	{
 	{
 		// Clip polygon to row. Store the remaining polygon as well
 		// Clip polygon to row. Store the remaining polygon as well
-		const float cz = bmin[2] + y*cs;
-		dividePoly(in, nvIn, inrow, &nvrow, p1, &nvIn, cz+cs, 2);
+		const float cellZ = hfBBMin[2] + (float)z * cellSize;
+		dividePoly(in, nvIn, inRow, &nvRow, p1, &nvIn, cellZ + cellSize, RC_AXIS_Z);
 		rcSwap(in, p1);
 		rcSwap(in, p1);
-		if (nvrow < 3) continue;
-		if (y < 0) continue;
-		// find the horizontal bounds in the row
-		float minX = inrow[0], maxX = inrow[0];
-		for (int i=1; i<nvrow; ++i)
+		
+		if (nvRow < 3)
 		{
 		{
-			if (minX > inrow[i*3])	minX = inrow[i*3];
-			if (maxX < inrow[i*3])	maxX = inrow[i*3];
+			continue;
 		}
 		}
-		int x0 = (int)((minX - bmin[0])*ics);
-		int x1 = (int)((maxX - bmin[0])*ics);
-		if (x1 < 0 || x0 >= w) {
+		if (z < 0)
+		{
 			continue;
 			continue;
 		}
 		}
-		x0 = rcClamp(x0, -1, w-1);
-		x1 = rcClamp(x1, 0, w-1);
+		
+		// find X-axis bounds of the row
+		float minX = inRow[0];
+		float maxX = inRow[0];
+		for (int vert = 1; vert < nvRow; ++vert)
+		{
+			if (minX > inRow[vert * 3])
+			{
+				minX = inRow[vert * 3];
+			}
+			if (maxX < inRow[vert * 3])
+			{
+				maxX = inRow[vert * 3];
+			}
+		}
+		int x0 = (int)((minX - hfBBMin[0]) * inverseCellSize);
+		int x1 = (int)((maxX - hfBBMin[0]) * inverseCellSize);
+		if (x1 < 0 || x0 >= w)
+		{
+			continue;
+		}
+		x0 = rcClamp(x0, -1, w - 1);
+		x1 = rcClamp(x1, 0, w - 1);
 
 
-		int nv, nv2 = nvrow;
+		int nv;
+		int nv2 = nvRow;
 
 
 		for (int x = x0; x <= x1; ++x)
 		for (int x = x0; x <= x1; ++x)
 		{
 		{
 			// Clip polygon to column. store the remaining polygon as well
 			// Clip polygon to column. store the remaining polygon as well
-			const float cx = bmin[0] + x*cs;
-			dividePoly(inrow, nv2, p1, &nv, p2, &nv2, cx+cs, 0);
-			rcSwap(inrow, p2);
-			if (nv < 3) continue;
-			if (x < 0) continue;
+			const float cx = hfBBMin[0] + (float)x * cellSize;
+			dividePoly(inRow, nv2, p1, &nv, p2, &nv2, cx + cellSize, RC_AXIS_X);
+			rcSwap(inRow, p2);
+			
+			if (nv < 3)
+			{
+				continue;
+			}
+			if (x < 0)
+			{
+				continue;
+			}
+			
 			// Calculate min and max of the span.
 			// Calculate min and max of the span.
-			float smin = p1[1], smax = p1[1];
-			for (int i = 1; i < nv; ++i)
+			float spanMin = p1[1];
+			float spanMax = p1[1];
+			for (int vert = 1; vert < nv; ++vert)
 			{
 			{
-				smin = rcMin(smin, p1[i*3+1]);
-				smax = rcMax(smax, p1[i*3+1]);
+				spanMin = rcMin(spanMin, p1[vert * 3 + 1]);
+				spanMax = rcMax(spanMax, p1[vert * 3 + 1]);
 			}
 			}
-			smin -= bmin[1];
-			smax -= bmin[1];
-			// Skip the span if it is outside the heightfield bbox
-			if (smax < 0.0f) continue;
-			if (smin > by) continue;
-			// Clamp the span to the heightfield bbox.
-			if (smin < 0.0f) smin = 0;
-			if (smax > by) smax = by;
+			spanMin -= hfBBMin[1];
+			spanMax -= hfBBMin[1];
 			
 			
-			// Snap the span to the heightfield height grid.
-			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);
+			// Skip the span if it's completely outside the heightfield bounding box
+			if (spanMax < 0.0f)
+			{
+				continue;
+			}
+			if (spanMin > by)
+			{
+				continue;
+			}
 			
 			
-			if (!addSpan(hf, x, y, ismin, ismax, area, flagMergeThr))
+			// Clamp the span to the heightfield bounding box.
+			if (spanMin < 0.0f)
+			{
+				spanMin = 0;
+			}
+			if (spanMax > by)
+			{
+				spanMax = by;
+			}
+
+			// Snap the span to the heightfield height grid.
+			unsigned short spanMinCellIndex = (unsigned short)rcClamp((int)floorf(spanMin * inverseCellHeight), 0, RC_SPAN_MAX_HEIGHT);
+			unsigned short spanMaxCellIndex = (unsigned short)rcClamp((int)ceilf(spanMax * inverseCellHeight), (int)spanMinCellIndex + 1, RC_SPAN_MAX_HEIGHT);
+
+			if (!addSpan(hf, x, z, spanMinCellIndex, spanMaxCellIndex, areaID, flagMergeThreshold))
+			{
 				return false;
 				return false;
+			}
 		}
 		}
 	}
 	}
 
 
 	return true;
 	return true;
 }
 }
 
 
-/// @par
-///
-/// No spans will be added if the triangle does not overlap the heightfield grid.
-///
-/// @see rcHeightfield
-bool rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
-						 const unsigned char area, rcHeightfield& solid,
-						 const int flagMergeThr)
+bool rcRasterizeTriangle(rcContext* context,
+                         const float* v0, const float* v1, const float* v2,
+                         const unsigned char areaID, rcHeightfield& heightfield, const int flagMergeThreshold)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context != NULL);
 
 
-	rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES);
+	rcScopedTimer timer(context, RC_TIMER_RASTERIZE_TRIANGLES);
 
 
-	const float ics = 1.0f/solid.cs;
-	const float ich = 1.0f/solid.ch;
-	if (!rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr))
+	// Rasterize the single triangle.
+	const float inverseCellSize = 1.0f / heightfield.cs;
+	const float inverseCellHeight = 1.0f / heightfield.ch;
+	if (!rasterizeTri(v0, v1, v2, areaID, heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize, inverseCellHeight, flagMergeThreshold))
 	{
 	{
-		ctx->log(RC_LOG_ERROR, "rcRasterizeTriangle: Out of memory.");
+		context->log(RC_LOG_ERROR, "rcRasterizeTriangle: Out of memory.");
 		return false;
 		return false;
 	}
 	}
 
 
 	return true;
 	return true;
 }
 }
 
 
-/// @par
-///
-/// Spans will only be added for triangles that overlap the heightfield grid.
-///
-/// @see rcHeightfield
-bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
-						  const int* tris, const unsigned char* areas, const int nt,
-						  rcHeightfield& solid, const int flagMergeThr)
+bool rcRasterizeTriangles(rcContext* context,
+                          const float* verts, const int /*nv*/,
+                          const int* tris, const unsigned char* triAreaIDs, const int numTris,
+                          rcHeightfield& heightfield, const int flagMergeThreshold)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context != NULL);
 
 
-	rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES);
+	rcScopedTimer timer(context, RC_TIMER_RASTERIZE_TRIANGLES);
 	
 	
-	const float ics = 1.0f/solid.cs;
-	const float ich = 1.0f/solid.ch;
-	// Rasterize triangles.
-	for (int i = 0; i < nt; ++i)
+	// Rasterize the triangles.
+	const float inverseCellSize = 1.0f / heightfield.cs;
+	const float inverseCellHeight = 1.0f / heightfield.ch;
+	for (int triIndex = 0; triIndex < numTris; ++triIndex)
 	{
 	{
-		const float* v0 = &verts[tris[i*3+0]*3];
-		const float* v1 = &verts[tris[i*3+1]*3];
-		const float* v2 = &verts[tris[i*3+2]*3];
-		// Rasterize.
-		if (!rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr))
+		const float* v0 = &verts[tris[triIndex * 3 + 0] * 3];
+		const float* v1 = &verts[tris[triIndex * 3 + 1] * 3];
+		const float* v2 = &verts[tris[triIndex * 3 + 2] * 3];
+		if (!rasterizeTri(v0, v1, v2, triAreaIDs[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize, inverseCellHeight, flagMergeThreshold))
 		{
 		{
-			ctx->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory.");
+			context->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory.");
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -394,31 +502,26 @@ bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
 	return true;
 	return true;
 }
 }
 
 
-/// @par
-///
-/// Spans will only be added for triangles that overlap the heightfield grid.
-///
-/// @see rcHeightfield
-bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
-						  const unsigned short* tris, const unsigned char* areas, const int nt,
-						  rcHeightfield& solid, const int flagMergeThr)
+bool rcRasterizeTriangles(rcContext* context,
+                          const float* verts, const int /*nv*/,
+                          const unsigned short* tris, const unsigned char* triAreaIDs, const int numTris,
+                          rcHeightfield& heightfield, const int flagMergeThreshold)
 {
 {
-	rcAssert(ctx);
+	rcAssert(context != NULL);
 
 
-	rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES);
-	
-	const float ics = 1.0f/solid.cs;
-	const float ich = 1.0f/solid.ch;
-	// Rasterize triangles.
-	for (int i = 0; i < nt; ++i)
+	rcScopedTimer timer(context, RC_TIMER_RASTERIZE_TRIANGLES);
+
+	// Rasterize the triangles.
+	const float inverseCellSize = 1.0f / heightfield.cs;
+	const float inverseCellHeight = 1.0f / heightfield.ch;
+	for (int triIndex = 0; triIndex < numTris; ++triIndex)
 	{
 	{
-		const float* v0 = &verts[tris[i*3+0]*3];
-		const float* v1 = &verts[tris[i*3+1]*3];
-		const float* v2 = &verts[tris[i*3+2]*3];
-		// Rasterize.
-		if (!rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr))
+		const float* v0 = &verts[tris[triIndex * 3 + 0] * 3];
+		const float* v1 = &verts[tris[triIndex * 3 + 1] * 3];
+		const float* v2 = &verts[tris[triIndex * 3 + 2] * 3];
+		if (!rasterizeTri(v0, v1, v2, triAreaIDs[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize, inverseCellHeight, flagMergeThreshold))
 		{
 		{
-			ctx->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory.");
+			context->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory.");
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -426,30 +529,25 @@ bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
 	return true;
 	return true;
 }
 }
 
 
-/// @par
-///
-/// Spans will only be added for triangles that overlap the heightfield grid.
-///
-/// @see rcHeightfield
-bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
-						  rcHeightfield& solid, const int flagMergeThr)
+bool rcRasterizeTriangles(rcContext* context,
+                          const float* verts, const unsigned char* triAreaIDs, const int numTris,
+                          rcHeightfield& heightfield, const int flagMergeThreshold)
 {
 {
-	rcAssert(ctx);
-	
-	rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES);
+	rcAssert(context != NULL);
+
+	rcScopedTimer timer(context, RC_TIMER_RASTERIZE_TRIANGLES);
 	
 	
-	const float ics = 1.0f/solid.cs;
-	const float ich = 1.0f/solid.ch;
-	// Rasterize triangles.
-	for (int i = 0; i < nt; ++i)
+	// Rasterize the triangles.
+	const float inverseCellSize = 1.0f / heightfield.cs;
+	const float inverseCellHeight = 1.0f / heightfield.ch;
+	for (int triIndex = 0; triIndex < numTris; ++triIndex)
 	{
 	{
-		const float* v0 = &verts[(i*3+0)*3];
-		const float* v1 = &verts[(i*3+1)*3];
-		const float* v2 = &verts[(i*3+2)*3];
-		// Rasterize.
-		if (!rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr))
+		const float* v0 = &verts[(triIndex * 3 + 0) * 3];
+		const float* v1 = &verts[(triIndex * 3 + 1) * 3];
+		const float* v2 = &verts[(triIndex * 3 + 2) * 3];
+		if (!rasterizeTri(v0, v1, v2, triAreaIDs[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize, inverseCellHeight, flagMergeThreshold))
 		{
 		{
-			ctx->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory.");
+			context->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory.");
 			return false;
 			return false;
 		}
 		}
 	}
 	}

+ 0 - 1
thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp

@@ -17,7 +17,6 @@
 //
 //
 
 
 #include <float.h>
 #include <float.h>
-#define _USE_MATH_DEFINES
 #include <math.h>
 #include <math.h>
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff