This commit is contained in:
aozhiwei 2020-08-13 21:01:02 +08:00
parent db1d19a46e
commit 244e92f1fa
3 changed files with 238 additions and 235 deletions

View File

@ -19,6 +19,8 @@
#include "entity.h"
#include "metamgr.h"
#include "navmeshhelper.h"
static const float kAgentMaxSlope = 90;
static const float kAgentHeight = 1;
static const float kAgentMaxClimb = 1;
@ -37,244 +39,9 @@ static const int kTileSize = 48;
static const float kDetailSampleDist = 1;
static const float kDetailSampleMaxError = 1;
static const int EXPECTED_LAYERS_PER_TILE = 4;
static const int MAX_LAYERS = 32;
static const int kMaxTiles = 0;
static const int kMaxPolysPerTile = 0;
/// Mask of the ceil part of the area id (3 lower bits)
/// the 0 value (RC_NULL_AREA) is left unused
static const unsigned char SAMPLE_POLYAREA_TYPE_MASK = 0x07;
/// Value for the kind of ceil "ground"
static const unsigned char SAMPLE_POLYAREA_TYPE_GROUND = 0x1;
/// Value for the kind of ceil "water"
static const unsigned char SAMPLE_POLYAREA_TYPE_WATER = 0x2;
/// Value for the kind of ceil "road"
static const unsigned char SAMPLE_POLYAREA_TYPE_ROAD = 0x3;
/// Value for the kind of ceil "grass"
static const unsigned char SAMPLE_POLYAREA_TYPE_GRASS = 0x4;
/// Flag for door area. Can be combined with area types and jump flag.
static const unsigned char SAMPLE_POLYAREA_FLAG_DOOR = 0x08;
/// Flag for jump area. Can be combined with area types and door flag.
static const unsigned char SAMPLE_POLYAREA_FLAG_JUMP = 0x10;
struct TileCacheData
{
unsigned char* data;
int dataSize;
};
struct rcChunkyTriMeshNode
{
float bmin[2];
float bmax[2];
int i;
int n;
};
struct rcChunkyTriMesh
{
inline rcChunkyTriMesh() : nodes(0), nnodes(0), tris(0), ntris(0), maxTrisPerChunk(0) {};
inline ~rcChunkyTriMesh() { delete [] nodes; delete [] tris; }
rcChunkyTriMeshNode* nodes;
int nnodes;
int* tris;
int ntris;
int maxTrisPerChunk;
private:
// Explicitly disabled copy constructor and copy assignment operator.
#if 0
rcChunkyTriMesh(const rcChunkyTriMesh&);
rcChunkyTriMesh& operator=(const rcChunkyTriMesh&);
#endif
};
static const int MAX_CONVEXVOL_PTS = 12;
struct ConvexVolume
{
ConvexVolume(): areaMod(RC_AREA_FLAGS_MASK) {}
float verts[MAX_CONVEXVOL_PTS*3];
float hmin, hmax;
int nverts;
rcAreaModification areaMod;
};
inline bool checkOverlapRect(const float amin[2], const float amax[2],
const float bmin[2], const float bmax[2])
{
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;
return overlap;
}
static int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm,
float bmin[2], float bmax[2],
int* ids, const int maxIds)
{
// Traverse tree
int i = 0;
int n = 0;
while (i < cm->nnodes) {
const rcChunkyTriMeshNode* node = &cm->nodes[i];
const bool overlap = checkOverlapRect(bmin, bmax, node->bmin, node->bmax);
const bool isLeafNode = node->i >= 0;
if (isLeafNode && overlap) {
if (n < maxIds) {
ids[n] = i;
n++;
}
}
if (overlap || isLeafNode)
i++;
else {
const int escapeIndex = -node->i;
i += escapeIndex;
}
}
return n;
}
struct RasterizationContext
{
RasterizationContext() :
solid(0),
triareas(0),
lset(0),
chf(0),
ntiles(0)
{
memset(tiles, 0, sizeof(TileCacheData)*MAX_LAYERS);
}
~RasterizationContext()
{
rcFreeHeightField(solid);
delete [] triareas;
rcFreeHeightfieldLayerSet(lset);
rcFreeCompactHeightfield(chf);
for (int i = 0; i < MAX_LAYERS; ++i)
{
dtFree(tiles[i].data);
tiles[i].data = 0;
}
}
rcHeightfield* solid;
unsigned char* triareas;
rcHeightfieldLayerSet* lset;
rcCompactHeightfield* chf;
TileCacheData tiles[MAX_LAYERS];
int ntiles;
};
struct LinearAllocator : public dtTileCacheAlloc
{
unsigned char* buffer;
size_t capacity;
size_t top;
size_t high;
LinearAllocator(const size_t cap) : buffer(0), capacity(0), top(0), high(0)
{
resize(cap);
}
~LinearAllocator()
{
dtFree(buffer);
}
void resize(const size_t cap)
{
if (buffer) dtFree(buffer);
buffer = (unsigned char*)dtAlloc(cap, DT_ALLOC_PERM);
capacity = cap;
}
virtual void reset()
{
high = dtMax(high, top);
top = 0;
}
virtual void* alloc(const size_t size)
{
if (!buffer)
return 0;
if (top+size > capacity)
return 0;
unsigned char* mem = &buffer[top];
top += size;
return mem;
}
virtual void free(void* /*ptr*/)
{
// Empty
}
};
struct FastLZCompressor : public dtTileCacheCompressor
{
virtual int maxCompressedSize(const int bufferSize)
{
return (int)(bufferSize* 1.05f);
}
virtual dtStatus compress(const unsigned char* buffer, const int bufferSize,
unsigned char* compressed, const int /*maxCompressedSize*/, int* compressedSize)
{
*compressedSize = fastlz_compress((const void *const)buffer, bufferSize, compressed);
return DT_SUCCESS;
}
virtual dtStatus decompress(const unsigned char* compressed, const int compressedSize,
unsigned char* buffer, const int maxBufferSize, int* bufferSize)
{
*bufferSize = fastlz_decompress(compressed, compressedSize, buffer, maxBufferSize);
return *bufferSize < 0 ? DT_FAILURE : DT_SUCCESS;
}
};
struct MeshProcess : public dtTileCacheMeshProcess
{
inline MeshProcess()
{
}
virtual void process(struct dtNavMeshCreateParams* params,
unsigned char* polyAreas,
unsigned short* polyFlags)
{
#if 0
// Update poly flags from areas.
for (int i = 0; i < params->polyCount; ++i)
{
polyFlags[i] = sampleAreaToFlags(polyAreas[i]);
}
// Pass in off-mesh connections.
if (m_geom)
{
params->offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params->offMeshConRad = m_geom->getOffMeshConnectionRads();
params->offMeshConDir = m_geom->getOffMeshConnectionDirs();
params->offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params->offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params->offMeshConUserID = m_geom->getOffMeshConnectionId();
params->offMeshConCount = m_geom->getOffMeshConnectionCount();
}
#endif
}
};
void NavMeshBuilder::Init()
{

View File

View File

@ -0,0 +1,236 @@
#pragma once
static const int EXPECTED_LAYERS_PER_TILE = 4;
static const int MAX_LAYERS = 32;
/// Mask of the ceil part of the area id (3 lower bits)
/// the 0 value (RC_NULL_AREA) is left unused
static const unsigned char SAMPLE_POLYAREA_TYPE_MASK = 0x07;
/// Value for the kind of ceil "ground"
static const unsigned char SAMPLE_POLYAREA_TYPE_GROUND = 0x1;
/// Value for the kind of ceil "water"
static const unsigned char SAMPLE_POLYAREA_TYPE_WATER = 0x2;
/// Value for the kind of ceil "road"
static const unsigned char SAMPLE_POLYAREA_TYPE_ROAD = 0x3;
/// Value for the kind of ceil "grass"
static const unsigned char SAMPLE_POLYAREA_TYPE_GRASS = 0x4;
/// Flag for door area. Can be combined with area types and jump flag.
static const unsigned char SAMPLE_POLYAREA_FLAG_DOOR = 0x08;
/// Flag for jump area. Can be combined with area types and door flag.
static const unsigned char SAMPLE_POLYAREA_FLAG_JUMP = 0x10;
struct TileCacheData
{
unsigned char* data;
int dataSize;
};
struct rcChunkyTriMeshNode
{
float bmin[2];
float bmax[2];
int i;
int n;
};
struct rcChunkyTriMesh
{
inline rcChunkyTriMesh() : nodes(0), nnodes(0), tris(0), ntris(0), maxTrisPerChunk(0) {};
inline ~rcChunkyTriMesh() { delete [] nodes; delete [] tris; }
rcChunkyTriMeshNode* nodes;
int nnodes;
int* tris;
int ntris;
int maxTrisPerChunk;
private:
// Explicitly disabled copy constructor and copy assignment operator.
#if 0
rcChunkyTriMesh(const rcChunkyTriMesh&);
rcChunkyTriMesh& operator=(const rcChunkyTriMesh&);
#endif
};
static const int MAX_CONVEXVOL_PTS = 12;
struct ConvexVolume
{
ConvexVolume(): areaMod(RC_AREA_FLAGS_MASK) {}
float verts[MAX_CONVEXVOL_PTS*3];
float hmin, hmax;
int nverts;
rcAreaModification areaMod;
};
inline bool checkOverlapRect(const float amin[2], const float amax[2],
const float bmin[2], const float bmax[2])
{
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;
return overlap;
}
int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm,
float bmin[2], float bmax[2],
int* ids, const int maxIds)
{
// Traverse tree
int i = 0;
int n = 0;
while (i < cm->nnodes) {
const rcChunkyTriMeshNode* node = &cm->nodes[i];
const bool overlap = checkOverlapRect(bmin, bmax, node->bmin, node->bmax);
const bool isLeafNode = node->i >= 0;
if (isLeafNode && overlap) {
if (n < maxIds) {
ids[n] = i;
n++;
}
}
if (overlap || isLeafNode)
i++;
else {
const int escapeIndex = -node->i;
i += escapeIndex;
}
}
return n;
}
struct RasterizationContext
{
RasterizationContext() :
solid(0),
triareas(0),
lset(0),
chf(0),
ntiles(0)
{
memset(tiles, 0, sizeof(TileCacheData)*MAX_LAYERS);
}
~RasterizationContext()
{
rcFreeHeightField(solid);
delete [] triareas;
rcFreeHeightfieldLayerSet(lset);
rcFreeCompactHeightfield(chf);
for (int i = 0; i < MAX_LAYERS; ++i)
{
dtFree(tiles[i].data);
tiles[i].data = 0;
}
}
rcHeightfield* solid;
unsigned char* triareas;
rcHeightfieldLayerSet* lset;
rcCompactHeightfield* chf;
TileCacheData tiles[MAX_LAYERS];
int ntiles;
};
struct LinearAllocator : public dtTileCacheAlloc
{
unsigned char* buffer;
size_t capacity;
size_t top;
size_t high;
LinearAllocator(const size_t cap) : buffer(0), capacity(0), top(0), high(0)
{
resize(cap);
}
~LinearAllocator()
{
dtFree(buffer);
}
void resize(const size_t cap)
{
if (buffer) dtFree(buffer);
buffer = (unsigned char*)dtAlloc(cap, DT_ALLOC_PERM);
capacity = cap;
}
virtual void reset()
{
high = dtMax(high, top);
top = 0;
}
virtual void* alloc(const size_t size)
{
if (!buffer)
return 0;
if (top+size > capacity)
return 0;
unsigned char* mem = &buffer[top];
top += size;
return mem;
}
virtual void free(void* /*ptr*/)
{
// Empty
}
};
struct FastLZCompressor : public dtTileCacheCompressor
{
virtual int maxCompressedSize(const int bufferSize)
{
return (int)(bufferSize* 1.05f);
}
virtual dtStatus compress(const unsigned char* buffer, const int bufferSize,
unsigned char* compressed, const int /*maxCompressedSize*/, int* compressedSize)
{
*compressedSize = fastlz_compress((const void *const)buffer, bufferSize, compressed);
return DT_SUCCESS;
}
virtual dtStatus decompress(const unsigned char* compressed, const int compressedSize,
unsigned char* buffer, const int maxBufferSize, int* bufferSize)
{
*bufferSize = fastlz_decompress(compressed, compressedSize, buffer, maxBufferSize);
return *bufferSize < 0 ? DT_FAILURE : DT_SUCCESS;
}
};
struct MeshProcess : public dtTileCacheMeshProcess
{
inline MeshProcess()
{
}
virtual void process(struct dtNavMeshCreateParams* params,
unsigned char* polyAreas,
unsigned short* polyFlags)
{
#if 0
// Update poly flags from areas.
for (int i = 0; i < params->polyCount; ++i)
{
polyFlags[i] = sampleAreaToFlags(polyAreas[i]);
}
// Pass in off-mesh connections.
if (m_geom)
{
params->offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params->offMeshConRad = m_geom->getOffMeshConnectionRads();
params->offMeshConDir = m_geom->getOffMeshConnectionDirs();
params->offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params->offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params->offMeshConUserID = m_geom->getOffMeshConnectionId();
params->offMeshConCount = m_geom->getOffMeshConnectionCount();
}
#endif
}
};