Skip to content

Commit

Permalink
Custom allocator for Recast.
Browse files Browse the repository at this point in the history
  • Loading branch information
memononen committed Jul 9, 2010
1 parent e5cca88 commit cd3a351
Show file tree
Hide file tree
Showing 20 changed files with 2,470 additions and 432 deletions.
3 changes: 2 additions & 1 deletion Detour/Source/DetourAlloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ void* dtAlloc(int size, dtAllocHint hint)

void dtFree(void* ptr)
{
sFreeFunc(ptr);
if (ptr)
sFreeFunc(ptr);
}
89 changes: 22 additions & 67 deletions Recast/Include/Recast.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,6 @@ struct rcSpanPool
// Dynamic span-heightfield.
struct rcHeightfield
{
inline rcHeightfield() : width(0), height(0), spans(0), pools(0), freelist(0) {}
inline ~rcHeightfield()
{
// Delete span array.
delete [] spans;
// Delete span pools.
while (pools)
{
rcSpanPool* next = pools->next;
delete [] reinterpret_cast<unsigned char*>(pools);
pools = next;
}
}
int width, height; // Dimension of the heightfield.
float bmin[3], bmax[3]; // Bounding box of the heightfield
float cs, ch; // Cell size and height.
Expand All @@ -100,16 +87,9 @@ struct rcCompactSpan
// Compact static heightfield.
struct rcCompactHeightfield
{
inline rcCompactHeightfield() :
maxDistance(0), maxRegions(0), cells(0),
spans(0), dist(0), areas(0) {}
inline ~rcCompactHeightfield()
{
delete [] cells;
delete [] spans;
delete [] dist;
delete [] areas;
}
rcCompactHeightfield();
~rcCompactHeightfield();

int width, height; // Width and height of the heighfield.
int spanCount; // Number of spans in the heightfield.
int walkableHeight, walkableClimb; // Agent properties.
Expand All @@ -125,8 +105,6 @@ struct rcCompactHeightfield

struct rcContour
{
inline rcContour() : verts(0), nverts(0), rverts(0), nrverts(0) { }
inline ~rcContour() { delete [] verts; delete [] rverts; }
int* verts; // Vertex coordinates, each vertex contains 4 components.
int nverts; // Number of vertices.
int* rverts; // Raw vertex coordinates, each vertex contains 4 components.
Expand All @@ -137,8 +115,6 @@ struct rcContour

struct rcContourSet
{
inline rcContourSet() : conts(0), nconts(0) {}
inline ~rcContourSet() { delete [] conts; }
rcContour* conts; // Pointer to all contours.
int nconts; // Number of contours.
float bmin[3], bmax[3]; // Bounding box of the heightfield.
Expand All @@ -157,11 +133,7 @@ struct rcContourSet
// y = bmin[1] + verts[i*3+1]*ch;
// z = bmin[2] + verts[i*3+2]*cs;
struct rcPolyMesh
{
inline rcPolyMesh() : verts(0), polys(0), regs(0), flags(0), areas(0), nverts(0), npolys(0), maxpolys(0), nvp(3) {}

inline ~rcPolyMesh() { delete [] verts; delete [] polys; delete [] regs; delete [] flags; delete [] areas; }

{
unsigned short* verts; // Vertices of the mesh, 3 elements per vertex.
unsigned short* polys; // Polygons of the mesh, nvp*2 elements per polygon.
unsigned short* regs; // Region ID of the polygons.
Expand All @@ -187,14 +159,6 @@ struct rcPolyMesh

struct rcPolyMeshDetail
{
inline rcPolyMeshDetail() :
meshes(0), verts(0), tris(0),
nmeshes(0), nverts(0), ntris(0) {}
inline ~rcPolyMeshDetail()
{
delete [] meshes; delete [] verts; delete [] tris;
}

unsigned short* meshes; // Pointer to all mesh data.
float* verts; // Pointer to all vertex data.
unsigned char* tris; // Pointer to all triangle data.
Expand All @@ -203,35 +167,22 @@ struct rcPolyMeshDetail
int ntris; // Number of triangles.
};

// Allocators and destructors for Recast objects.
rcHeightfield* rcAllocHeightfield();
void rcFreeHeightField(rcHeightfield* hf);

// Simple dynamic array ints.
class rcIntArray
{
int* m_data;
int m_size, m_cap;
public:
inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {}
inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(n) { m_data = new int[n]; }
inline ~rcIntArray() { delete [] m_data; }
void resize(int n);
inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; }
inline const int& operator[](int i) const { return m_data[i]; }
inline int& operator[](int i) { return m_data[i]; }
inline int size() const { return m_size; }
};
rcCompactHeightfield* rcAllocCompactHeightfield();
void rcFreeCompactHeightfield(rcCompactHeightfield* chf);

rcContourSet* rcAllocContourSet();
void rcFreeContourSet(rcContourSet* cset);

rcPolyMesh* rcAllocPolyMesh();
void rcFreePolyMesh(rcPolyMesh* pmesh);

rcPolyMeshDetail* rcAllocPolyMeshDetail();
void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh);

// Simple helper class to delete array in scope
template<class T> class rcScopedDelete
{
T* ptr;
public:
inline rcScopedDelete() : ptr(0) {}
inline rcScopedDelete(T* p) : ptr(p) {}
inline ~rcScopedDelete() { delete [] ptr; }
inline operator T*() { return ptr; }
inline T* operator=(T* p) { ptr = p; return ptr; }
};

enum rcSpanFlags
{
Expand Down Expand Up @@ -391,6 +342,10 @@ inline bool rcVequal(const float* p0, const float* p1)
return d < thr;
}

// Alloc helpers for different Recast objects.
rcHeightfield* rcAllocHeightfield();
void rcFreeHeightField(rcHeightfield* hf);


// Calculated bounding box of array of vertices.
// Params:
Expand Down
67 changes: 67 additions & 0 deletions Recast/Include/RecastAlloc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// Copyright (c) 2009-2010 Mikko Mononen [email protected]
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//

#ifndef RECASTALLOC_H
#define RECASTALLOC_H

enum rcAllocHint
{
RC_ALLOC_PERM, // Memory persist after a function call.
RC_ALLOC_TEMP // Memory used temporarily within a function.
};

typedef void* (rcAllocFunc)(int size, rcAllocHint hint);
typedef void (rcFreeFunc)(void* ptr);

void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc);

void* rcAlloc(int size, rcAllocHint hint);
void rcFree(void* ptr);



// Simple dynamic array ints.
class rcIntArray
{
int* m_data;
int m_size, m_cap;
public:
inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {}
inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(n) { m_data = new int[n]; }
inline ~rcIntArray() { delete [] m_data; }
void resize(int n);
inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; }
inline const int& operator[](int i) const { return m_data[i]; }
inline int& operator[](int i) { return m_data[i]; }
inline int size() const { return m_size; }
};

// Simple internal helper class to delete array in scope
template<class T> class rcScopedDelete
{
T* ptr;
inline T* operator=(T* p) { /*ptr = p; return ptr;*/ }
public:
inline rcScopedDelete() : ptr(0) {}
inline rcScopedDelete(T* p) : ptr(p) {}
inline ~rcScopedDelete() { rcFree(ptr); }
inline operator T*() { return ptr; }
};

#endif
106 changes: 93 additions & 13 deletions Recast/Source/Recast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,106 @@
#include "Recast.h"
#include "RecastLog.h"
#include "RecastTimer.h"
#include "RecastAlloc.h"

float rcSqrt(float x)
{
return sqrtf(x);
}

void rcIntArray::resize(int n)
rcHeightfield* rcAllocHeightfield()
{
if (n > m_cap)
rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM);
memset(hf, 0, sizeof(rcHeightfield));
return hf;
}

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;
}
rcFree(hf);
}

rcCompactHeightfield* rcAllocCompactHeightfield()
{
rcCompactHeightfield* chf = (rcCompactHeightfield*)rcAlloc(sizeof(rcCompactHeightfield), RC_ALLOC_PERM);
memset(chf, 0, sizeof(rcCompactHeightfield));
return chf;
}

void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
{
if (!chf) return;
rcFree(chf->cells);
rcFree(chf->spans);
rcFree(chf->dist);
rcFree(chf->areas);
rcFree(chf);
}

rcContourSet* rcAllocContourSet()
{
rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM);
memset(cset, 0, sizeof(rcContourSet));
return cset;
}

void rcFreeContourSet(rcContourSet* cset)
{
if (!cset) return;
for (int i = 0; i < cset->nconts; ++i)
{
if (!m_cap) m_cap = 8;
while (m_cap < n) m_cap *= 2;
int* newData = new int[m_cap];
if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int));
delete [] m_data;
m_data = newData;
rcFree(cset->conts[i].verts);
rcFree(cset->conts[i].rverts);
}
m_size = n;
rcFree(cset->conts);
rcFree(cset);
}

rcPolyMesh* rcAllocPolyMesh()
{
rcPolyMesh* pmesh = (rcPolyMesh*)rcAlloc(sizeof(rcPolyMesh), RC_ALLOC_PERM);
memset(pmesh, 0, sizeof(rcPolyMesh));
return pmesh;
}

void rcFreePolyMesh(rcPolyMesh* pmesh)
{
if (!pmesh) return;
rcFree(pmesh->verts);
rcFree(pmesh->polys);
rcFree(pmesh->regs);
rcFree(pmesh->flags);
rcFree(pmesh->areas);
rcFree(pmesh);
}

rcPolyMeshDetail* rcAllocPolyMeshDetail()
{
rcPolyMeshDetail* dmesh = (rcPolyMeshDetail*)rcAlloc(sizeof(rcPolyMeshDetail), RC_ALLOC_PERM);
memset(dmesh, 0, sizeof(rcPolyMeshDetail));
return dmesh;
}

void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
{
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)
{
// Calculate bounding box.
Expand All @@ -70,11 +150,11 @@ bool rcCreateHeightfield(rcHeightfield& hf, int width, int height,
{
hf.width = width;
hf.height = height;
hf.spans = new rcSpan*[hf.width*hf.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)
return false;
memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height);
Expand Down Expand Up @@ -150,23 +230,23 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
chf.bmax[1] += walkableHeight*hf.ch;
chf.cs = hf.cs;
chf.ch = hf.ch;
chf.cells = new rcCompactCell[w*h];
chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM);
if (!chf.cells)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h);
return false;
}
memset(chf.cells, 0, sizeof(rcCompactCell)*w*h);
chf.spans = new rcCompactSpan[spanCount];
chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM);
if (!chf.spans)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
return false;
}
memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount);
chf.areas = new unsigned char[spanCount];
chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM);
if (!chf.areas)
{
if (rcGetLog())
Expand Down
Loading

0 comments on commit cd3a351

Please sign in to comment.