1
This commit is contained in:
parent
db1d19a46e
commit
244e92f1fa
@ -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()
|
||||
{
|
||||
|
||||
|
0
server/gameserver/navmeshhelper.cc
Normal file
0
server/gameserver/navmeshhelper.cc
Normal file
236
server/gameserver/navmeshhelper.h
Normal file
236
server/gameserver/navmeshhelper.h
Normal 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
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user