1
This commit is contained in:
parent
db1d19a46e
commit
244e92f1fa
@ -19,6 +19,8 @@
|
|||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "metamgr.h"
|
#include "metamgr.h"
|
||||||
|
|
||||||
|
#include "navmeshhelper.h"
|
||||||
|
|
||||||
static const float kAgentMaxSlope = 90;
|
static const float kAgentMaxSlope = 90;
|
||||||
static const float kAgentHeight = 1;
|
static const float kAgentHeight = 1;
|
||||||
static const float kAgentMaxClimb = 1;
|
static const float kAgentMaxClimb = 1;
|
||||||
@ -37,244 +39,9 @@ static const int kTileSize = 48;
|
|||||||
static const float kDetailSampleDist = 1;
|
static const float kDetailSampleDist = 1;
|
||||||
static const float kDetailSampleMaxError = 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 kMaxTiles = 0;
|
||||||
static const int kMaxPolysPerTile = 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()
|
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