2025-01-22 16:18:30 +01:00

379 lines
9.0 KiB
C++

#pragma once
#include "../Recast/Include/Recast.h"
#include "../Detour/Include/DetourNavMesh.h"
#include "../Detour/Include/DetourCommon.h"
#include "../Detour/Include/DetourNavMeshBuilder.h"
#include "../DetourCrowd/Include/DetourCrowd.h"
#include "../DetourTileCache/Include/DetourTileCache.h"
#include "../DetourTileCache/Include/DetourTileCacheBuilder.h"
#include "../RecastDemo/Contrib/fastlz/fastlz.h"
#include <vector>
#include <iostream>
#include <list>
class dtNavMeshQuery;
class dtNavMesh;
class MeshLoader;
class NavMesh;
struct rcPolyMesh;
class rcPolyMeshDetail;
struct rcConfig;
struct NavMeshintermediates;
struct TileCacheData;
struct Vec3
{
Vec3() {}
Vec3(float v) : x(v), y(v), z(v) {}
Vec3(float x, float y, float z) : x(x), y(y), z(z) {}
void isMinOf(const Vec3& v)
{
x = (std::min)(x, v.x);
y = (std::min)(y, v.y);
z = (std::min)(z, v.z);
}
void isMaxOf(const Vec3& v)
{
x = (std::max)(x, v.x);
y = (std::max)(y, v.y);
z = (std::max)(z, v.z);
}
float operator [](int index) {
return ((float*)&x)[index];
}
float x, y, z;
};
struct Triangle
{
Triangle(){}
const Vec3& getPoint(long n)
{
if (n < 2)
{
return mPoint[n];
}
return mPoint[2];
}
Vec3 mPoint[3];
};
struct DebugNavMesh
{
int getTriangleCount() { return int(mTriangles.size()); }
const Triangle& getTriangle(int n)
{
if (n < int(mTriangles.size()))
{
return mTriangles[n];
}
return mTriangles.back();
}
std::vector<Triangle> mTriangles;
};
struct NavPath
{
int getPointCount() { return int(mPoints.size()); }
const Vec3& getPoint(int n)
{
if (n < int(mPoints.size()))
{
return mPoints[n];
}
return mPoints.back();
}
std::vector<Vec3> mPoints;
};
struct NavmeshData
{
void* dataPointer;
int size;
};
struct RecastFastLZCompressor : 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 RecastLinearAllocator : public dtTileCacheAlloc
{
unsigned char* buffer;
size_t capacity;
size_t top;
size_t high;
RecastLinearAllocator(const size_t cap) : buffer(0), capacity(0), top(0), high(0)
{
resize(cap);
}
~RecastLinearAllocator()
{
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 RecastMeshProcess : public dtTileCacheMeshProcess
{
inline RecastMeshProcess()
{
}
virtual void process(struct dtNavMeshCreateParams* params,
unsigned char* polyAreas, unsigned short* polyFlags)
{
// Update poly flags from areas.
for (int i = 0; i < params->polyCount; ++i)
{
polyAreas[i] = 0;
polyFlags[i] = 1; //SAMPLE_POLYFLAGS_WALK
}
// Pass in off-mesh connections.
params->offMeshConVerts = 0;//m_geom->getOffMeshConnectionVerts();
params->offMeshConRad = 0;//m_geom->getOffMeshConnectionRads();
params->offMeshConDir = 0;//m_geom->getOffMeshConnectionDirs();
params->offMeshConAreas = 0;//m_geom->getOffMeshConnectionAreas();
params->offMeshConFlags = 0;//m_geom->getOffMeshConnectionFlags();
params->offMeshConUserID = 0;//m_geom->getOffMeshConnectionId();
params->offMeshConCount = 0;//m_geom->getOffMeshConnectionCount();
}
};
class NavMesh
{
public:
NavMesh() : m_navQuery(0)
, m_navMesh(0)
, m_tileCache(0)
, m_pmesh(0)
, m_dmesh(0)
, m_navData(0)
, m_defaultQueryExtent(1.f)
, m_talloc(32000)
{
}
void destroy();
void build(const float* positions, const int positionCount, const int* indices, const int indexCount, const rcConfig& config);
void buildFromNavmeshData(NavmeshData* navmeshData);
NavmeshData getNavmeshData() const;
void freeNavmeshData(NavmeshData* navmeshData);
DebugNavMesh getDebugNavMesh();
Vec3 getClosestPoint(const Vec3& position);
Vec3 getRandomPointAround(const Vec3& position, float maxRadius);
Vec3 moveAlong(const Vec3& position, const Vec3& destination);
dtNavMesh* getNavMesh()
{
return m_navMesh;
}
NavPath computePath(const Vec3& start, const Vec3& end) const;
void setDefaultQueryExtent(const Vec3& extent)
{
m_defaultQueryExtent = extent;
}
Vec3 getDefaultQueryExtent() const
{
return m_defaultQueryExtent;
}
dtObstacleRef* addCylinderObstacle(const Vec3& position, float radius, float height);
dtObstacleRef* addBoxObstacle(const Vec3& position, const Vec3& extent, float angle);
void removeObstacle(dtObstacleRef* obstacle);
void update();
dtTileCache* m_tileCache;
dtNavMeshQuery* m_navQuery;
protected:
std::list<dtObstacleRef> m_obstacles;
dtNavMesh* m_navMesh;
rcPolyMesh* m_pmesh;
rcPolyMeshDetail* m_dmesh;
unsigned char* m_navData;
Vec3 m_defaultQueryExtent;
RecastLinearAllocator m_talloc;
RecastFastLZCompressor m_tcomp;
RecastMeshProcess m_tmproc;
void navMeshPoly(DebugNavMesh& debugNavMesh, const dtNavMesh& mesh, dtPolyRef ref);
void navMeshPolysWithFlags(DebugNavMesh& debugNavMesh, const dtNavMesh& mesh, const unsigned short polyFlags);
bool computeTiledNavMesh(const std::vector<float>& verts, const std::vector<int>& tris, rcConfig& cfg, NavMeshintermediates& intermediates, const std::vector<unsigned char>& triareas);
int rasterizeTileLayers(const int tx, const int ty, const rcConfig& cfg, TileCacheData* tiles, const int maxTiles, NavMeshintermediates& intermediates, const std::vector<unsigned char>& triareas, const std::vector<float>& verts);
};
class Crowd
{
public:
Crowd(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav);
void destroy();
int addAgent(const Vec3& pos, const dtCrowdAgentParams* params);
void removeAgent(const int idx);
void update(const float dt);
Vec3 getAgentPosition(int idx);
Vec3 getAgentVelocity(int idx);
Vec3 getAgentNextTargetPath(int idx);
int getAgentState(int idx);
bool overOffmeshConnection(int idx);
void agentGoto(int idx, const Vec3& destination);
void agentTeleport(int idx, const Vec3& destination);
dtCrowdAgentParams getAgentParameters(const int idx);
void setAgentParameters(const int idx, const dtCrowdAgentParams* params);
void setDefaultQueryExtent(const Vec3& extent)
{
m_defaultQueryExtent = extent;
}
Vec3 getDefaultQueryExtent() const
{
return m_defaultQueryExtent;
}
NavPath getCorners(const int idx);
protected:
dtCrowd *m_crowd;
Vec3 m_defaultQueryExtent;
};
class RecastConfigHelper
{
public:
RecastConfigHelper() {};
void destroy();
void setBMAX(rcConfig& cfg, float x, float y, float z);
void setBMIN(rcConfig& cfg, float x, float y, float z);
Vec3 getBMAX(rcConfig& cfg);
Vec3 getBMIN(rcConfig& cfg);
};
class rcFloatArray {
int count = 0;
public:
float *raw;
rcFloatArray(int num) {
raw = (float *) malloc(sizeof(float) * num);
count = num;
}
~rcFloatArray() {
free(raw);
}
float at(int pos) {
return raw[pos];
}
int set(int pos, float value) {
if(pos < count){
raw[pos] = value;
return 0;
}
return 1;
}
int size() {
return count;
}
};
class rcIntArray {
int count = 0;
public:
int *raw;
rcIntArray(int num) {
raw = (int *) malloc(sizeof(int) * num);
count = num;
}
~rcIntArray() {
free(raw);
}
float at(int pos) {
return raw[pos];
}
int set(int pos, int value) {
if(pos < count){
raw[pos] = value;
return 0;
}
return 1;
}
int size() {
return count;
}
};