Changed the polygon merging so that it does not generate parallel neighbor edges.
Added first version of Detour. Changed the demo to use Detour.
This commit is contained in:
parent
ea8fb55a46
commit
b93fe6b29a
28
Detour/Include/DetourDebugDraw.h
Executable file
28
Detour/Include/DetourDebugDraw.h
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DETOURDEBUGDRAW_H
|
||||||
|
#define DETOURDEBUGDRAW_H
|
||||||
|
|
||||||
|
#include "DetourStatNavMesh.h"
|
||||||
|
|
||||||
|
void dtDebugDrawStatNavMeshPoly(const dtStatNavMesh* mesh, dtPolyRef ref, const float* col);
|
||||||
|
void dtDebugDrawStatNavMeshBVTree(const dtStatNavMesh* mesh);
|
||||||
|
void dtDebugDrawStatNavMesh(const dtStatNavMesh* mesh);
|
||||||
|
|
||||||
|
#endif // DETOURDEBUGDRAW_H
|
201
Detour/Include/DetourStatNavMesh.h
Executable file
201
Detour/Include/DetourStatNavMesh.h
Executable file
@ -0,0 +1,201 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DETOURSTATNAVMESH_H
|
||||||
|
#define DETOURSTATNAVMESH_H
|
||||||
|
|
||||||
|
// Reference to navigation polygon.
|
||||||
|
typedef unsigned short dtPolyRef;
|
||||||
|
|
||||||
|
// Maximum number of vertices per navigation polygon.
|
||||||
|
static const int DT_VERTS_PER_POLYGON = 6;
|
||||||
|
|
||||||
|
// Structure holding the navigation polygon data.
|
||||||
|
struct dtPoly
|
||||||
|
{
|
||||||
|
unsigned short v[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly.
|
||||||
|
dtPolyRef n[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
|
||||||
|
unsigned char nv; // Number of vertices.
|
||||||
|
unsigned char flags; // Flags (not used).
|
||||||
|
unsigned char pad[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
const int DT_NAVMESH_MAGIC = 'NAVM';
|
||||||
|
const int DT_NAVMESH_VERSION = 2;
|
||||||
|
|
||||||
|
struct dtBVNode
|
||||||
|
{
|
||||||
|
unsigned short bmin[3], bmax[3];
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dtStatNavMeshHeader
|
||||||
|
{
|
||||||
|
int magic;
|
||||||
|
int version;
|
||||||
|
int npolys;
|
||||||
|
int nverts;
|
||||||
|
int nnodes;
|
||||||
|
float cs;
|
||||||
|
float bmin[3], bmax[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
class dtStatNavMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
dtStatNavMesh();
|
||||||
|
~dtStatNavMesh();
|
||||||
|
|
||||||
|
// Initializes the path finder with path data.
|
||||||
|
// Params:
|
||||||
|
// data - (in) Pointer to path data.
|
||||||
|
// dataSize - (in) size of the path data.
|
||||||
|
// ownsData - (in) Flag indicating if the pathfinder should delete the data.
|
||||||
|
bool init(unsigned char* data, int dataSize, bool ownsData);
|
||||||
|
|
||||||
|
// Finds the nearest navigation polygon around the center location.
|
||||||
|
// Params:
|
||||||
|
// center - (in) The center of the search box.
|
||||||
|
// extents - (in) The extents of the search box.
|
||||||
|
dtPolyRef findNearestPoly(const float* center, const float* extents);
|
||||||
|
|
||||||
|
// Returns polygons which touch the query box.
|
||||||
|
// Params:
|
||||||
|
// center - (in) the center of the search box.
|
||||||
|
// extents - (in) the extents of the search box.
|
||||||
|
// polys - (out) array holding the search result.
|
||||||
|
// maxPolys - (in) The max number of polygons the polys array can hold.
|
||||||
|
// Returns: Number of polygons in search result array.
|
||||||
|
int queryPolygons(const float* center, const float* extents,
|
||||||
|
unsigned short* polys, const int maxPolys);
|
||||||
|
|
||||||
|
// Finds path from start polygon to end polygon.
|
||||||
|
// If target polygon canno be reached through the navigation graph,
|
||||||
|
// the last node on the array is nearest node to the end polygon.
|
||||||
|
// Params:
|
||||||
|
// startRef - (in) ref to path start polygon.
|
||||||
|
// endRef - (in) ref to path end polygon.
|
||||||
|
// path - (out) array holding the search result.
|
||||||
|
// maxPathSize - (in) The max number of polygons the path array can hold.
|
||||||
|
// Returns: Number of polygons in search result array.
|
||||||
|
int findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||||||
|
dtPolyRef* path, const int maxPathSize);
|
||||||
|
|
||||||
|
// Finds a straight path from start to end locations within the corridor
|
||||||
|
// described by the path polygons.
|
||||||
|
// Start and end locations will be clamped on the corridor.
|
||||||
|
// Params:
|
||||||
|
// startPos - (in) Path start location.
|
||||||
|
// endPos - (in) Path end location.
|
||||||
|
// path - (in) Array of connected polygons describing the corridor.
|
||||||
|
// pathSize - (in) Number of polygons in path array.
|
||||||
|
// straightPath - (out) Points describing the straight path.
|
||||||
|
// maxStraightPathSize - (in) The max number of points the straight path array can hold.
|
||||||
|
int findStraightPath(const float* startPos, const float* endPos,
|
||||||
|
const dtPolyRef* path, const int pathSize,
|
||||||
|
float* straightPath, const int maxStraightPathSize);
|
||||||
|
|
||||||
|
// Finds intersection againts walls starting from start pos.
|
||||||
|
// Params:
|
||||||
|
// startRef - (in) ref to the polygon where the start lies.
|
||||||
|
// startPos - (in) start position of the query.
|
||||||
|
// endPos - (in) end position of the query.
|
||||||
|
// t - (out) hit parameter along the segment, valid only if hit.
|
||||||
|
// endRef - (out) ref to the last polygon which was processed.
|
||||||
|
// Returns: True if hit wall.
|
||||||
|
// TODO: Return the whole corridor!!
|
||||||
|
bool raycast(dtPolyRef startRef, const float* startPos, const float* endPos, float& t, dtPolyRef& endRef);
|
||||||
|
|
||||||
|
// Returns distance to nearest wall from the specified location.
|
||||||
|
// Params:
|
||||||
|
// centerRef - (in) ref to the polygon where the center lies.
|
||||||
|
// centerPos - (in) center if the query circle.
|
||||||
|
// maxRadius - (in) max search radius.
|
||||||
|
// hitPos - (out) location of the nearest hit.
|
||||||
|
// hitNormal - (out) normal of the nearest hit.
|
||||||
|
// Returns: Distance to nearest wall from the test location.
|
||||||
|
float findDistanceToWall(dtPolyRef centerRef, const float* centerPos, float maxRadius,
|
||||||
|
float* hitPos, float* hitNormal);
|
||||||
|
|
||||||
|
// Finds polygons found along the navigation graph which touch the specified circle.
|
||||||
|
// Params:
|
||||||
|
// centerRef - (in) ref to the polygon where the center lies.
|
||||||
|
// centerPos - (in) center if the query circle
|
||||||
|
// radius - (in) radius of the query circle
|
||||||
|
// resultRef - (out, opt) refs to the polygons touched by the circle.
|
||||||
|
// resultParent - (out, opt) parent of each result polygon.
|
||||||
|
// resultCost - (out, opt) search cost at each result polygon.
|
||||||
|
// resultDepth - (out, opt) search depth at each result polygon.
|
||||||
|
// maxResult - (int) maximum capacity of search results.
|
||||||
|
// Returns: Number of results.
|
||||||
|
int findPolysAround(dtPolyRef centerRef, const float* centerPos, float radius,
|
||||||
|
dtPolyRef* resultRef, dtPolyRef* resultParent,
|
||||||
|
unsigned short* resultCost, unsigned short* resultDepth,
|
||||||
|
const int maxResult);
|
||||||
|
|
||||||
|
// Returns closest point on navigation polygon.
|
||||||
|
// Params:
|
||||||
|
// ref - (in) ref to the polygon.
|
||||||
|
// pos - (in) the point to check.
|
||||||
|
// closest - (out) closest point.
|
||||||
|
bool closestPointToPoly(dtPolyRef ref, const float* pos, float* closest) const;
|
||||||
|
|
||||||
|
// Returns cost between two polygons.
|
||||||
|
unsigned short getCost(dtPolyRef from, dtPolyRef to) const;
|
||||||
|
|
||||||
|
// Returns pointer to a polygon based on ref.
|
||||||
|
const dtPoly* getPolyByRef(dtPolyRef ref) const;
|
||||||
|
// Returns number of navigation polygons.
|
||||||
|
inline int getPolyCount() const { return m_header ? m_header->npolys : 0; }
|
||||||
|
// Rerturns pointer to specified navigation polygon.
|
||||||
|
inline const dtPoly* getPoly(int i) const { return &m_polys[i]; }
|
||||||
|
// Returns number of vertices.
|
||||||
|
inline int getVertexCount() const { return m_header ? m_header->nverts : 0; }
|
||||||
|
// Returns pointer to specified vertex.
|
||||||
|
inline const float* getVertex(int i) const { return &m_verts[i*3]; }
|
||||||
|
|
||||||
|
bool isInOpenList(dtPolyRef ref) const;
|
||||||
|
|
||||||
|
int getMemUsed() const;
|
||||||
|
|
||||||
|
inline const dtStatNavMeshHeader* getHeader() const { return m_header; }
|
||||||
|
|
||||||
|
inline const dtBVNode* getBvTreeNodes() const { return m_bvtree; }
|
||||||
|
inline int getBvTreeNodeCount() const { return m_header->nnodes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Copies the locations of vertices of a polygon to an array.
|
||||||
|
int getPolyVerts(dtPolyRef ref, float* verts);
|
||||||
|
// Returns portal points between two polygons.
|
||||||
|
bool getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right);
|
||||||
|
|
||||||
|
unsigned char* m_data;
|
||||||
|
int m_dataSize;
|
||||||
|
|
||||||
|
dtStatNavMeshHeader* m_header;
|
||||||
|
dtPoly* m_polys;
|
||||||
|
float* m_verts;
|
||||||
|
dtBVNode* m_bvtree;
|
||||||
|
|
||||||
|
class dtNodePool* m_nodePool;
|
||||||
|
class dtNodeQueue* m_openList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DETOURSTATNAVMESH_H
|
27
Detour/Include/DetourStatNavMeshBuilder.h
Executable file
27
Detour/Include/DetourStatNavMeshBuilder.h
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DETOURSTATNAVMESHBUILDER_H
|
||||||
|
#define DETOURSTATNAVMESHBUILDER_H
|
||||||
|
|
||||||
|
bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
|
||||||
|
const unsigned short* polys, const int npolys, const int nvp,
|
||||||
|
const float* bmin, const float* bmax, float cs, float ch,
|
||||||
|
unsigned char** outData, int* outDataSize);
|
||||||
|
|
||||||
|
#endif // DETOURSTATNAVMESHBUILDER_H
|
183
Detour/Source/DetourDebugDraw.cpp
Executable file
183
Detour/Source/DetourDebugDraw.cpp
Executable file
@ -0,0 +1,183 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "DetourDebugDraw.h"
|
||||||
|
#include "DetourStatNavMesh.h"
|
||||||
|
#include "SDL.h"
|
||||||
|
#include "SDL_Opengl.h"
|
||||||
|
|
||||||
|
void dtDebugDrawStatNavMeshPoly(const dtStatNavMesh* mesh, dtPolyRef ref, const float* col)
|
||||||
|
{
|
||||||
|
const dtPoly* p = mesh->getPolyByRef(ref);
|
||||||
|
if (!p)
|
||||||
|
return;
|
||||||
|
glColor4f(col[0],col[1],col[2],0.25f);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
unsigned short vi[3];
|
||||||
|
for (int j = 2; j < (int)p->nv; ++j)
|
||||||
|
{
|
||||||
|
vi[0] = p->v[0];
|
||||||
|
vi[1] = p->v[j-1];
|
||||||
|
vi[2] = p->v[j];
|
||||||
|
for (int k = 0; k < 3; ++k)
|
||||||
|
{
|
||||||
|
const float* v = mesh->getVertex(vi[k]);
|
||||||
|
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, const float* col)
|
||||||
|
{
|
||||||
|
glColor4fv(col);
|
||||||
|
|
||||||
|
// Top
|
||||||
|
glVertex3f(minx, miny, minz);
|
||||||
|
glVertex3f(maxx, miny, minz);
|
||||||
|
glVertex3f(maxx, miny, minz);
|
||||||
|
glVertex3f(maxx, miny, maxz);
|
||||||
|
glVertex3f(maxx, miny, maxz);
|
||||||
|
glVertex3f(minx, miny, maxz);
|
||||||
|
glVertex3f(minx, miny, maxz);
|
||||||
|
glVertex3f(minx, miny, minz);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
glVertex3f(minx, maxy, minz);
|
||||||
|
glVertex3f(maxx, maxy, minz);
|
||||||
|
glVertex3f(maxx, maxy, minz);
|
||||||
|
glVertex3f(maxx, maxy, maxz);
|
||||||
|
glVertex3f(maxx, maxy, maxz);
|
||||||
|
glVertex3f(minx, maxy, maxz);
|
||||||
|
glVertex3f(minx, maxy, maxz);
|
||||||
|
glVertex3f(minx, maxy, minz);
|
||||||
|
|
||||||
|
// Sides
|
||||||
|
glVertex3f(minx, miny, minz);
|
||||||
|
glVertex3f(minx, maxy, minz);
|
||||||
|
glVertex3f(maxx, miny, minz);
|
||||||
|
glVertex3f(maxx, maxy, minz);
|
||||||
|
glVertex3f(maxx, miny, maxz);
|
||||||
|
glVertex3f(maxx, maxy, maxz);
|
||||||
|
glVertex3f(minx, miny, maxz);
|
||||||
|
glVertex3f(minx, maxy, maxz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtDebugDrawStatNavMeshBVTree(const dtStatNavMesh* mesh)
|
||||||
|
{
|
||||||
|
const float col[] = { 1,1,1,0.5f };
|
||||||
|
const dtStatNavMeshHeader* hdr = mesh->getHeader();
|
||||||
|
|
||||||
|
const dtBVNode* nodes = mesh->getBvTreeNodes();
|
||||||
|
int nnodes = mesh->getBvTreeNodeCount();
|
||||||
|
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
|
||||||
|
for (int i = 0; i < nnodes; ++i)
|
||||||
|
{
|
||||||
|
const dtBVNode* n = &nodes[i];
|
||||||
|
if (n->i < 0) // Leaf indices are positive.
|
||||||
|
continue;
|
||||||
|
drawBoxWire(hdr->bmin[0] + n->bmin[0]*hdr->cs,
|
||||||
|
hdr->bmin[1] + n->bmin[1]*hdr->cs,
|
||||||
|
hdr->bmin[2] + n->bmin[2]*hdr->cs,
|
||||||
|
hdr->bmin[0] + n->bmax[0]*hdr->cs,
|
||||||
|
hdr->bmin[1] + n->bmax[1]*hdr->cs,
|
||||||
|
hdr->bmin[2] + n->bmax[2]*hdr->cs, col);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtDebugDrawStatNavMesh(const dtStatNavMesh* mesh)
|
||||||
|
{
|
||||||
|
glColor4ub(0,196,255,64);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
for (int i = 0; i < mesh->getPolyCount(); ++i)
|
||||||
|
{
|
||||||
|
const dtPoly* p = mesh->getPoly(i);
|
||||||
|
unsigned short vi[3];
|
||||||
|
for (int j = 2; j < (int)p->nv; ++j)
|
||||||
|
{
|
||||||
|
vi[0] = p->v[0];
|
||||||
|
vi[1] = p->v[j-1];
|
||||||
|
vi[2] = p->v[j];
|
||||||
|
for (int k = 0; k < 3; ++k)
|
||||||
|
{
|
||||||
|
const float* v = mesh->getVertex(vi[k]);
|
||||||
|
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
// Draw tri boundaries
|
||||||
|
glColor4ub(0,0,0,64);
|
||||||
|
glLineWidth(1.0f);
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
for (int i = 0; i < mesh->getPolyCount(); ++i)
|
||||||
|
{
|
||||||
|
const dtPoly* p = mesh->getPoly(i);
|
||||||
|
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||||
|
{
|
||||||
|
if (p->n[j] == 0) continue;
|
||||||
|
int vi[2];
|
||||||
|
vi[0] = p->v[j];
|
||||||
|
vi[1] = p->v[(j+1) % nj];
|
||||||
|
for (int k = 0; k < 2; ++k)
|
||||||
|
{
|
||||||
|
const float* v = mesh->getVertex(vi[k]);
|
||||||
|
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
// Draw boundaries
|
||||||
|
glLineWidth(3.0f);
|
||||||
|
glColor4ub(0,0,0,128);
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
for (int i = 0; i < mesh->getPolyCount(); ++i)
|
||||||
|
{
|
||||||
|
const dtPoly* p = mesh->getPoly(i);
|
||||||
|
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||||
|
{
|
||||||
|
if (p->n[j] != 0) continue;
|
||||||
|
int vi[2];
|
||||||
|
vi[0] = p->v[j];
|
||||||
|
vi[1] = p->v[(j+1) % nj];
|
||||||
|
for (int k = 0; k < 2; ++k)
|
||||||
|
{
|
||||||
|
const float* v = mesh->getVertex(vi[k]);
|
||||||
|
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
glLineWidth(1.0f);
|
||||||
|
|
||||||
|
glPointSize(4.0f);
|
||||||
|
glColor4ub(0,0,0,128);
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
for (int i = 0; i < mesh->getVertexCount(); ++i)
|
||||||
|
{
|
||||||
|
const float* v = mesh->getVertex(i);
|
||||||
|
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
glPointSize(1.0f);
|
||||||
|
}
|
1314
Detour/Source/DetourStatNavMesh.cpp
Executable file
1314
Detour/Source/DetourStatNavMesh.cpp
Executable file
File diff suppressed because it is too large
Load Diff
291
Detour/Source/DetourStatNavMeshBuilder.cpp
Executable file
291
Detour/Source/DetourStatNavMeshBuilder.cpp
Executable file
@ -0,0 +1,291 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2009 Mikko Mononen memon@inside.org
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "DetourStatNavMesh.h"
|
||||||
|
|
||||||
|
struct BVItem
|
||||||
|
{
|
||||||
|
unsigned short bmin[3];
|
||||||
|
unsigned short bmax[3];
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int compareItemX(const void* va, const void* vb)
|
||||||
|
{
|
||||||
|
const BVItem* a = (const BVItem*)va;
|
||||||
|
const BVItem* b = (const BVItem*)vb;
|
||||||
|
if (a->bmin[0] < b->bmin[0])
|
||||||
|
return -1;
|
||||||
|
if (a->bmin[0] > b->bmin[0])
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compareItemY(const void* va, const void* vb)
|
||||||
|
{
|
||||||
|
const BVItem* a = (const BVItem*)va;
|
||||||
|
const BVItem* b = (const BVItem*)vb;
|
||||||
|
if (a->bmin[1] < b->bmin[1])
|
||||||
|
return -1;
|
||||||
|
if (a->bmin[1] > b->bmin[1])
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compareItemZ(const void* va, const void* vb)
|
||||||
|
{
|
||||||
|
const BVItem* a = (const BVItem*)va;
|
||||||
|
const BVItem* b = (const BVItem*)vb;
|
||||||
|
if (a->bmin[2] < b->bmin[2])
|
||||||
|
return -1;
|
||||||
|
if (a->bmin[2] > b->bmin[2])
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcExtends(BVItem* items, int nitems, int imin, int imax,
|
||||||
|
unsigned short* bmin, unsigned short* bmax)
|
||||||
|
{
|
||||||
|
bmin[0] = items[imin].bmin[0];
|
||||||
|
bmin[1] = items[imin].bmin[1];
|
||||||
|
bmin[2] = items[imin].bmin[2];
|
||||||
|
|
||||||
|
bmax[0] = items[imin].bmax[0];
|
||||||
|
bmax[1] = items[imin].bmax[1];
|
||||||
|
bmax[2] = items[imin].bmax[2];
|
||||||
|
|
||||||
|
for (unsigned i = imin+1; i < imax; ++i)
|
||||||
|
{
|
||||||
|
const BVItem& it = items[i];
|
||||||
|
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
|
||||||
|
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
|
||||||
|
if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2];
|
||||||
|
|
||||||
|
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
|
||||||
|
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
|
||||||
|
if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int longestAxis(unsigned short x, unsigned short y, unsigned short z)
|
||||||
|
{
|
||||||
|
int axis = 0;
|
||||||
|
unsigned short maxVal = x;
|
||||||
|
if (y > maxVal)
|
||||||
|
{
|
||||||
|
axis = 1;
|
||||||
|
maxVal = y;
|
||||||
|
}
|
||||||
|
if (z > maxVal)
|
||||||
|
{
|
||||||
|
axis = 2;
|
||||||
|
maxVal = z;
|
||||||
|
}
|
||||||
|
return axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNode, dtBVNode* nodes)
|
||||||
|
{
|
||||||
|
int inum = imax - imin;
|
||||||
|
int icur = curNode;
|
||||||
|
|
||||||
|
dtBVNode& node = nodes[curNode++];
|
||||||
|
|
||||||
|
if (inum == 1)
|
||||||
|
{
|
||||||
|
// Leaf
|
||||||
|
node.bmin[0] = items[imin].bmin[0];
|
||||||
|
node.bmin[1] = items[imin].bmin[1];
|
||||||
|
node.bmin[2] = items[imin].bmin[2];
|
||||||
|
|
||||||
|
node.bmax[0] = items[imin].bmax[0];
|
||||||
|
node.bmax[1] = items[imin].bmax[1];
|
||||||
|
node.bmax[2] = items[imin].bmax[2];
|
||||||
|
|
||||||
|
node.i = items[imin].i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Split
|
||||||
|
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||||
|
|
||||||
|
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||||
|
node.bmax[1] - node.bmin[1],
|
||||||
|
node.bmax[2] - node.bmin[2]);
|
||||||
|
|
||||||
|
if (axis == 0)
|
||||||
|
{
|
||||||
|
// Sort along x-axis
|
||||||
|
qsort(items+imin, inum, sizeof(BVItem), compareItemX);
|
||||||
|
}
|
||||||
|
else if (axis == 1)
|
||||||
|
{
|
||||||
|
// Sort along y-axis
|
||||||
|
qsort(items+imin, inum, sizeof(BVItem), compareItemY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Sort along z-axis
|
||||||
|
qsort(items+imin, inum, sizeof(BVItem), compareItemZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isplit = imin+inum/2;
|
||||||
|
|
||||||
|
// Left
|
||||||
|
subdivide(items, nitems, imin, isplit, curNode, nodes);
|
||||||
|
// Right
|
||||||
|
subdivide(items, nitems, isplit, imax, curNode, nodes);
|
||||||
|
|
||||||
|
int iescape = curNode - icur;
|
||||||
|
// Negative index means escape.
|
||||||
|
node.i = -iescape;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*struct rcPolyMesh
|
||||||
|
{
|
||||||
|
inline rcPolyMesh() : verts(0), polys(0), nverts(0), npolys(0), nvp(3) {}
|
||||||
|
inline ~rcPolyMesh() { delete [] verts; delete [] polys; }
|
||||||
|
unsigned short* verts;
|
||||||
|
unsigned short* polys;
|
||||||
|
int nverts;
|
||||||
|
int npolys;
|
||||||
|
int nvp;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
int createBVTree(const unsigned short* verts, const int nverts,
|
||||||
|
const unsigned short* polys, const int npolys, const int nvp,
|
||||||
|
float cs, float ch,
|
||||||
|
int nnodes, dtBVNode* nodes)
|
||||||
|
{
|
||||||
|
// Build tree
|
||||||
|
BVItem* items = new BVItem[npolys];
|
||||||
|
for (int i = 0; i < npolys; i++)
|
||||||
|
{
|
||||||
|
BVItem& it = items[i];
|
||||||
|
it.i = i+1;
|
||||||
|
// Calc polygon bounds.
|
||||||
|
const unsigned short* p = &polys[i*nvp*2];
|
||||||
|
it.bmin[0] = it.bmax[0] = verts[p[0]*3+0];
|
||||||
|
it.bmin[1] = it.bmax[1] = verts[p[0]*3+1];
|
||||||
|
it.bmin[2] = it.bmax[2] = verts[p[0]*3+2];
|
||||||
|
|
||||||
|
for (int j = 1; j < nvp; ++j)
|
||||||
|
{
|
||||||
|
if (p[j] == 0xffff) break;
|
||||||
|
unsigned short x = verts[p[j]*3+0];
|
||||||
|
unsigned short y = verts[p[j]*3+1];
|
||||||
|
unsigned short z = verts[p[j]*3+2];
|
||||||
|
|
||||||
|
if (x < it.bmin[0]) it.bmin[0] = x;
|
||||||
|
if (y < it.bmin[1]) it.bmin[1] = y;
|
||||||
|
if (z < it.bmin[2]) it.bmin[2] = z;
|
||||||
|
|
||||||
|
if (x > it.bmax[0]) it.bmax[0] = x;
|
||||||
|
if (y > it.bmax[1]) it.bmax[1] = y;
|
||||||
|
if (z > it.bmax[2]) it.bmax[2] = z;
|
||||||
|
}
|
||||||
|
// Remap y
|
||||||
|
it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs);
|
||||||
|
it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int curNode = 0;
|
||||||
|
subdivide(items, npolys, 0, npolys, curNode, nodes);
|
||||||
|
|
||||||
|
delete [] items;
|
||||||
|
|
||||||
|
return curNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
|
||||||
|
const unsigned short* polys, const int npolys, const int nvp,
|
||||||
|
const float* bmin, const float* bmax, float cs, float ch,
|
||||||
|
unsigned char** outData, int* outDataSize)
|
||||||
|
{
|
||||||
|
if (nvp != DT_VERTS_PER_POLYGON)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Calculate data size
|
||||||
|
const int headerSize = sizeof(dtStatNavMeshHeader);
|
||||||
|
const int vertsSize = sizeof(float)*3*nverts;
|
||||||
|
const int polysSize = sizeof(dtPoly)*npolys;
|
||||||
|
const int nodesSize = sizeof(dtBVNode)*npolys*2;
|
||||||
|
|
||||||
|
const int dataSize = headerSize + vertsSize + polysSize + nodesSize;
|
||||||
|
unsigned char* data = new unsigned char[dataSize];
|
||||||
|
if (!data)
|
||||||
|
return false;
|
||||||
|
memset(data, 0, dataSize);
|
||||||
|
|
||||||
|
dtStatNavMeshHeader* header = (dtStatNavMeshHeader*)(data);
|
||||||
|
float* navVerts = (float*)(data + headerSize);
|
||||||
|
dtPoly* navPolys = (dtPoly*)(data + headerSize + vertsSize);
|
||||||
|
dtBVNode* nodes = (dtBVNode*)(data + headerSize + vertsSize + polysSize);
|
||||||
|
|
||||||
|
// Store header
|
||||||
|
header->magic = DT_NAVMESH_MAGIC;
|
||||||
|
header->version = DT_NAVMESH_VERSION;
|
||||||
|
header->npolys = npolys;
|
||||||
|
header->nverts = nverts;
|
||||||
|
header->cs = cs;
|
||||||
|
header->bmin[0] = bmin[0];
|
||||||
|
header->bmin[1] = bmin[1];
|
||||||
|
header->bmin[2] = bmin[2];
|
||||||
|
header->bmax[0] = bmax[0];
|
||||||
|
header->bmax[1] = bmax[1];
|
||||||
|
header->bmax[2] = bmax[2];
|
||||||
|
|
||||||
|
// Store vertices
|
||||||
|
for (int i = 0; i < nverts; ++i)
|
||||||
|
{
|
||||||
|
const unsigned short* iv = &verts[i*3];
|
||||||
|
float* v = &navVerts[i*3];
|
||||||
|
v[0] = bmin[0] + iv[0] * cs;
|
||||||
|
v[1] = bmin[1] + iv[1] * ch;
|
||||||
|
v[2] = bmin[2] + iv[2] * cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store polygons
|
||||||
|
const unsigned short* src = polys;
|
||||||
|
for (int i = 0; i < npolys; ++i)
|
||||||
|
{
|
||||||
|
dtPoly* p = &navPolys[i];
|
||||||
|
p->nv = 0;
|
||||||
|
for (int j = 0; j < nvp; ++j)
|
||||||
|
{
|
||||||
|
if (src[j] == 0xffff) break;
|
||||||
|
p->v[j] = src[j];
|
||||||
|
p->n[j] = src[nvp+j]+1;
|
||||||
|
p->nv++;
|
||||||
|
}
|
||||||
|
src += nvp*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
header->nnodes = createBVTree(verts, nverts, polys, npolys, nvp,
|
||||||
|
cs, ch, npolys*2, nodes);
|
||||||
|
|
||||||
|
*outData = data;
|
||||||
|
*outDataSize = dataSize;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -35,6 +35,12 @@ The project files with this distribution can be compiled with Microsoft Visual C
|
|||||||
|
|
||||||
Release Notes
|
Release Notes
|
||||||
|
|
||||||
|
----------------
|
||||||
|
* Recast 1.1
|
||||||
|
Released April 11th, 2009
|
||||||
|
|
||||||
|
This is the first release of Detour.
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
* Recast 1.0
|
* Recast 1.0
|
||||||
Released March 29th, 2009
|
Released March 29th, 2009
|
||||||
|
@ -384,10 +384,10 @@ static int countPolyVerts(const unsigned short* p, const int nvp)
|
|||||||
return nvp;
|
return nvp;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool uleftOn(const unsigned short* a, const unsigned short* b, const unsigned short* c)
|
inline bool uleft(const unsigned short* a, const unsigned short* b, const unsigned short* c)
|
||||||
{
|
{
|
||||||
return ((int)b[0] - (int)a[0]) * ((int)c[2] - (int)a[2]) -
|
return ((int)b[0] - (int)a[0]) * ((int)c[2] - (int)a[2]) -
|
||||||
((int)c[0] - (int)a[0]) * ((int)b[2] - (int)a[2]) <= 0;
|
((int)c[0] - (int)a[0]) * ((int)b[2] - (int)a[2]) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getPolyMergeValue(unsigned short* pa, unsigned short* pb,
|
static int getPolyMergeValue(unsigned short* pa, unsigned short* pb,
|
||||||
@ -436,13 +436,13 @@ static int getPolyMergeValue(unsigned short* pa, unsigned short* pb,
|
|||||||
va = pa[(ea+na-1) % na];
|
va = pa[(ea+na-1) % na];
|
||||||
vb = pa[ea];
|
vb = pa[ea];
|
||||||
vc = pb[(eb+2) % nb];
|
vc = pb[(eb+2) % nb];
|
||||||
if (!uleftOn(&verts[va*3], &verts[vb*3], &verts[vc*3]))
|
if (!uleft(&verts[va*3], &verts[vb*3], &verts[vc*3]))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
va = pb[(eb+nb-1) % nb];
|
va = pb[(eb+nb-1) % nb];
|
||||||
vb = pb[eb];
|
vb = pb[eb];
|
||||||
vc = pa[(ea+2) % na];
|
vc = pa[(ea+2) % na];
|
||||||
if (!uleftOn(&verts[va*3], &verts[vb*3], &verts[vc*3]))
|
if (!uleft(&verts[va*3], &verts[vb*3], &verts[vc*3]))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
va = pa[ea];
|
va = pa[ea];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user