game2004/server/gameserver/navmeshhelper.h
aozhiwei 2e61aa105a 1
2020-08-18 17:38:14 +08:00

258 lines
7.6 KiB
C++

#pragma once
#include "Recast.h"
#include "RecastAlloc.h"
#include "DetourTileCache.h"
#include "DetourTileCacheBuilder.h"
#include "DetourNavMeshBuilder.h"
#include "DetourNavMeshQuery.h"
#include "DetourCommon.h"
#include "DetourNavMesh.h"
#include "fastlz.h"
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 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
}
};
class BuildContext : public rcContext
{
protected:
virtual void doResetLog() {}
virtual void doLog(const rcLogCategory category, const char* msg, const int len) {}
virtual void doResetTimers() {}
virtual void doStartTimer(const rcTimerLabel label) {}
virtual void doStopTimer(const rcTimerLabel label) {}
virtual int doGetAccumulatedTime(const rcTimerLabel label) const { return 0;}
};
class MapInstance;
class NavMeshHelper
{
public:
static void OutputObjFile(MapInstance* map_instance);
};
namespace f8
{
class InputGeom;
}
struct BuilderParams
{
const float kCellSize = 1; //体素大小
const float kCellHeight = 1; //体素高度
const float kAgentMaxSlope = 90; //角色可走的最大坡度
const float kAgentHeight = 1; //角色高
const float kAgentMaxClimb = 1; //角色能爬的最大高度
const float kAgentRadius = 20; //角色半径
const float kEdgeMaxLen = 6; //简化列表中相邻两点间的距离
const float kEdgeMaxError = 6; //从简化边到实边的最大距离
const float kRegionMinSize = 6; //最小区域的大小, 网格面积小于该值的地方,将不生成导航网格
/*
限制: >= 0
当一些区域的尺寸小于此参数时,如果可以,会和较大区域合并.
取值以体素为单位
该参数可以帮助减少一些尺寸较小的区域
由于区域生成算法的固有错误,会产生一些不期望的小区域.这在三角路径区域划分时,更为明显.
如果小区域无法被合并到临近的区域,则这些小区域会被保留,不会改变.比如合并后会导致非简单多边形等原因导致无法合并.
[该参数取值过小,产生了一些细长三角形]
[该参数取值足够大,一些细长三角形被合并,网格有更少的细长三角形]
*/
#if 1
const float kRegionMergeSize = 400;
#else
const float kRegionMergeSize = 20;
#endif
/*
限制: >= 3 在体素到多边形转换过程中生成的多边形中每个多边形的最大顶点数
较大的取值会导致较高的处理耗时,但是会在寻路网格上生成较好的多边形.
一般取6左右的值即可,更高的取值,收效递减*/
const int kVertsPerPoly = 6;
const int kTileSize = 64; //单个瓦片大小
const float kDetailSampleDist = 6;
const float kDetailSampleMaxError = 1;
#if 0
const int kMaxTiles = 0;
const int kMaxPolysPerTile = 0;
#endif
const bool kFilterLowHangingObstacles = false;
const bool kFilterLedgeSpans = false;
const bool kFilterWalkableLowHeightSpans = false;
int grid_width = 0;
int grid_height = 0;
int tile_size = 0;
int tile_width = 0;
int tile_height = 0;
MapInstance* map_instance = nullptr;
f8::InputGeom* geom = nullptr;
dtNavMesh* navmesh = nullptr;
rcContext* ctx = nullptr;
dtTileCache* tile_cache = nullptr;
};