Area progress: Pass area type and ability flags to recast. Convex Area tool. Mark chf with convex volumes. Better visualization of volumes.

This commit is contained in:
Mikko Mononen 2010-02-05 16:15:49 +00:00
parent 8561fb6d00
commit a715e9a5f7
21 changed files with 5324 additions and 655 deletions

View File

@ -49,7 +49,7 @@ static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshHeader* header,
{ {
const dtPoly* p = &header->polys[i]; const dtPoly* p = &header->polys[i];
if (p->flags & DT_POLY_OFFMESH_CONNECTION) continue; if (p->type == DT_POLYTYPE_OFFMESH_CONNECTION) continue;
const dtPolyDetail* pd = &header->detailMeshes[i]; const dtPolyDetail* pd = &header->detailMeshes[i];
@ -126,7 +126,7 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTil
for (int i = 0; i < header->polyCount; ++i) for (int i = 0; i < header->polyCount; ++i)
{ {
const dtPoly* p = &header->polys[i]; const dtPoly* p = &header->polys[i];
if (p->flags & DT_POLY_OFFMESH_CONNECTION) // Skip off-mesh links. if (p->type == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links.
continue; continue;
const dtPolyDetail* pd = &header->detailMeshes[i]; const dtPolyDetail* pd = &header->detailMeshes[i];
@ -135,7 +135,12 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTil
if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i)) if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,64); col = duRGBA(255,196,0,64);
else else
col = duRGBA(0,196,255,64); {
if (p->area == 0) // Treat zero area type as default.
col = duRGBA(0,192,255,64);
else
col = duIntToCol(p->area, 64);
}
for (int j = 0; j < pd->triCount; ++j) for (int j = 0; j < pd->triCount; ++j)
{ {
@ -163,14 +168,14 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTil
for (int i = 0; i < header->polyCount; ++i) for (int i = 0; i < header->polyCount; ++i)
{ {
const dtPoly* p = &header->polys[i]; const dtPoly* p = &header->polys[i];
if ((p->flags & DT_POLY_OFFMESH_CONNECTION) == 0) // Skip regular polys. if (p->type != DT_POLYTYPE_OFFMESH_CONNECTION) // Skip regular polys.
continue; continue;
unsigned int col; unsigned int col;
if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i)) if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,220); col = duRGBA(255,196,0,220);
else else
col = duRGBA(255,255,255,220); col = duDarkenColor(duIntToCol(p->area, 220));
const dtOffMeshConnection* con = &header->offMeshCons[i - header->offMeshBase]; const dtOffMeshConnection* con = &header->offMeshCons[i - header->offMeshBase];
const float* va = &header->verts[p->verts[0]*3]; const float* va = &header->verts[p->verts[0]*3];
@ -452,7 +457,7 @@ void duDebugDrawNavMeshPoly(duDebugDraw* dd, const dtNavMesh* mesh, dtPolyRef re
const unsigned int c = (col & 0x00ffffff) | (64 << 24); const unsigned int c = (col & 0x00ffffff) | (64 << 24);
if (p->flags & DT_POLY_OFFMESH_CONNECTION) if (p->type == DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
dtOffMeshConnection* con = &header->offMeshCons[ip - header->offMeshBase]; dtOffMeshConnection* con = &header->offMeshCons[ip - header->offMeshBase];

View File

@ -32,6 +32,8 @@ static const unsigned short DT_EXT_LINK = 0x8000;
static const unsigned int DT_NULL_LINK = 0xffffffff; static const unsigned int DT_NULL_LINK = 0xffffffff;
static const unsigned int DT_OFFMESH_CON_BIDIR = 1; static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
static const int DT_MAX_AREAS = 64;
// Flags returned by findStraightPath(). // Flags returned by findStraightPath().
enum dtStraightPathFlags enum dtStraightPathFlags
{ {
@ -41,10 +43,10 @@ enum dtStraightPathFlags
}; };
// Flags describing polygon properties. // Flags describing polygon properties.
enum dtPolyFlags enum dtPolyTypes
{ {
DT_POLY_GROUND = 0x01, // Regular ground polygons. DT_POLYTYPE_GROUND = 0, // Regular ground polygons.
DT_POLY_OFFMESH_CONNECTION = 0x02, // Off-mesh connections. DT_POLYTYPE_OFFMESH_CONNECTION = 1, // Off-mesh connections.
}; };
struct dtQueryFilter struct dtQueryFilter
@ -62,6 +64,8 @@ struct dtPoly
unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly. unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
unsigned short flags; // Flags (see dtPolyFlags). unsigned short flags; // Flags (see dtPolyFlags).
unsigned char vertCount; // Number of vertices. unsigned char vertCount; // Number of vertices.
unsigned char area : 6; // Area ID of the polygon.
unsigned char type : 2; // Polygon type, see dtPolyTypes.
}; };
// Stucture describing polygon detail triangles. // Stucture describing polygon detail triangles.
@ -364,6 +368,17 @@ public:
// Returns: true if over polygon. // Returns: true if over polygon.
bool getPolyHeight(dtPolyRef ref, const float* pos, float* height) const; bool getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
// Sets the pathfinding cost of the specified area.
// Params:
// area - (in) area ID (0-63).
// cost - (int) travel cost of the area.
void setAreaCost(const int area, float cost);
// Returns the pathfinding cost of the specified area.
// Params:
// area - (in) area ID (0-63).
float getAreaCost(const int area) const;
// Returns pointer to a polygon based on ref. // Returns pointer to a polygon based on ref.
const dtPoly* getPolyByRef(dtPolyRef ref) const; const dtPoly* getPolyByRef(dtPolyRef ref) const;
@ -434,6 +449,7 @@ private:
bool closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, const float* pos, float* closest) const; bool closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, const float* pos, float* closest) const;
unsigned short getPolyFlags(dtPolyRef ref); unsigned short getPolyFlags(dtPolyRef ref);
unsigned char getPolyType(dtPolyRef ref);
float getCost(dtPolyRef prev, dtPolyRef from, dtPolyRef to) const; float getCost(dtPolyRef prev, dtPolyRef from, dtPolyRef to) const;
float getFirstCost(const float* pos, dtPolyRef from, dtPolyRef to) const; float getFirstCost(const float* pos, dtPolyRef from, dtPolyRef to) const;
float getLastCost(dtPolyRef from, dtPolyRef to, const float* pos) const; float getLastCost(dtPolyRef from, dtPolyRef to, const float* pos) const;
@ -441,7 +457,7 @@ private:
// Returns portal points between two polygons. // Returns portal points between two polygons.
bool getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, bool getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
unsigned short& fromFlags, unsigned short& toFlags) const; unsigned char& fromType, unsigned char& toType) const;
// Returns edge mid point between two polygons. // Returns edge mid point between two polygons.
bool getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const; bool getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const;
@ -459,6 +475,8 @@ private:
unsigned int m_tileBits; // Number of tile bits in the tile ID. unsigned int m_tileBits; // Number of tile bits in the tile ID.
unsigned int m_polyBits; // Number of poly bits in the tile ID. unsigned int m_polyBits; // Number of poly bits in the tile ID.
float m_areaCost[DT_MAX_AREAS]; // Cost per area.
class dtNodePool* m_nodePool; // Pointer to node pool. class dtNodePool* m_nodePool; // Pointer to node pool.
class dtNodeQueue* m_openList; // Pointer to open list queue. class dtNodeQueue* m_openList; // Pointer to open list queue.
}; };

View File

@ -26,6 +26,8 @@ struct dtNavMeshCreateParams
int vertCount; int vertCount;
// Navmesh polygons // Navmesh polygons
const unsigned short* polys; const unsigned short* polys;
const unsigned short* polyFlags;
const unsigned char* polyAreas;
int polyCount; int polyCount;
int nvp; int nvp;
// Navmesh Detail // Navmesh Detail
@ -37,6 +39,8 @@ struct dtNavMeshCreateParams
// Off-Mesh Connections. // Off-Mesh Connections.
const float* offMeshConVerts; const float* offMeshConVerts;
const float* offMeshConRad; const float* offMeshConRad;
const unsigned short* offMeshConFlags;
const unsigned char* offMeshConAreas;
const unsigned char* offMeshConDir; const unsigned char* offMeshConDir;
int offMeshConCount; int offMeshConCount;
// Settings // Settings

View File

@ -421,7 +421,7 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile)
dtPoly* poly = &header->polys[i]; dtPoly* poly = &header->polys[i];
poly->firstLink = DT_NULL_LINK; poly->firstLink = DT_NULL_LINK;
if (poly->flags & DT_POLY_OFFMESH_CONNECTION) if (poly->type == DT_POLYTYPE_OFFMESH_CONNECTION)
continue; continue;
// Build edge links backwards so that the links will be // Build edge links backwards so that the links will be
@ -827,7 +827,7 @@ bool dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef p
const dtPoly* poly = &header->polys[ip]; const dtPoly* poly = &header->polys[ip];
// Make sure that the current poly is indeed off-mesh link. // Make sure that the current poly is indeed off-mesh link.
if ((poly->flags & DT_POLY_OFFMESH_CONNECTION) == 0) if (poly->type != DT_POLYTYPE_OFFMESH_CONNECTION)
return false; return false;
// Figure out which way to hand out the vertices. // Figure out which way to hand out the vertices.
@ -865,7 +865,7 @@ bool dtNavMesh::getPolyHeight(dtPolyRef ref, const float* pos, float* height) co
if (ip >= (unsigned int)header->polyCount) return false; if (ip >= (unsigned int)header->polyCount) return false;
const dtPoly* poly = &header->polys[ip]; const dtPoly* poly = &header->polys[ip];
if (poly->flags & DT_POLY_OFFMESH_CONNECTION) if (poly->type == DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
const float* v0 = &header->verts[poly->verts[0]*3]; const float* v0 = &header->verts[poly->verts[0]*3];
const float* v1 = &header->verts[poly->verts[1]*3]; const float* v1 = &header->verts[poly->verts[1]*3];
@ -903,6 +903,18 @@ bool dtNavMesh::getPolyHeight(dtPolyRef ref, const float* pos, float* height) co
return false; return false;
} }
void dtNavMesh::setAreaCost(const int area, float cost)
{
if (area >= 0 && area > DT_MAX_AREAS)
m_areaCost[area] = cost;
}
float dtNavMesh::getAreaCost(const int area) const
{
if (area >= 0 && area > DT_MAX_AREAS)
return m_areaCost[area];
return -1;
}
dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents, dtQueryFilter* filter, float* nearestPt) dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents, dtQueryFilter* filter, float* nearestPt)
{ {
@ -1271,8 +1283,8 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
int leftIndex = 0; int leftIndex = 0;
int rightIndex = 0; int rightIndex = 0;
unsigned short leftPolyFlags = 0; unsigned char leftPolyType = 0;
unsigned short rightPolyFlags = 0; unsigned char rightPolyType = 0;
dtPolyRef leftPolyRef = path[0]; dtPolyRef leftPolyRef = path[0];
dtPolyRef rightPolyRef = path[0]; dtPolyRef rightPolyRef = path[0];
@ -1280,12 +1292,12 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
for (int i = 0; i < pathSize; ++i) for (int i = 0; i < pathSize; ++i)
{ {
float left[3], right[3]; float left[3], right[3];
unsigned short fromFlags, toFlags; unsigned char fromType, toType;
if (i+1 < pathSize) if (i+1 < pathSize)
{ {
// Next portal. // Next portal.
if (!getPortalPoints(path[i], path[i+1], left, right, fromFlags, toFlags)) if (!getPortalPoints(path[i], path[i+1], left, right, fromType, toType))
{ {
if (!closestPointOnPolyBoundary(path[i], endPos, closestEndPos)) if (!closestPointOnPolyBoundary(path[i], endPos, closestEndPos))
return 0; return 0;
@ -1306,7 +1318,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(left, closestEndPos); vcopy(left, closestEndPos);
vcopy(right, closestEndPos); vcopy(right, closestEndPos);
fromFlags = toFlags = 0; fromType = toType = DT_POLYTYPE_GROUND;
} }
// Right vertex. // Right vertex.
@ -1314,7 +1326,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{ {
vcopy(portalRight, right); vcopy(portalRight, right);
rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0; rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
rightPolyFlags = toFlags; rightPolyType = toType;
rightIndex = i; rightIndex = i;
} }
else else
@ -1325,7 +1337,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{ {
vcopy(portalRight, right); vcopy(portalRight, right);
rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0; rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
rightPolyFlags = toFlags; rightPolyType = toType;
rightIndex = i; rightIndex = i;
} }
else else
@ -1333,7 +1345,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(portalApex, portalLeft); vcopy(portalApex, portalLeft);
apexIndex = leftIndex; apexIndex = leftIndex;
unsigned char flags = (leftPolyFlags & DT_POLY_OFFMESH_CONNECTION) ? DT_STRAIGHTPATH_OFFMESH_CONNECTION : 0; unsigned char flags = (leftPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) ? DT_STRAIGHTPATH_OFFMESH_CONNECTION : 0;
dtPolyRef ref = leftPolyRef; dtPolyRef ref = leftPolyRef;
if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex)) if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex))
@ -1375,7 +1387,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{ {
vcopy(portalLeft, left); vcopy(portalLeft, left);
leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0; leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
leftPolyFlags = toFlags; leftPolyType = toType;
leftIndex = i; leftIndex = i;
} }
else else
@ -1386,7 +1398,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{ {
vcopy(portalLeft, left); vcopy(portalLeft, left);
leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0; leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
leftPolyFlags = toFlags; leftPolyType = toType;
leftIndex = i; leftIndex = i;
} }
else else
@ -1394,7 +1406,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(portalApex, portalRight); vcopy(portalApex, portalRight);
apexIndex = rightIndex; apexIndex = rightIndex;
unsigned char flags = (rightPolyFlags & DT_POLY_OFFMESH_CONNECTION) ? DT_STRAIGHTPATH_OFFMESH_CONNECTION : 0; unsigned char flags = (rightPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) ? DT_STRAIGHTPATH_OFFMESH_CONNECTION : 0;
dtPolyRef ref = rightPolyRef; dtPolyRef ref = rightPolyRef;
if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex)) if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex))
@ -1474,13 +1486,13 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
const dtPoly* poly = &header->polys[ip]; const dtPoly* poly = &header->polys[ip];
// In case of Off-Mesh link, just snap to the end location and advance over it. // In case of Off-Mesh link, just snap to the end location and advance over it.
if (poly->flags & DT_POLY_OFFMESH_CONNECTION) if (poly->type == DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
if (n+1 < pathSize) if (n+1 < pathSize)
{ {
float left[3], right[3]; float left[3], right[3];
unsigned short fromFlags, toFlags; unsigned char fromType, toType;
if (!getPortalPoints(path[n], path[n+1], left, right, fromFlags, toFlags)) if (!getPortalPoints(path[n], path[n+1], left, right, fromType, toType))
return n; return n;
vcopy(resultPos, endPos); vcopy(resultPos, endPos);
} }
@ -1523,8 +1535,8 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
if (n+1 >= pathSize) if (n+1 >= pathSize)
return n; return n;
float left[3], right[3]; float left[3], right[3];
unsigned short fromFlags, toFlags; unsigned char fromType, toType;
if (!getPortalPoints(path[n], path[n+1], left, right, fromFlags, toFlags)) if (!getPortalPoints(path[n], path[n+1], left, right, fromType, toType))
return n; return n;
// If the clamped point is close to the next portal edge, advance to next poly. // If the clamped point is close to the next portal edge, advance to next poly.
float t; float t;
@ -1540,7 +1552,7 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
// Returns portal points between two polygons. // Returns portal points between two polygons.
bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
unsigned short& fromFlags, unsigned short& toFlags) const unsigned char& fromType, unsigned char& toType) const
{ {
unsigned int salt, it, ip; unsigned int salt, it, ip;
decodePolyId(from, salt, it, ip); decodePolyId(from, salt, it, ip);
@ -1549,7 +1561,7 @@ bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false; if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false;
const dtMeshHeader* fromHeader = m_tiles[it].header; const dtMeshHeader* fromHeader = m_tiles[it].header;
const dtPoly* fromPoly = &fromHeader->polys[ip]; const dtPoly* fromPoly = &fromHeader->polys[ip];
fromFlags = fromPoly->flags; fromType = fromPoly->type;
for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromHeader->links[i].next) for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromHeader->links[i].next)
{ {
@ -1563,9 +1575,9 @@ bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false; if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false;
const dtMeshHeader* toHeader = m_tiles[it].header; const dtMeshHeader* toHeader = m_tiles[it].header;
const dtPoly* toPoly = &toHeader->polys[ip]; const dtPoly* toPoly = &toHeader->polys[ip];
toFlags = toPoly->flags; toType = toPoly->type;
if (fromPoly->flags & DT_POLY_OFFMESH_CONNECTION) if (fromPoly->type == DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
// Find link that points to first vertex. // Find link that points to first vertex.
for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromHeader->links[i].next) for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromHeader->links[i].next)
@ -1581,7 +1593,7 @@ bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float
return false; return false;
} }
if (toPoly->flags & DT_POLY_OFFMESH_CONNECTION) if (toPoly->type == DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
for (unsigned int i = toPoly->firstLink; i != DT_NULL_LINK; i = toHeader->links[i].next) for (unsigned int i = toPoly->firstLink; i != DT_NULL_LINK; i = toHeader->links[i].next)
{ {
@ -1638,8 +1650,8 @@ bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float
bool dtNavMesh::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const bool dtNavMesh::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const
{ {
float left[3], right[3]; float left[3], right[3];
unsigned short fromFlags, toFlags; unsigned char fromType, toType;
if (!getPortalPoints(from, to, left,right, fromFlags, toFlags)) return false; if (!getPortalPoints(from, to, left,right, fromType, toType)) return false;
mid[0] = (left[0]+right[0])*0.5f; mid[0] = (left[0]+right[0])*0.5f;
mid[1] = (left[1]+right[1])*0.5f; mid[1] = (left[1]+right[1])*0.5f;
mid[2] = (left[2]+right[2])*0.5f; mid[2] = (left[2]+right[2])*0.5f;
@ -1658,6 +1670,18 @@ unsigned short dtNavMesh::getPolyFlags(dtPolyRef ref)
return poly->flags; return poly->flags;
} }
unsigned char dtNavMesh::getPolyType(dtPolyRef ref)
{
unsigned int salt, it, ip;
decodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return 0;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return 0;
const dtMeshHeader* header = m_tiles[it].header;
const dtPoly* poly = &header->polys[ip];
return poly->type;
}
int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float* endPos, dtQueryFilter* filter, int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float* endPos, dtQueryFilter* filter,
float& t, float* hitNormal, dtPolyRef* path, const int pathSize) float& t, float* hitNormal, dtPolyRef* path, const int pathSize)
{ {

View File

@ -257,8 +257,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
// Classify off-mesh connection points. We store only the connections // Classify off-mesh connection points. We store only the connections
// whose start point is inside the tile. // whose start point is inside the tile.
unsigned char* offMeshConFlags = new unsigned char [params->offMeshConCount*2]; unsigned char* offMeshConClass = new unsigned char [params->offMeshConCount*2];
if (!offMeshConFlags) if (!offMeshConClass)
return false; return false;
int storedOffMeshConCount = 0; int storedOffMeshConCount = 0;
@ -266,16 +266,16 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i) for (int i = 0; i < params->offMeshConCount; ++i)
{ {
offMeshConFlags[i*2+0] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax); offMeshConClass[i*2+0] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax);
offMeshConFlags[i*2+1] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax); offMeshConClass[i*2+1] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax);
// Cound how many links should be allocated for off-mesh connections. // Cound how many links should be allocated for off-mesh connections.
if (offMeshConFlags[i*2+0] == 0xff) if (offMeshConClass[i*2+0] == 0xff)
offMeshConLinkCount++; offMeshConLinkCount++;
if (offMeshConFlags[i*2+1] == 0xff) if (offMeshConClass[i*2+1] == 0xff)
offMeshConLinkCount++; offMeshConLinkCount++;
if (offMeshConFlags[i*2+0] == 0xff) if (offMeshConClass[i*2+0] == 0xff)
storedOffMeshConCount++; storedOffMeshConCount++;
} }
@ -400,7 +400,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i) for (int i = 0; i < params->offMeshConCount; ++i)
{ {
// Only store connections which start from this tile. // Only store connections which start from this tile.
if (offMeshConFlags[i*2+0] == 0xff) if (offMeshConClass[i*2+0] == 0xff)
{ {
const float* linkv = &params->offMeshConVerts[i*2*3]; const float* linkv = &params->offMeshConVerts[i*2*3];
float* v = &navVerts[(offMeshVertsBase + n*2)*3]; float* v = &navVerts[(offMeshVertsBase + n*2)*3];
@ -417,7 +417,9 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
{ {
dtPoly* p = &navPolys[i]; dtPoly* p = &navPolys[i];
p->vertCount = 0; p->vertCount = 0;
p->flags = DT_POLY_GROUND; p->flags = params->polyFlags[i];
p->area = params->polyAreas[i];
p->type = DT_POLYTYPE_GROUND;
for (int j = 0; j < nvp; ++j) for (int j = 0; j < nvp; ++j)
{ {
if (src[j] == MESH_NULL_IDX) break; if (src[j] == MESH_NULL_IDX) break;
@ -432,13 +434,15 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i) for (int i = 0; i < params->offMeshConCount; ++i)
{ {
// Only store connections which start from this tile. // Only store connections which start from this tile.
if (offMeshConFlags[i*2+0] == 0xff) if (offMeshConClass[i*2+0] == 0xff)
{ {
dtPoly* p = &navPolys[offMeshPolyBase+n]; dtPoly* p = &navPolys[offMeshPolyBase+n];
p->vertCount = 2; p->vertCount = 2;
p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0); p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0);
p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1); p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1);
p->flags = DT_POLY_OFFMESH_CONNECTION; // Off-mesh link poly. p->flags = params->offMeshConFlags[i];
p->area = params->offMeshConAreas[i];
p->type = DT_POLYTYPE_OFFMESH_CONNECTION;
n++; n++;
} }
} }
@ -503,7 +507,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i) for (int i = 0; i < params->offMeshConCount; ++i)
{ {
// Only store connections which start from this tile. // Only store connections which start from this tile.
if (offMeshConFlags[i*2+0] == 0xff) if (offMeshConClass[i*2+0] == 0xff)
{ {
dtOffMeshConnection* con = &offMeshCons[n]; dtOffMeshConnection* con = &offMeshCons[n];
con->poly = offMeshPolyBase + n; con->poly = offMeshPolyBase + n;
@ -513,12 +517,12 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
vcopy(&con->pos[3], &endPts[3]); vcopy(&con->pos[3], &endPts[3]);
con->rad = params->offMeshConRad[i]; con->rad = params->offMeshConRad[i];
con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0; con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
con->side = offMeshConFlags[i*2+1]; con->side = offMeshConClass[i*2+1];
n++; n++;
} }
} }
delete [] offMeshConFlags; delete [] offMeshConClass;
*outData = data; *outData = data;
*outDataSize = dataSize; *outDataSize = dataSize;

View File

@ -159,13 +159,14 @@ struct rcContourSet
// z = bmin[2] + verts[i*3+2]*cs; // z = bmin[2] + verts[i*3+2]*cs;
struct rcPolyMesh struct rcPolyMesh
{ {
inline rcPolyMesh() : verts(0), polys(0), regs(0), areas(0), nverts(0), npolys(0), nvp(3) {} inline rcPolyMesh() : verts(0), polys(0), regs(0), flags(0), areas(0), nverts(0), npolys(0), nvp(3) {}
inline ~rcPolyMesh() { delete [] verts; delete [] polys; delete [] regs; delete [] areas; } inline ~rcPolyMesh() { delete [] verts; delete [] polys; delete [] regs; delete [] flags; delete [] areas; }
unsigned short* verts; // Vertices of the mesh, 3 elements per vertex. unsigned short* verts; // Vertices of the mesh, 3 elements per vertex.
unsigned short* polys; // Polygons of the mesh, nvp*2 elements per polygon. unsigned short* polys; // Polygons of the mesh, nvp*2 elements per polygon.
unsigned short* regs; // Region ID of the polygons. unsigned short* regs; // Region ID of the polygons.
unsigned short* flags; // Per polygon flags.
unsigned char* areas; // Area ID of polygons. unsigned char* areas; // Area ID of polygons.
int nverts; // Number of vertices. int nverts; // Number of vertices.
int npolys; // Number of polygons. int npolys; // Number of polygons.
@ -508,11 +509,31 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
rcHeightfield& hf, rcHeightfield& hf,
rcCompactHeightfield& chf); rcCompactHeightfield& chf);
// Erodes specified area id and replaces the are with null.
// Params:
// areaId - (in) area to erode.
// radius - (in) radius of erosion (max 255).
// chf - (in/out) compact heightfield to erode.
bool rcErodeArea(unsigned char areaId, int radius, rcCompactHeightfield& chf); bool rcErodeArea(unsigned char areaId, int radius, rcCompactHeightfield& chf);
bool rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId, // Marks the area of the convex polygon into the area type of the compact heighfield.
// Params:
// bmin/bmax - (in) bounds of the axis aligned box.
// areaId - (in) area ID to mark.
// chf - (in/out) compact heightfield to mark.
void rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId,
rcCompactHeightfield& chf); rcCompactHeightfield& chf);
// Marks the area of the convex polygon into the area type of the compact heighfield.
// Params:
// verts - (in) vertices of the convex polygon.
// nverts - (in) number of vertices in the polygon.
// hmin/hmax - (in) min and max height of the polygon.
// areaId - (in) area ID to mark.
// chf - (in/out) compact heightfield to mark.
void rcMarkConvexPolyArea(const float* verts, const int nverts,
const float hmin, const float hmax, unsigned char areaId,
rcCompactHeightfield& chf);
// Builds distance field and stores it into the combat heightfield. // Builds distance field and stores it into the combat heightfield.

View File

@ -207,30 +207,35 @@ bool rcErodeArea(unsigned char areaId, int radius, rcCompactHeightfield& chf)
return true; return true;
} }
bool rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId, void rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId,
rcCompactHeightfield& chf) rcCompactHeightfield& chf)
{ {
int minx = (int)floorf((bmin[0]-chf.bmin[0])/chf.cs); int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
int miny = (int)floorf((bmin[1]-chf.bmin[1])/chf.ch); int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
int minz = (int)floorf((bmin[2]-chf.bmin[2])/chf.cs); int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
int maxx = (int)ceilf((bmax[0]-chf.bmin[0])/chf.cs); int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
int maxy = (int)ceilf((bmax[1]-chf.bmin[1])/chf.ch); int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
int maxz = (int)ceilf((bmax[2]-chf.bmin[2])/chf.cs); int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
minx = rcClamp(minx, 0, chf.width); if (maxx < 0) return;
minz = rcClamp(minz, 0, chf.height); if (minx >= chf.width) return;
maxx = rcClamp(maxx, 0, chf.width); if (maxz < 0) return;
maxz = rcClamp(maxz, 0, chf.height); if (minz >= chf.height) return;
for (int z = minz; z < maxz; ++z) if (minx < 0) minx = 0;
if (maxx >= chf.width) maxx = chf.width-1;
if (minz < 0) minz = 0;
if (maxz >= chf.height) maxz = chf.height-1;
for (int z = minz; z <= maxz; ++z)
{ {
for (int x = minx; x < maxx; ++x) for (int x = minx; x <= maxx; ++x)
{ {
const rcCompactCell& c = chf.cells[x+z*chf.width]; const rcCompactCell& c = chf.cells[x+z*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{ {
rcCompactSpan& s = chf.spans[i]; rcCompactSpan& s = chf.spans[i];
if ((int)s.y >= miny && (int)s.y < maxy) if ((int)s.y >= miny && (int)s.y <= maxy)
{ {
if (areaId < chf.areas[i]) if (areaId < chf.areas[i])
chf.areas[i] = areaId; chf.areas[i] = areaId;
@ -238,5 +243,84 @@ bool rcMarkBoxArea(const float* bmin, const float* bmax, unsigned char areaId,
} }
} }
} }
return true;
} }
static int pointInPoly(int nvert, const float* verts, const float* p)
{
int i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++)
{
const float* vi = &verts[i*3];
const float* vj = &verts[j*3];
if (((vi[2] > p[2]) != (vj[2] > p[2])) &&
(p[0] < (vj[0]-vi[0]) * (p[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) )
c = !c;
}
return c;
}
void rcMarkConvexPolyArea(const float* verts, const int nverts,
const float hmin, const float hmax, unsigned char areaId,
rcCompactHeightfield& chf)
{
float bmin[3], bmax[3];
vcopy(bmin, verts);
vcopy(bmax, verts);
for (int i = 1; i < nverts; ++i)
{
vmin(bmin, &verts[i*3]);
vmax(bmax, &verts[i*3]);
}
bmin[1] = hmin;
bmax[1] = hmax;
int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
if (maxx < 0) return;
if (minx >= chf.width) return;
if (maxz < 0) return;
if (minz >= chf.height) return;
if (minx < 0) minx = 0;
if (maxx >= chf.width) maxx = chf.width-1;
if (minz < 0) minz = 0;
if (maxz >= chf.height) maxz = chf.height-1;
// TODO: Optimize.
for (int z = minz; z <= maxz; ++z)
{
for (int x = minx; x <= maxx; ++x)
{
const rcCompactCell& c = chf.cells[x+z*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
rcCompactSpan& s = chf.spans[i];
if ((int)s.y >= miny && (int)s.y <= maxy)
{
if (areaId < chf.areas[i])
{
float p[3];
p[0] = chf.bmin[0] + (x+0.5f)*chf.cs;
p[1] = 0;
p[2] = chf.bmin[2] + (z+0.5f)*chf.cs;
if (pointInPoly(nverts, verts, p))
{
chf.areas[i] = areaId;
}
}
}
}
}
}
}

View File

@ -1067,6 +1067,15 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh)
return false; return false;
} }
// Just allocate the mesh flags array. The user is resposible to fill it.
mesh.flags = new unsigned short[mesh.npolys];
if (!mesh.flags)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.flags' (%d).", mesh.npolys);
return false;
}
rcTimeVal endTime = rcGetPerformanceTimer(); rcTimeVal endTime = rcGetPerformanceTimer();
// if (rcGetLog()) // if (rcGetLog())
@ -1139,6 +1148,15 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
} }
memset(mesh.areas, 0, sizeof(unsigned char)*maxPolys); memset(mesh.areas, 0, sizeof(unsigned char)*maxPolys);
mesh.flags = new unsigned short[maxPolys];
if (!mesh.flags)
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.flags' (%d).", maxPolys);
return false;
}
memset(mesh.flags, 0, sizeof(unsigned short)*maxPolys);
rcScopedDelete<int> nextVert = new int[maxVerts]; rcScopedDelete<int> nextVert = new int[maxVerts];
if (!nextVert) if (!nextVert)
{ {
@ -1187,6 +1205,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
unsigned short* src = &pmesh->polys[j*2*mesh.nvp]; unsigned short* src = &pmesh->polys[j*2*mesh.nvp];
mesh.regs[mesh.npolys] = pmesh->regs[j]; mesh.regs[mesh.npolys] = pmesh->regs[j];
mesh.areas[mesh.npolys] = pmesh->areas[j]; mesh.areas[mesh.npolys] = pmesh->areas[j];
mesh.flags[mesh.npolys] = pmesh->flags[j];
mesh.npolys++; mesh.npolys++;
for (int k = 0; k < mesh.nvp; ++k) for (int k = 0; k < mesh.nvp; ++k)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -281,13 +281,14 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key> <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array> <array>
<array> <array>
<integer>55</integer> <integer>43</integer>
<integer>35</integer>
<integer>1</integer> <integer>1</integer>
<integer>0</integer> <integer>0</integer>
</array> </array>
</array> </array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key> <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 606}, {358, 643}}</string> <string>{{0, 269}, {358, 643}}</string>
</dict> </dict>
<key>PBXTopSmartGroupGIDs</key> <key>PBXTopSmartGroupGIDs</key>
<array/> <array/>
@ -322,7 +323,7 @@
<key>PBXProjectModuleGUID</key> <key>PBXProjectModuleGUID</key>
<string>6B8632A30F78115100E2684A</string> <string>6B8632A30F78115100E2684A</string>
<key>PBXProjectModuleLabel</key> <key>PBXProjectModuleLabel</key>
<string>imguiRenderGL.cpp</string> <string>Sample_TileMesh.cpp</string>
<key>PBXSplitModuleInNavigatorKey</key> <key>PBXSplitModuleInNavigatorKey</key>
<dict> <dict>
<key>Split0</key> <key>Split0</key>
@ -330,30 +331,25 @@
<key>PBXProjectModuleGUID</key> <key>PBXProjectModuleGUID</key>
<string>6B8632A40F78115100E2684A</string> <string>6B8632A40F78115100E2684A</string>
<key>PBXProjectModuleLabel</key> <key>PBXProjectModuleLabel</key>
<string>imguiRenderGL.cpp</string> <string>Sample_TileMesh.cpp</string>
<key>_historyCapacity</key> <key>_historyCapacity</key>
<integer>0</integer> <integer>0</integer>
<key>bookmark</key> <key>bookmark</key>
<string>6B324AE9111C07AB00EBD2FD</string> <string>6B324D05111C7B0900EBD2FD</string>
<key>history</key> <key>history</key>
<array> <array>
<string>6B8DE70D10B01BBF00DF20FB</string> <string>6B8DE70D10B01BBF00DF20FB</string>
<string>6BB93D1510CFFC6D00F74F2B</string>
<string>6BBB883C10EA9B6F008FEA1F</string> <string>6BBB883C10EA9B6F008FEA1F</string>
<string>6BB7FDC010F37703006DA0A6</string> <string>6BB7FDC010F37703006DA0A6</string>
<string>6BB7FDC110F37703006DA0A6</string> <string>6BB7FDC110F37703006DA0A6</string>
<string>6BB7FF6D10F4E8E2006DA0A6</string>
<string>6B69739F10FFCA4500984788</string> <string>6B69739F10FFCA4500984788</string>
<string>6BCF341A1105EC43009445BF</string> <string>6BCF341A1105EC43009445BF</string>
<string>6BF7BE1F110F0792002B3F46</string> <string>6BF7BE1F110F0792002B3F46</string>
<string>6BF7C0E511116E74002B3F46</string> <string>6BF7C0E511116E74002B3F46</string>
<string>6BF7C0EE11116E74002B3F46</string>
<string>6BF7C1D01111BCF2002B3F46</string> <string>6BF7C1D01111BCF2002B3F46</string>
<string>6BF7C2441111DAC1002B3F46</string> <string>6BF7C2441111DAC1002B3F46</string>
<string>6BF7C2761112BE4F002B3F46</string> <string>6BF7C2761112BE4F002B3F46</string>
<string>6BF7C2851112C348002B3F46</string> <string>6BF7C2851112C348002B3F46</string>
<string>6BF7C2BD1112D453002B3F46</string>
<string>6BF7C2EF1112D646002B3F46</string>
<string>6BF7C3211112DB82002B3F46</string> <string>6BF7C3211112DB82002B3F46</string>
<string>6BF7C3431112E74B002B3F46</string> <string>6BF7C3431112E74B002B3F46</string>
<string>6BF7C36E1112EB25002B3F46</string> <string>6BF7C36E1112EB25002B3F46</string>
@ -361,48 +357,52 @@
<string>6BF7C394111316AD002B3F46</string> <string>6BF7C394111316AD002B3F46</string>
<string>6BF7C395111316AD002B3F46</string> <string>6BF7C395111316AD002B3F46</string>
<string>6BF7C3CC11131F26002B3F46</string> <string>6BF7C3CC11131F26002B3F46</string>
<string>6BF7C3CF11131F26002B3F46</string>
<string>6BF7C4021113209A002B3F46</string>
<string>6BF7C4641115C514002B3F46</string> <string>6BF7C4641115C514002B3F46</string>
<string>6BF7C4821115C7C4002B3F46</string>
<string>6BF7C4831115C7C4002B3F46</string> <string>6BF7C4831115C7C4002B3F46</string>
<string>6BF7C50D1115DB96002B3F46</string>
<string>6BF7C50E1115DB96002B3F46</string>
<string>6BF7C5241115FA3B002B3F46</string>
<string>6BF7C5BE1116E1C6002B3F46</string>
<string>6BF7C5D41116E3A1002B3F46</string>
<string>6BF7C5E61116E464002B3F46</string>
<string>6BF7C5ED1116F280002B3F46</string>
<string>6BF7C5F91116F346002B3F46</string> <string>6BF7C5F91116F346002B3F46</string>
<string>6BF7C6581117142A002B3F46</string>
<string>6BF7C6591117142A002B3F46</string> <string>6BF7C6591117142A002B3F46</string>
<string>6BF7C67C1117163B002B3F46</string> <string>6BF7C67C1117163B002B3F46</string>
<string>6BF7C67D1117163B002B3F46</string> <string>6BF7C67D1117163B002B3F46</string>
<string>6BF7C68C111720C6002B3F46</string>
<string>6BF7C69A11172159002B3F46</string>
<string>6BF7C69B11172159002B3F46</string> <string>6BF7C69B11172159002B3F46</string>
<string>6BF7C6AA11172278002B3F46</string> <string>6BF7C6AA11172278002B3F46</string>
<string>6BF7C6B1111722A5002B3F46</string>
<string>6BF7C6B5111761C3002B3F46</string>
<string>6B324A7C111BF65400EBD2FD</string> <string>6B324A7C111BF65400EBD2FD</string>
<string>6B324AA7111BF92500EBD2FD</string>
<string>6B324AC1111C00D700EBD2FD</string>
<string>6B324AC2111C00D700EBD2FD</string>
<string>6B324AC3111C00D700EBD2FD</string> <string>6B324AC3111C00D700EBD2FD</string>
<string>6B324AC4111C00D700EBD2FD</string>
<string>6B324AC5111C00D700EBD2FD</string> <string>6B324AC5111C00D700EBD2FD</string>
<string>6B324AC6111C00D700EBD2FD</string>
<string>6B324AC8111C00D700EBD2FD</string>
<string>6B324AC9111C00D700EBD2FD</string>
<string>6B324ACA111C00D700EBD2FD</string> <string>6B324ACA111C00D700EBD2FD</string>
<string>6B324AE6111C07AB00EBD2FD</string> <string>6B324AE6111C07AB00EBD2FD</string>
<string>6B324AE7111C07AB00EBD2FD</string> <string>6B324AEA111C0D9700EBD2FD</string>
<string>6B324AFB111C0F2700EBD2FD</string>
<string>6B324B1F111C10C700EBD2FD</string>
<string>6B324B49111C1AC800EBD2FD</string>
<string>6B324B4F111C1AC800EBD2FD</string>
<string>6B324B50111C1AC800EBD2FD</string>
<string>6B324B51111C1AC800EBD2FD</string>
<string>6B324B52111C1AC800EBD2FD</string>
<string>6B324B71111C1C4F00EBD2FD</string>
<string>6B324B7A111C1C8200EBD2FD</string>
<string>6B324B8A111C1DE600EBD2FD</string>
<string>6B324BB8111C4C2B00EBD2FD</string>
<string>6B324BBB111C4C2B00EBD2FD</string>
<string>6B324C45111C5C5A00EBD2FD</string>
<string>6B324C51111C5D1400EBD2FD</string>
<string>6B324C92111C604500EBD2FD</string>
<string>6B324C9E111C6DD400EBD2FD</string>
<string>6B324CB5111C6EEA00EBD2FD</string>
<string>6B324CC3111C6F6300EBD2FD</string>
<string>6B324CCE111C759F00EBD2FD</string>
<string>6B324CDA111C789800EBD2FD</string>
<string>6B324CF2111C7A9800EBD2FD</string>
<string>6B324CF9111C7B0900EBD2FD</string>
<string>6B324CFA111C7B0900EBD2FD</string>
<string>6B324CFB111C7B0900EBD2FD</string>
<string>6B324CFC111C7B0900EBD2FD</string>
<string>6B324CFD111C7B0900EBD2FD</string>
<string>6B324CFE111C7B0900EBD2FD</string>
</array> </array>
<key>prevStack</key> <key>prevStack</key>
<array> <array>
<string>6B9869FC10DFFA98007D8D84</string> <string>6B9869FC10DFFA98007D8D84</string>
<string>6BBB87E510EA97CC008FEA1F</string> <string>6BBB87E510EA97CC008FEA1F</string>
<string>6BBB87E910EA97CC008FEA1F</string>
<string>6BBB883F10EA9B6F008FEA1F</string> <string>6BBB883F10EA9B6F008FEA1F</string>
<string>6BBB885510EA9ECC008FEA1F</string> <string>6BBB885510EA9ECC008FEA1F</string>
<string>6BBB889D10EAA094008FEA1F</string> <string>6BBB889D10EAA094008FEA1F</string>
@ -412,7 +412,6 @@
<string>6BB7FE2110F37CF7006DA0A6</string> <string>6BB7FE2110F37CF7006DA0A6</string>
<string>6BB7FE2210F37CF7006DA0A6</string> <string>6BB7FE2210F37CF7006DA0A6</string>
<string>6BB7FE5410F3817A006DA0A6</string> <string>6BB7FE5410F3817A006DA0A6</string>
<string>6BB7FECF10F4B5E1006DA0A6</string>
<string>6BB7FF2410F4D699006DA0A6</string> <string>6BB7FF2410F4D699006DA0A6</string>
<string>6BB7FF9610F4E8E2006DA0A6</string> <string>6BB7FF9610F4E8E2006DA0A6</string>
<string>6BB700C310FA3AB1006DA0A6</string> <string>6BB700C310FA3AB1006DA0A6</string>
@ -428,37 +427,26 @@
<string>6BF7C0F611116E74002B3F46</string> <string>6BF7C0F611116E74002B3F46</string>
<string>6BF7C10811116E74002B3F46</string> <string>6BF7C10811116E74002B3F46</string>
<string>6BF7C10E11116E74002B3F46</string> <string>6BF7C10E11116E74002B3F46</string>
<string>6BF7C11511116E74002B3F46</string>
<string>6BF7C16E11119D8F002B3F46</string> <string>6BF7C16E11119D8F002B3F46</string>
<string>6BF7C1E51111BD81002B3F46</string> <string>6BF7C1E51111BD81002B3F46</string>
<string>6BF7C1F21111C0A6002B3F46</string> <string>6BF7C1F21111C0A6002B3F46</string>
<string>6BF7C15711119BB4002B3F46</string> <string>6BF7C15711119BB4002B3F46</string>
<string>6BF7C30C1112D8C1002B3F46</string> <string>6BF7C30C1112D8C1002B3F46</string>
<string>6BF7C399111316AD002B3F46</string>
<string>6BF7C39C111316AD002B3F46</string> <string>6BF7C39C111316AD002B3F46</string>
<string>6BB7FDD910F37703006DA0A6</string> <string>6BB7FDD910F37703006DA0A6</string>
<string>6BF7C16711119C69002B3F46</string> <string>6BF7C16711119C69002B3F46</string>
<string>6BF7C3D711131F26002B3F46</string>
<string>6BF7C3E211131F26002B3F46</string>
<string>6BF7C4661115C514002B3F46</string> <string>6BF7C4661115C514002B3F46</string>
<string>6BF7C4671115C514002B3F46</string>
<string>6BF7C46A1115C514002B3F46</string> <string>6BF7C46A1115C514002B3F46</string>
<string>6BF7C52F1115FA3B002B3F46</string> <string>6BF7C52F1115FA3B002B3F46</string>
<string>6BF7C5F11116F280002B3F46</string>
<string>6BF7C6081116F61A002B3F46</string> <string>6BF7C6081116F61A002B3F46</string>
<string>6BF7C11111116E74002B3F46</string> <string>6BF7C11111116E74002B3F46</string>
<string>6BF7C66A1117142A002B3F46</string> <string>6BF7C66A1117142A002B3F46</string>
<string>6BF7C678111715D1002B3F46</string>
<string>6BF7C6801117163B002B3F46</string> <string>6BF7C6801117163B002B3F46</string>
<string>6BF7C690111720C6002B3F46</string>
<string>6BF7C6A411172253002B3F46</string> <string>6BF7C6A411172253002B3F46</string>
<string>6B324A7E111BF65400EBD2FD</string> <string>6B324A7E111BF65400EBD2FD</string>
<string>6B324AA8111BF92500EBD2FD</string> <string>6B324AA8111BF92500EBD2FD</string>
<string>6B324AA9111BF92500EBD2FD</string> <string>6B324AA9111BF92500EBD2FD</string>
<string>6B324AAA111BF92500EBD2FD</string>
<string>6B324AB5111BFEFD00EBD2FD</string>
<string>6B324AB6111BFEFD00EBD2FD</string> <string>6B324AB6111BFEFD00EBD2FD</string>
<string>6B324ACC111C00D700EBD2FD</string>
<string>6B324ACD111C00D700EBD2FD</string> <string>6B324ACD111C00D700EBD2FD</string>
<string>6B324ACE111C00D700EBD2FD</string> <string>6B324ACE111C00D700EBD2FD</string>
<string>6B324ACF111C00D700EBD2FD</string> <string>6B324ACF111C00D700EBD2FD</string>
@ -468,9 +456,108 @@
<string>6B324AD3111C00D700EBD2FD</string> <string>6B324AD3111C00D700EBD2FD</string>
<string>6B324AD4111C00D700EBD2FD</string> <string>6B324AD4111C00D700EBD2FD</string>
<string>6B324AD5111C00D700EBD2FD</string> <string>6B324AD5111C00D700EBD2FD</string>
<string>6B324AD6111C00D700EBD2FD</string>
<string>6B324AD7111C00D700EBD2FD</string> <string>6B324AD7111C00D700EBD2FD</string>
<string>6B324AE8111C07AB00EBD2FD</string> <string>6B324AE8111C07AB00EBD2FD</string>
<string>6B324AEE111C0D9700EBD2FD</string>
<string>6B324AEF111C0D9700EBD2FD</string>
<string>6B324AF0111C0D9700EBD2FD</string>
<string>6B324B01111C0F2700EBD2FD</string>
<string>6B324B02111C0F2700EBD2FD</string>
<string>6B324B03111C0F2700EBD2FD</string>
<string>6B324B04111C0F2700EBD2FD</string>
<string>6B324B05111C0F2700EBD2FD</string>
<string>6B324B06111C0F2700EBD2FD</string>
<string>6B324B07111C0F2700EBD2FD</string>
<string>6B324B08111C0F2700EBD2FD</string>
<string>6B324B09111C0F2700EBD2FD</string>
<string>6B324B11111C103600EBD2FD</string>
<string>6B324B14111C103600EBD2FD</string>
<string>6B324B15111C103600EBD2FD</string>
<string>6B324B18111C103600EBD2FD</string>
<string>6B324B21111C10C700EBD2FD</string>
<string>6B324B23111C10C700EBD2FD</string>
<string>6B324B33111C153D00EBD2FD</string>
<string>6B324B35111C153D00EBD2FD</string>
<string>6B324B37111C153D00EBD2FD</string>
<string>6B324B39111C153D00EBD2FD</string>
<string>6B324B3A111C153D00EBD2FD</string>
<string>6B324B3B111C153D00EBD2FD</string>
<string>6B324B55111C1AC800EBD2FD</string>
<string>6B324B56111C1AC800EBD2FD</string>
<string>6B324B57111C1AC800EBD2FD</string>
<string>6B324B5A111C1AC800EBD2FD</string>
<string>6B324B5B111C1AC800EBD2FD</string>
<string>6B324B5C111C1AC800EBD2FD</string>
<string>6B324B5D111C1AC800EBD2FD</string>
<string>6B324B5E111C1AC800EBD2FD</string>
<string>6B324B5F111C1AC800EBD2FD</string>
<string>6B324B60111C1AC800EBD2FD</string>
<string>6B324B61111C1AC800EBD2FD</string>
<string>6B324B62111C1AC800EBD2FD</string>
<string>6B324B63111C1AC800EBD2FD</string>
<string>6B324B64111C1AC800EBD2FD</string>
<string>6B324B65111C1AC800EBD2FD</string>
<string>6B324B66111C1AC800EBD2FD</string>
<string>6B324B67111C1AC800EBD2FD</string>
<string>6B324B6C111C1B7500EBD2FD</string>
<string>6B324B74111C1C4F00EBD2FD</string>
<string>6B324B75111C1C4F00EBD2FD</string>
<string>6B324B7D111C1C8200EBD2FD</string>
<string>6B324B82111C1CF000EBD2FD</string>
<string>6B324B87111C1D9700EBD2FD</string>
<string>6B324B8C111C1DE600EBD2FD</string>
<string>6B324BBD111C4C2B00EBD2FD</string>
<string>6B324BBE111C4C2B00EBD2FD</string>
<string>6B324BC1111C4C2B00EBD2FD</string>
<string>6B324C21111C5B8D00EBD2FD</string>
<string>6B324C23111C5B8D00EBD2FD</string>
<string>6B324C25111C5B8D00EBD2FD</string>
<string>6B324C27111C5B8D00EBD2FD</string>
<string>6B324C29111C5B8D00EBD2FD</string>
<string>6B324C2B111C5B8D00EBD2FD</string>
<string>6B324C2D111C5B8D00EBD2FD</string>
<string>6B324C2F111C5B8D00EBD2FD</string>
<string>6B324C30111C5B8D00EBD2FD</string>
<string>6B324C31111C5B8D00EBD2FD</string>
<string>6B324C33111C5B8D00EBD2FD</string>
<string>6B324C34111C5B8D00EBD2FD</string>
<string>6B324C49111C5C5A00EBD2FD</string>
<string>6B324C58111C5D1400EBD2FD</string>
<string>6B324C59111C5D1400EBD2FD</string>
<string>6B324C5D111C5D1400EBD2FD</string>
<string>6B324C5F111C5D1400EBD2FD</string>
<string>6B324C61111C5D1400EBD2FD</string>
<string>6B324C70111C5DDC00EBD2FD</string>
<string>6B324C71111C5DDC00EBD2FD</string>
<string>6B324C79111C5E7C00EBD2FD</string>
<string>6B324C7A111C5E7C00EBD2FD</string>
<string>6B324C7B111C5E7C00EBD2FD</string>
<string>6B324C80111C5EF800EBD2FD</string>
<string>6B324CA4111C6DD400EBD2FD</string>
<string>6B324CA5111C6DD400EBD2FD</string>
<string>6B324CAE111C6E0100EBD2FD</string>
<string>6B324CB7111C6EEA00EBD2FD</string>
<string>6B324CB8111C6EEA00EBD2FD</string>
<string>6B324CB9111C6EEA00EBD2FD</string>
<string>6B324CBA111C6EEA00EBD2FD</string>
<string>6B324CBE111C6F3C00EBD2FD</string>
<string>6B324CC5111C6F6300EBD2FD</string>
<string>6B324CD0111C759F00EBD2FD</string>
<string>6B324CD1111C759F00EBD2FD</string>
<string>6B324CDE111C789800EBD2FD</string>
<string>6B324CDF111C789800EBD2FD</string>
<string>6B324CE0111C789800EBD2FD</string>
<string>6B324CE1111C789800EBD2FD</string>
<string>6B324CE5111C78DA00EBD2FD</string>
<string>6BF7C678111715D1002B3F46</string>
<string>6B324CF4111C7A9800EBD2FD</string>
<string>6B324CF5111C7A9800EBD2FD</string>
<string>6B324CFF111C7B0900EBD2FD</string>
<string>6B324D00111C7B0900EBD2FD</string>
<string>6B324D01111C7B0900EBD2FD</string>
<string>6B324D02111C7B0900EBD2FD</string>
<string>6B324D03111C7B0900EBD2FD</string>
<string>6B324D04111C7B0900EBD2FD</string>
</array> </array>
</dict> </dict>
<key>SplitCount</key> <key>SplitCount</key>
@ -484,18 +571,18 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{0, 0}, {876, 423}}</string> <string>{{0, 0}, {876, 545}}</string>
<key>RubberWindowFrame</key> <key>RubberWindowFrame</key>
<string>11 76 1256 702 0 0 1280 778 </string> <string>11 76 1256 702 0 0 1280 778 </string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXNavigatorGroup</string> <string>PBXNavigatorGroup</string>
<key>Proportion</key> <key>Proportion</key>
<string>423pt</string> <string>545pt</string>
</dict> </dict>
<dict> <dict>
<key>Proportion</key> <key>Proportion</key>
<string>233pt</string> <string>111pt</string>
<key>Tabs</key> <key>Tabs</key>
<array> <array>
<dict> <dict>
@ -509,7 +596,7 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{10, 27}, {876, 88}}</string> <string>{{10, 27}, {876, 48}}</string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>XCDetailModule</string> <string>XCDetailModule</string>
@ -525,7 +612,7 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{10, 27}, {876, 138}}</string> <string>{{10, 27}, {876, 197}}</string>
</dict> </dict>
<key>Module</key> <key>Module</key>
<string>PBXProjectFindModule</string> <string>PBXProjectFindModule</string>
@ -563,7 +650,7 @@
<key>GeometryConfiguration</key> <key>GeometryConfiguration</key>
<dict> <dict>
<key>Frame</key> <key>Frame</key>
<string>{{10, 27}, {876, 206}}</string> <string>{{10, 27}, {876, 84}}</string>
<key>RubberWindowFrame</key> <key>RubberWindowFrame</key>
<string>11 76 1256 702 0 0 1280 778 </string> <string>11 76 1256 702 0 0 1280 778 </string>
</dict> </dict>
@ -672,8 +759,8 @@
<string>yes</string> <string>yes</string>
<key>sizes</key> <key>sizes</key>
<array> <array>
<string>{{0, 0}, {623, 109}}</string> <string>{{0, 0}, {625, 125}}</string>
<string>{{623, 0}, {633, 109}}</string> <string>{{625, 0}, {631, 125}}</string>
</array> </array>
</dict> </dict>
<key>VerticalSplitView</key> <key>VerticalSplitView</key>
@ -688,8 +775,8 @@
<string>yes</string> <string>yes</string>
<key>sizes</key> <key>sizes</key>
<array> <array>
<string>{{0, 0}, {1256, 109}}</string> <string>{{0, 0}, {1256, 125}}</string>
<string>{{0, 109}, {1256, 287}}</string> <string>{{0, 125}, {1256, 271}}</string>
</array> </array>
</dict> </dict>
</dict> </dict>
@ -719,10 +806,10 @@
<string>Value</string> <string>Value</string>
<real>85</real> <real>85</real>
<string>Summary</string> <string>Summary</string>
<real>403</real> <real>401</real>
</array> </array>
<key>Frame</key> <key>Frame</key>
<string>{{623, 0}, {633, 109}}</string> <string>{{625, 0}, {631, 125}}</string>
</dict> </dict>
</dict> </dict>
<key>Module</key> <key>Module</key>
@ -785,6 +872,8 @@
<integer>5</integer> <integer>5</integer>
<key>WindowOrderList</key> <key>WindowOrderList</key>
<array> <array>
<string>6B324BD2111C4F7D00EBD2FD</string>
<string>6B324BD3111C4F7D00EBD2FD</string>
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string> <string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
</array> </array>
<key>WindowString</key> <key>WindowString</key>

View File

@ -25,6 +25,7 @@
6B25B6190FFA62BE004F1BC4 /* Sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B25B6140FFA62BE004F1BC4 /* Sample.cpp */; }; 6B25B6190FFA62BE004F1BC4 /* Sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B25B6140FFA62BE004F1BC4 /* Sample.cpp */; };
6B25B61D0FFA62BE004F1BC4 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; }; 6B25B61D0FFA62BE004F1BC4 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B25B6180FFA62BE004F1BC4 /* main.cpp */; };
6B2AEC530FFB8958005BE9CC /* Sample_TileMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */; }; 6B2AEC530FFB8958005BE9CC /* Sample_TileMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */; };
6B324C66111C5D9A00EBD2FD /* ConvexVolumeTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B324C65111C5D9A00EBD2FD /* ConvexVolumeTool.cpp */; };
6B555DB1100B212E00247EA3 /* imguiRenderGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */; }; 6B555DB1100B212E00247EA3 /* imguiRenderGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */; };
6B62416A103434880002E346 /* RecastMeshDetail.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B624169103434880002E346 /* RecastMeshDetail.cpp */; }; 6B62416A103434880002E346 /* RecastMeshDetail.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B624169103434880002E346 /* RecastMeshDetail.cpp */; };
6B8632DA0F78122C00E2684A /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B8632D90F78122C00E2684A /* SDL.framework */; }; 6B8632DA0F78122C00E2684A /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B8632D90F78122C00E2684A /* SDL.framework */; };
@ -42,7 +43,6 @@
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; }; 6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; };
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; }; 6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; };
6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C13F1111953A002B3F46 /* TestCase.cpp */; }; 6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C13F1111953A002B3F46 /* TestCase.cpp */; };
6BF7C3C511131B1F002B3F46 /* BoxVolumeTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C3C411131B1F002B3F46 /* BoxVolumeTool.cpp */; };
6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C4531115C277002B3F46 /* RecastArea.cpp */; }; 6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BF7C4531115C277002B3F46 /* RecastArea.cpp */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
@ -83,6 +83,8 @@
6B25B6180FFA62BE004F1BC4 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../Source/main.cpp; sourceTree = SOURCE_ROOT; }; 6B25B6180FFA62BE004F1BC4 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../Source/main.cpp; sourceTree = SOURCE_ROOT; };
6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sample_TileMesh.h; path = ../../Include/Sample_TileMesh.h; sourceTree = SOURCE_ROOT; }; 6B2AEC510FFB8946005BE9CC /* Sample_TileMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sample_TileMesh.h; path = ../../Include/Sample_TileMesh.h; sourceTree = SOURCE_ROOT; };
6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Sample_TileMesh.cpp; path = ../../Source/Sample_TileMesh.cpp; sourceTree = SOURCE_ROOT; }; 6B2AEC520FFB8958005BE9CC /* Sample_TileMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Sample_TileMesh.cpp; path = ../../Source/Sample_TileMesh.cpp; sourceTree = SOURCE_ROOT; };
6B324C64111C5D9A00EBD2FD /* ConvexVolumeTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConvexVolumeTool.h; path = ../../Include/ConvexVolumeTool.h; sourceTree = SOURCE_ROOT; };
6B324C65111C5D9A00EBD2FD /* ConvexVolumeTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConvexVolumeTool.cpp; path = ../../Source/ConvexVolumeTool.cpp; sourceTree = SOURCE_ROOT; };
6B555DAE100B211D00247EA3 /* imguiRenderGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imguiRenderGL.h; path = ../../Include/imguiRenderGL.h; sourceTree = SOURCE_ROOT; }; 6B555DAE100B211D00247EA3 /* imguiRenderGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imguiRenderGL.h; path = ../../Include/imguiRenderGL.h; sourceTree = SOURCE_ROOT; };
6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imguiRenderGL.cpp; path = ../../Source/imguiRenderGL.cpp; sourceTree = SOURCE_ROOT; }; 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imguiRenderGL.cpp; path = ../../Source/imguiRenderGL.cpp; sourceTree = SOURCE_ROOT; };
6B555DF6100B273500247EA3 /* stb_truetype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_truetype.h; path = ../../Contrib/stb_truetype.h; sourceTree = SOURCE_ROOT; }; 6B555DF6100B273500247EA3 /* stb_truetype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_truetype.h; path = ../../Contrib/stb_truetype.h; sourceTree = SOURCE_ROOT; };
@ -115,8 +117,6 @@
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; }; 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; };
6BF7C13E11119520002B3F46 /* TestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestCase.h; path = ../../Include/TestCase.h; sourceTree = SOURCE_ROOT; }; 6BF7C13E11119520002B3F46 /* TestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestCase.h; path = ../../Include/TestCase.h; sourceTree = SOURCE_ROOT; };
6BF7C13F1111953A002B3F46 /* TestCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestCase.cpp; path = ../../Source/TestCase.cpp; sourceTree = SOURCE_ROOT; }; 6BF7C13F1111953A002B3F46 /* TestCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestCase.cpp; path = ../../Source/TestCase.cpp; sourceTree = SOURCE_ROOT; };
6BF7C3C311131B0F002B3F46 /* BoxVolumeTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BoxVolumeTool.h; path = ../../Include/BoxVolumeTool.h; sourceTree = SOURCE_ROOT; };
6BF7C3C411131B1F002B3F46 /* BoxVolumeTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BoxVolumeTool.cpp; path = ../../Source/BoxVolumeTool.cpp; sourceTree = SOURCE_ROOT; };
6BF7C4531115C277002B3F46 /* RecastArea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastArea.cpp; path = ../../../Recast/Source/RecastArea.cpp; sourceTree = SOURCE_ROOT; }; 6BF7C4531115C277002B3F46 /* RecastArea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastArea.cpp; path = ../../../Recast/Source/RecastArea.cpp; sourceTree = SOURCE_ROOT; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Recast.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Recast.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8D1107320486CEB800E47090 /* Recast.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Recast.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -270,12 +270,12 @@
6BB7FE8E10F4A175006DA0A6 /* Tools */ = { 6BB7FE8E10F4A175006DA0A6 /* Tools */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
6B324C64111C5D9A00EBD2FD /* ConvexVolumeTool.h */,
6B324C65111C5D9A00EBD2FD /* ConvexVolumeTool.cpp */,
6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */, 6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */,
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */, 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */,
6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */, 6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */,
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */, 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */,
6BF7C3C311131B0F002B3F46 /* BoxVolumeTool.h */,
6BF7C3C411131B1F002B3F46 /* BoxVolumeTool.cpp */,
); );
name = Tools; name = Tools;
sourceTree = "<group>"; sourceTree = "<group>";
@ -397,8 +397,8 @@
6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */, 6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */,
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */, 6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */,
6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */, 6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */,
6BF7C3C511131B1F002B3F46 /* BoxVolumeTool.cpp in Sources */,
6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */, 6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */,
6B324C66111C5D9A00EBD2FD /* ConvexVolumeTool.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -1,47 +0,0 @@
//
// 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 BOXVOLUMETOOL_H
#define BOXVOLUMETOOL_H
#include "Sample.h"
// Tool to create box volumess for InputGeom
class BoxVolumeTool : public SampleTool
{
Sample* m_sample;
float m_hitPos[3];
bool m_hitPosSet;
float m_areaType;
float m_boxHeight;
public:
BoxVolumeTool();
~BoxVolumeTool();
virtual int type() { return TOOL_BOX_VOLUME; }
virtual void init(Sample* sample);
virtual void reset();
virtual void handleMenu();
virtual void handleClick(const float* p, bool shift);
virtual void handleRender();
virtual void handleRenderOverlay(double* proj, double* model, int* view);
};
#endif // BOXVOLUMETOOL_H

View File

@ -22,6 +22,15 @@
#include "ChunkyTriMesh.h" #include "ChunkyTriMesh.h"
#include "MeshLoaderObj.h" #include "MeshLoaderObj.h"
static const int MAX_CONVEXVOL_PTS = 12;
struct ConvexVolume
{
float verts[MAX_CONVEXVOL_PTS*3];
float hmin, hmax;
int nverts;
int area;
};
class InputGeom class InputGeom
{ {
rcChunkyTriMesh* m_chunkyMesh; rcChunkyTriMesh* m_chunkyMesh;
@ -33,13 +42,14 @@ class InputGeom
float m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS*3*2]; float m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS*3*2];
float m_offMeshConRads[MAX_OFFMESH_CONNECTIONS]; float m_offMeshConRads[MAX_OFFMESH_CONNECTIONS];
unsigned char m_offMeshConDirs[MAX_OFFMESH_CONNECTIONS]; unsigned char m_offMeshConDirs[MAX_OFFMESH_CONNECTIONS];
unsigned char m_offMeshConAreas[MAX_OFFMESH_CONNECTIONS];
unsigned short m_offMeshConFlags[MAX_OFFMESH_CONNECTIONS];
int m_offMeshConCount; int m_offMeshConCount;
// Box Volumes. // Convex Volumes.
static const int MAX_BOX_VOLUMES = 256; static const int MAX_VOLUMES = 256;
float m_boxVolVerts[MAX_BOX_VOLUMES*3*2]; ConvexVolume m_volumes[MAX_VOLUMES];
unsigned char m_boxVolTypes[MAX_BOX_VOLUMES]; int m_volumeCount;
int m_boxVolCount;
public: public:
InputGeom(); InputGeom();
@ -62,17 +72,20 @@ public:
const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; } const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; }
const float* getOffMeshConnectionRads() const { return m_offMeshConRads; } const float* getOffMeshConnectionRads() const { return m_offMeshConRads; }
const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; } const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; }
void addOffMeshConnection(const float* spos, const float* epos, const float rad, unsigned char bidir); const unsigned char* getOffMeshConnectionAreas() const { return m_offMeshConAreas; }
const unsigned short* getOffMeshConnectionFlags() const { return m_offMeshConFlags; }
void addOffMeshConnection(const float* spos, const float* epos, const float rad,
unsigned char bidir, unsigned char area, unsigned short flags);
void deleteOffMeshConnection(int i); void deleteOffMeshConnection(int i);
void drawOffMeshConnections(struct duDebugDraw* dd, bool hilight = false); void drawOffMeshConnections(struct duDebugDraw* dd, bool hilight = false);
// Box Volumes. // Box Volumes.
int getBoxVolumeCount() const { return m_boxVolCount; } int getConvexVolumeCount() const { return m_volumeCount; }
const float* getBoxVolumeVerts() const { return m_boxVolVerts; } const ConvexVolume* getConvexVolumes() const { return m_volumes; }
const unsigned char* getBoxVolumeTypes() const { return m_boxVolTypes; } void addConvexVolume(const float* verts, const int nverts,
void addBoxVolume(const float* bmin, const float* bmax, unsigned char type); const float minh, const float maxh, unsigned char area);
void deleteBoxVolume(int i); void deleteConvexVolume(int i);
void drawBoxVolumes(struct duDebugDraw* dd, bool hilight = false); void drawConvexVolumes(struct duDebugDraw* dd, bool hilight = false);
}; };
#endif // INPUTGEOM_H #endif // INPUTGEOM_H

View File

@ -22,6 +22,29 @@
#include "DebugDraw.h" #include "DebugDraw.h"
#include "DetourNavMesh.h" #include "DetourNavMesh.h"
// These are just sample areas to use consistent values across the samples.
// The use should specify these base on his needs.
enum SamplePolyAreas
{
SAMPLE_POLYAREA_GROUND,
SAMPLE_POLYAREA_WATER,
SAMPLE_POLYAREA_ROAD,
SAMPLE_POLYAREA_DOOR,
SAMPLE_POLYAREA_GRASS,
SAMPLE_POLYAREA_JUMP,
};
enum SamplePolyFlags
{
SAMPLE_POLYFLAGS_WALK = 0x01, // Ability to walk (ground, grass, road)
SAMPLE_POLYFLAGS_SWIM = 0x02, // Ability to swim (water).
SAMPLE_POLYFLAGS_DOOR = 0x04, // Ability to move through doors.
SAMPLE_POLYFLAGS_JUMP = 0x08, // Ability to jump.
SAMPLE_POLYFLAGS_ALL = 0xffff // All abilities.
};
// OpenGL debug draw implementation.
struct DebugDrawGL : public duDebugDraw struct DebugDrawGL : public duDebugDraw
{ {
virtual void depthMask(bool state); virtual void depthMask(bool state);
@ -31,6 +54,7 @@ struct DebugDrawGL : public duDebugDraw
virtual void end(); virtual void end();
}; };
// Tool types.
enum SampleToolType enum SampleToolType
{ {
TOOL_NONE = 0, TOOL_NONE = 0,
@ -38,7 +62,7 @@ enum SampleToolType
TOOL_TILE_HIGHLIGHT, TOOL_TILE_HIGHLIGHT,
TOOL_NAVMESH_TESTER, TOOL_NAVMESH_TESTER,
TOOL_OFFMESH_CONNECTION, TOOL_OFFMESH_CONNECTION,
TOOL_BOX_VOLUME, TOOL_CONVEX_VOLUME,
}; };
struct SampleTool struct SampleTool

View File

@ -1,152 +0,0 @@
//
// 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.
//
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <float.h>
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "BoxVolumeTool.h"
#include "InputGeom.h"
#include "Sample.h"
#include "Recast.h"
#include "RecastDebugDraw.h"
#include "DetourDebugDraw.h"
#ifdef WIN32
# define snprintf _snprintf
#endif
BoxVolumeTool::BoxVolumeTool() :
m_sample(0),
m_hitPosSet(0),
m_areaType(1),
m_boxHeight(5.0f)
{
}
BoxVolumeTool::~BoxVolumeTool()
{
}
void BoxVolumeTool::init(Sample* sample)
{
m_sample = sample;
}
void BoxVolumeTool::reset()
{
m_hitPosSet = false;
}
void BoxVolumeTool::handleMenu()
{
imguiSlider("Box Height", &m_boxHeight, 0.1f, 20.0f, 0.1f);
imguiSlider("Area Type", &m_areaType, 1.0f, 20.0f, 1.0f);
if (!m_hitPosSet)
{
imguiValue("Click to set connection start.");
}
else
{
imguiValue("Click to set connection end.");
}
}
void BoxVolumeTool::handleClick(const float* p, bool shift)
{
if (!m_sample) return;
InputGeom* geom = m_sample->getInputGeom();
if (!geom) return;
if (shift)
{
// Delete
// Find nearest link end-point
int nearestIndex = -1;
const float* verts = geom->getBoxVolumeVerts();
for (int i = 0; i < geom->getBoxVolumeCount(); ++i)
{
const float* bmin = &verts[(i*2+0)*3];
const float* bmax = &verts[(i*2+1)*3];
if (p[0] >= bmin[0] && p[0] <= bmax[0] &&
p[1] >= bmin[1] && p[1] <= bmax[1] &&
p[2] >= bmin[2] && p[2] <= bmax[2])
{
nearestIndex = i; // Each link has two vertices.
}
}
// If end point close enough, delete it.
if (nearestIndex != -1)
{
geom->deleteBoxVolume(nearestIndex);
}
}
else
{
// Create
if (!m_hitPosSet)
{
vcopy(m_hitPos, p);
m_hitPosSet = true;
}
else
{
float bmin[3], bmax[3];
vcopy(bmin, m_hitPos);
vcopy(bmax, m_hitPos);
vmin(bmin, p);
vmax(bmax, p);
bmin[1] -= m_boxHeight/4.0f;
bmax[1] = bmin[1]+m_boxHeight;
geom->addBoxVolume(bmin, bmax, (unsigned char)m_areaType);
m_hitPosSet = false;
}
}
}
void BoxVolumeTool::handleRender()
{
DebugDrawGL dd;
const float s = m_sample->getAgentRadius();
if (m_hitPosSet)
duDebugDrawCross(&dd, m_hitPos[0],m_hitPos[1]+0.1f,m_hitPos[2], s, duRGBA(0,0,0,128), 2.0f);
InputGeom* geom = m_sample->getInputGeom();
if (geom)
geom->drawBoxVolumes(&dd, true);
}
void BoxVolumeTool::handleRenderOverlay(double* proj, double* model, int* view)
{
GLdouble x, y, z;
// Draw start and end point labels
if (m_hitPosSet && gluProject((GLdouble)m_hitPos[0], (GLdouble)m_hitPos[1], (GLdouble)m_hitPos[2],
model, proj, view, &x, &y, &z))
{
imguiDrawText((int)x, (int)(y-25), IMGUI_ALIGN_CENTER, "Start", imguiRGBA(0,0,0,220));
}
}

View File

@ -20,6 +20,7 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#include <string.h>
#include "Recast.h" #include "Recast.h"
#include "RecastLog.h" #include "RecastLog.h"
#include "InputGeom.h" #include "InputGeom.h"
@ -108,7 +109,7 @@ InputGeom::InputGeom() :
m_chunkyMesh(0), m_chunkyMesh(0),
m_mesh(0), m_mesh(0),
m_offMeshConCount(0), m_offMeshConCount(0),
m_boxVolCount(0) m_volumeCount(0)
{ {
} }
@ -128,7 +129,7 @@ bool InputGeom::loadMesh(const char* filepath)
m_mesh = 0; m_mesh = 0;
} }
m_offMeshConCount = 0; m_offMeshConCount = 0;
m_boxVolCount = 0; m_volumeCount = 0;
m_mesh = new rcMeshLoaderObj; m_mesh = new rcMeshLoaderObj;
if (!m_mesh) if (!m_mesh)
@ -182,7 +183,7 @@ bool InputGeom::load(const char* filePath)
fclose(fp); fclose(fp);
m_offMeshConCount = 0; m_offMeshConCount = 0;
m_boxVolCount = 0; m_volumeCount = 0;
delete m_mesh; delete m_mesh;
m_mesh = 0; m_mesh = 0;
@ -216,26 +217,30 @@ bool InputGeom::load(const char* filePath)
if (m_offMeshConCount < MAX_OFFMESH_CONNECTIONS) if (m_offMeshConCount < MAX_OFFMESH_CONNECTIONS)
{ {
float* v = &m_offMeshConVerts[m_offMeshConCount*3*2]; float* v = &m_offMeshConVerts[m_offMeshConCount*3*2];
int bidir; int bidir, area = 0, flags = 0;
float rad; float rad;
sscanf(row+1, "%f %f %f %f %f %f %f %d", sscanf(row+1, "%f %f %f %f %f %f %f %d %d %d",
&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &rad, &bidir); &v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &rad, &bidir, &area, &flags);
m_offMeshConRads[m_offMeshConCount] = rad; m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConDirs[m_offMeshConCount] = bidir; m_offMeshConDirs[m_offMeshConCount] = bidir;
m_offMeshConAreas[m_offMeshConCount] = area;
m_offMeshConFlags[m_offMeshConCount] = flags;
m_offMeshConCount++; m_offMeshConCount++;
} }
} }
else if (row[0] == 'b') else if (row[0] == 'v')
{ {
// Box volumes // Convex volumes
if (m_boxVolCount < MAX_BOX_VOLUMES) if (m_volumeCount < MAX_VOLUMES)
{ {
float* v = &m_boxVolVerts[m_boxVolCount*3*2]; ConvexVolume* vol = &m_volumes[m_volumeCount++];
int type; sscanf(row+1, "%d %d %f %f", &vol->nverts, &vol->area, &vol->hmin, &vol->hmax);
sscanf(row+1, "%f %f %f %f %f %f %d", for (int i = 0; i < vol->nverts; ++i)
&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &type); {
m_boxVolTypes[m_boxVolCount] = (unsigned char)type; row[0] = '\0';
m_boxVolCount++; src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char));
sscanf(row, "%f %f %f", &vol->verts[i*3+0], &vol->verts[i*3+1], &vol->verts[i*3+2]);
}
} }
} }
} }
@ -261,17 +266,19 @@ bool InputGeom::save(const char* filepath)
const float* v = &m_offMeshConVerts[i*3*2]; const float* v = &m_offMeshConVerts[i*3*2];
const float rad = m_offMeshConRads[i]; const float rad = m_offMeshConRads[i];
const int bidir = m_offMeshConDirs[i]; const int bidir = m_offMeshConDirs[i];
fprintf(fp, "c %f %f %f %f %f %f %f %d\n", const int area = m_offMeshConAreas[i];
v[0], v[1], v[2], v[3], v[4], v[5], rad, bidir); const int flags = m_offMeshConFlags[i];
fprintf(fp, "c %f %f %f %f %f %f %f %d %d %d\n",
v[0], v[1], v[2], v[3], v[4], v[5], rad, bidir, area, flags);
} }
// Box volumes // Convex volumes
for (int i = 0; i < m_boxVolCount; ++i) for (int i = 0; i < m_volumeCount; ++i)
{ {
const float* v = &m_boxVolVerts[i*3*2]; ConvexVolume* vol = &m_volumes[i];
const int bidir = m_boxVolTypes[i]; fprintf(fp, "v %d %d %f %f\n", vol->nverts, vol->area, vol->hmin, vol->hmax);
fprintf(fp, "b %f %f %f %f %f %f %d\n", for (int i = 0; i < vol->nverts; ++i)
v[0], v[1], v[2], v[3], v[4], v[5], bidir); fprintf(fp, "%f %f %f\n", vol->verts[i*3+0], vol->verts[i*3+1], vol->verts[i*3+2]);
} }
fclose(fp); fclose(fp);
@ -312,12 +319,15 @@ bool InputGeom::raycastMesh(float* src, float* dst, float& tmin)
return hit; return hit;
} }
void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float rad, unsigned char bidir) void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float rad,
unsigned char bidir, unsigned char area, unsigned short flags)
{ {
if (m_offMeshConCount >= MAX_OFFMESH_CONNECTIONS) return; if (m_offMeshConCount >= MAX_OFFMESH_CONNECTIONS) return;
float* v = &m_offMeshConVerts[m_offMeshConCount*3*2]; float* v = &m_offMeshConVerts[m_offMeshConCount*3*2];
m_offMeshConRads[m_offMeshConCount] = rad; m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConDirs[m_offMeshConCount] = bidir; m_offMeshConDirs[m_offMeshConCount] = bidir;
m_offMeshConAreas[m_offMeshConCount] = area;
m_offMeshConFlags[m_offMeshConCount] = flags;
vcopy(&v[0], spos); vcopy(&v[0], spos);
vcopy(&v[3], epos); vcopy(&v[3], epos);
m_offMeshConCount++; m_offMeshConCount++;
@ -332,6 +342,8 @@ void InputGeom::deleteOffMeshConnection(int i)
vcopy(&dst[3], &src[3]); vcopy(&dst[3], &src[3]);
m_offMeshConRads[i] = m_offMeshConRads[m_offMeshConCount]; m_offMeshConRads[i] = m_offMeshConRads[m_offMeshConCount];
m_offMeshConDirs[i] = m_offMeshConDirs[m_offMeshConCount]; m_offMeshConDirs[i] = m_offMeshConDirs[m_offMeshConCount];
m_offMeshConAreas[i] = m_offMeshConAreas[m_offMeshConCount];
m_offMeshConFlags[i] = m_offMeshConFlags[m_offMeshConCount];
} }
void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool hilight) void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool hilight)
@ -365,47 +377,89 @@ void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool hilight)
dd->depthMask(true); dd->depthMask(true);
} }
void InputGeom::addBoxVolume(const float* bmin, const float* bmax, unsigned char type) void InputGeom::addConvexVolume(const float* verts, const int nverts,
const float minh, const float maxh, unsigned char area)
{ {
if (m_boxVolCount >= MAX_OFFMESH_CONNECTIONS) return; if (m_volumeCount >= MAX_VOLUMES) return;
float* v = &m_boxVolVerts[m_boxVolCount*3*2]; ConvexVolume* vol = &m_volumes[m_volumeCount++];
m_boxVolTypes[m_boxVolCount] = type; memset(vol, 0, sizeof(ConvexVolume));
vcopy(&v[0], bmin); memcpy(vol->verts, verts, sizeof(float)*3*nverts);
vcopy(&v[3], bmax); vol->hmin = minh;
m_boxVolCount++; vol->hmax = maxh;
vol->nverts = nverts;
vol->area = area;
} }
void InputGeom::deleteBoxVolume(int i) void InputGeom::deleteConvexVolume(int i)
{ {
m_boxVolCount--; m_volumeCount--;
float* src = &m_boxVolVerts[m_boxVolCount*3*2]; m_volumes[i] = m_volumes[m_volumeCount];
float* dst = &m_boxVolVerts[i*3*2];
vcopy(&dst[0], &src[0]);
vcopy(&dst[3], &src[3]);
m_boxVolTypes[i] = m_boxVolTypes[m_boxVolCount];
} }
void InputGeom::drawBoxVolumes(struct duDebugDraw* dd, bool hilight) void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool hilight)
{ {
dd->depthMask(false); dd->depthMask(false);
dd->begin(DU_DRAW_LINES, 2.0f); dd->begin(DU_DRAW_TRIS);
for (int i = 0; i < m_boxVolCount; ++i)
for (int i = 0; i < m_volumeCount; ++i)
{ {
unsigned int col = duIntToCol(m_boxVolTypes[i]+1, 220); const ConvexVolume* vol = &m_volumes[i];
const float* bounds = &m_boxVolVerts[i*3*2]; unsigned int col = duIntToCol(vol->area, 32);
duAppendBoxWire(dd, bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5], col); for (int j = 0, k = vol->nverts-1; j < vol->nverts; k = j++)
{
const float* va = &vol->verts[k*3];
const float* vb = &vol->verts[j*3];
dd->vertex(vol->verts[0],vol->hmax,vol->verts[2], col);
dd->vertex(vb[0],vol->hmax,vb[2], col);
dd->vertex(va[0],vol->hmax,va[2], col);
dd->vertex(va[0],vol->hmin,va[2], duDarkenColor(col));
dd->vertex(va[0],vol->hmax,va[2], col);
dd->vertex(vb[0],vol->hmax,vb[2], col);
dd->vertex(va[0],vol->hmin,va[2], duDarkenColor(col));
dd->vertex(vb[0],vol->hmax,vb[2], col);
dd->vertex(vb[0],vol->hmin,vb[2], duDarkenColor(col));
}
}
dd->end();
dd->begin(DU_DRAW_LINES, 2.0f);
for (int i = 0; i < m_volumeCount; ++i)
{
const ConvexVolume* vol = &m_volumes[i];
unsigned int col = duIntToCol(vol->area, 220);
for (int j = 0, k = vol->nverts-1; j < vol->nverts; k = j++)
{
const float* va = &vol->verts[k*3];
const float* vb = &vol->verts[j*3];
dd->vertex(va[0],vol->hmin,va[2], duDarkenColor(col));
dd->vertex(vb[0],vol->hmin,vb[2], duDarkenColor(col));
dd->vertex(va[0],vol->hmax,va[2], col);
dd->vertex(vb[0],vol->hmax,vb[2], col);
dd->vertex(va[0],vol->hmin,va[2], duDarkenColor(col));
dd->vertex(va[0],vol->hmax,va[2], col);
}
} }
dd->end(); dd->end();
dd->begin(DU_DRAW_POINTS, 4.0f); dd->begin(DU_DRAW_POINTS, 3.0f);
for (int i = 0; i < m_boxVolCount; ++i) for (int i = 0; i < m_volumeCount; ++i)
{ {
unsigned int col = duDarkenColor(duIntToCol(m_boxVolTypes[i]+1, 255)); const ConvexVolume* vol = &m_volumes[i];
const float* bounds = &m_boxVolVerts[i*3*2]; unsigned int col = duDarkenColor(duIntToCol(vol->area, 255));
duAppendBoxPoints(dd, bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5], col); for (int j = 0; j < vol->nverts; ++j)
{
dd->vertex(vol->verts[j*3+0],vol->verts[j*3+1]+0.1f,vol->verts[j*3+2], col);
dd->vertex(vol->verts[j*3+0],vol->hmin,vol->verts[j*3+2], col);
dd->vertex(vol->verts[j*3+0],vol->hmax,vol->verts[j*3+2], col);
}
} }
dd->end(); dd->end();
dd->depthMask(true); dd->depthMask(true);
} }

View File

@ -60,7 +60,7 @@ NavMeshTesterTool::NavMeshTesterTool() :
m_sposSet(false), m_sposSet(false),
m_eposSet(false) m_eposSet(false)
{ {
m_filter.includeFlags = DT_POLY_GROUND | DT_POLY_OFFMESH_CONNECTION; m_filter.includeFlags = SAMPLE_POLYFLAGS_ALL;
m_filter.excludeFlags = 0; m_filter.excludeFlags = 0;
m_polyPickExt[0] = 2; m_polyPickExt[0] = 2;
@ -127,29 +127,56 @@ void NavMeshTesterTool::handleMenu()
imguiLabel("Include Flags"); imguiLabel("Include Flags");
if (imguiCheck("Ground", (m_filter.includeFlags & DT_POLY_GROUND) ? true : false)) imguiIndent();
if (imguiCheck("Walk", (m_filter.includeFlags & SAMPLE_POLYFLAGS_WALK) != 0))
{ {
m_filter.includeFlags ^= DT_POLY_GROUND; m_filter.includeFlags ^= SAMPLE_POLYFLAGS_WALK;
recalc(); recalc();
} }
if (imguiCheck("Off-Mesh Connections", (m_filter.includeFlags & DT_POLY_OFFMESH_CONNECTION) ? true : false)) if (imguiCheck("Swim", (m_filter.includeFlags & SAMPLE_POLYFLAGS_SWIM) != 0))
{ {
m_filter.includeFlags ^= DT_POLY_OFFMESH_CONNECTION; m_filter.includeFlags ^= SAMPLE_POLYFLAGS_SWIM;
recalc(); recalc();
} }
if (imguiCheck("Door", (m_filter.includeFlags & SAMPLE_POLYFLAGS_DOOR) != 0))
{
m_filter.includeFlags ^= SAMPLE_POLYFLAGS_DOOR;
recalc();
}
if (imguiCheck("Jump", (m_filter.includeFlags & SAMPLE_POLYFLAGS_JUMP) != 0))
{
m_filter.includeFlags ^= SAMPLE_POLYFLAGS_JUMP;
recalc();
}
imguiUnindent();
imguiSeparator();
imguiLabel("Exclude Flags"); imguiLabel("Exclude Flags");
if (imguiCheck("Ground", (m_filter.excludeFlags & DT_POLY_GROUND) ? true : false)) imguiIndent();
if (imguiCheck("Walk", (m_filter.excludeFlags & SAMPLE_POLYFLAGS_WALK) != 0))
{ {
m_filter.excludeFlags ^= DT_POLY_GROUND; m_filter.excludeFlags ^= SAMPLE_POLYFLAGS_WALK;
recalc(); recalc();
} }
if (imguiCheck("Off-Mesh Connections", (m_filter.excludeFlags & DT_POLY_OFFMESH_CONNECTION) ? true : false)) if (imguiCheck("Swim", (m_filter.excludeFlags & SAMPLE_POLYFLAGS_SWIM) != 0))
{ {
m_filter.excludeFlags ^= DT_POLY_OFFMESH_CONNECTION; m_filter.excludeFlags ^= SAMPLE_POLYFLAGS_SWIM;
recalc(); recalc();
} }
if (imguiCheck("Door", (m_filter.excludeFlags & SAMPLE_POLYFLAGS_DOOR) != 0))
{
m_filter.excludeFlags ^= SAMPLE_POLYFLAGS_DOOR;
recalc();
}
if (imguiCheck("Jump", (m_filter.excludeFlags & SAMPLE_POLYFLAGS_JUMP) != 0))
{
m_filter.excludeFlags ^= SAMPLE_POLYFLAGS_JUMP;
recalc();
}
imguiUnindent();
imguiSeparator();
if (m_toolMode == TOOLMODE_PATHFIND_ITER || m_toolMode == TOOLMODE_PATHFIND_STRAIGHT) if (m_toolMode == TOOLMODE_PATHFIND_ITER || m_toolMode == TOOLMODE_PATHFIND_STRAIGHT)
{ {

View File

@ -123,7 +123,9 @@ void OffMeshConnectionTool::handleClick(const float* p, bool shift)
} }
else else
{ {
geom->addOffMeshConnection(m_hitPos, p, m_sample->getAgentRadius(), m_bidir ? 1 : 0); const unsigned char area = SAMPLE_POLYAREA_JUMP;
const unsigned short flags = SAMPLE_POLYFLAGS_JUMP;
geom->addOffMeshConnection(m_hitPos, p, m_sample->getAgentRadius(), m_bidir ? 1 : 0, area, flags);
m_hitPosSet = false; m_hitPosSet = false;
} }
} }

View File

@ -35,7 +35,7 @@
#include "DetourDebugDraw.h" #include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h" #include "NavMeshTesterTool.h"
#include "OffMeshConnectionTool.h" #include "OffMeshConnectionTool.h"
#include "BoxVolumeTool.h" #include "ConvexVolumeTool.h"
#ifdef WIN32 #ifdef WIN32
# define snprintf _snprintf # define snprintf _snprintf
@ -100,9 +100,9 @@ void Sample_SoloMeshSimple::handleTools()
{ {
setTool(new OffMeshConnectionTool); setTool(new OffMeshConnectionTool);
} }
if (imguiCheck("Create Box Volumes", type == TOOL_BOX_VOLUME)) if (imguiCheck("Create Convex Volumes", type == TOOL_CONVEX_VOLUME))
{ {
setTool(new BoxVolumeTool); setTool(new ConvexVolumeTool);
} }
imguiSeparator(); imguiSeparator();
@ -293,7 +293,7 @@ void Sample_SoloMeshSimple::handleRender()
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
} }
m_geom->drawBoxVolumes(&dd); m_geom->drawConvexVolumes(&dd);
if (m_tool) if (m_tool)
m_tool->handleRender(); m_tool->handleRender();
@ -471,13 +471,9 @@ bool Sample_SoloMeshSimple::handleBuild()
} }
// (Optional) Mark areas. // (Optional) Mark areas.
const float* boxVerts = m_geom->getBoxVolumeVerts(); const ConvexVolume* vols = m_geom->getConvexVolumes();
const unsigned char* boxTypes = m_geom->getBoxVolumeTypes(); for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
for (int i = 0; i < m_geom->getBoxVolumeCount(); ++i) rcMarkConvexPolyArea(vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
{
const float* v = &boxVerts[i*3*2];
rcMarkBoxArea(&v[0], &v[3], boxTypes[i], *m_chf);
}
// Prepare for region partitioning, by calculating distance field along the walkable surface. // Prepare for region partitioning, by calculating distance field along the walkable surface.
if (!rcBuildDistanceField(*m_chf)) if (!rcBuildDistanceField(*m_chf))
@ -572,11 +568,36 @@ bool Sample_SoloMeshSimple::handleBuild()
unsigned char* navData = 0; unsigned char* navData = 0;
int navDataSize = 0; int navDataSize = 0;
// Update poly flags from areas.
for (int i = 0; i < m_pmesh->npolys; ++i)
{
if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
}
else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
}
else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
}
}
dtNavMeshCreateParams params; dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts; params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts; params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys; params.polys = m_pmesh->polys;
params.polyAreas = m_pmesh->areas;
params.polyFlags = m_pmesh->flags;
params.polyCount = m_pmesh->npolys; params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp; params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes; params.detailMeshes = m_dmesh->meshes;
@ -587,6 +608,8 @@ bool Sample_SoloMeshSimple::handleBuild()
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts(); params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads(); params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs(); params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConCount = m_geom->getOffMeshConnectionCount(); params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight; params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius; params.walkableRadius = m_agentRadius;

View File

@ -34,7 +34,7 @@
#include "DetourDebugDraw.h" #include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h" #include "NavMeshTesterTool.h"
#include "OffMeshConnectionTool.h" #include "OffMeshConnectionTool.h"
#include "BoxVolumeTool.h" #include "ConvexVolumeTool.h"
#ifdef WIN32 #ifdef WIN32
# define snprintf _snprintf # define snprintf _snprintf
@ -187,9 +187,9 @@ void Sample_SoloMeshTiled::handleTools()
{ {
setTool(new OffMeshConnectionTool); setTool(new OffMeshConnectionTool);
} }
if (imguiCheck("Create Box Volumes", type == TOOL_BOX_VOLUME)) if (imguiCheck("Create Convex Volumes", type == TOOL_CONVEX_VOLUME))
{ {
setTool(new BoxVolumeTool); setTool(new ConvexVolumeTool);
} }
if (imguiCheck("Highlight Tile", type == TOOL_TILE_HIGHLIGHT)) if (imguiCheck("Highlight Tile", type == TOOL_TILE_HIGHLIGHT))
{ {
@ -486,7 +486,7 @@ void Sample_SoloMeshTiled::handleRender()
} }
} }
m_geom->drawBoxVolumes(&dd); m_geom->drawConvexVolumes(&dd);
if (m_tool) if (m_tool)
m_tool->handleRender(); m_tool->handleRender();
@ -840,13 +840,10 @@ bool Sample_SoloMeshTiled::handleBuild()
continue; continue;
} }
const float* boxVerts = m_geom->getBoxVolumeVerts(); // (Optional) Mark areas.
const unsigned char* boxTypes = m_geom->getBoxVolumeTypes(); const ConvexVolume* vols = m_geom->getConvexVolumes();
for (int i = 0; i < m_geom->getBoxVolumeCount(); ++i) for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
{ rcMarkConvexPolyArea(vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *chf);
const float* v = &boxVerts[i*3*2];
rcMarkBoxArea(&v[0], &v[3], boxTypes[i], *chf);
}
if (!rcBuildDistanceField(*chf)) if (!rcBuildDistanceField(*chf))
{ {
@ -1022,11 +1019,35 @@ bool Sample_SoloMeshTiled::handleBuild()
unsigned char* navData = 0; unsigned char* navData = 0;
int navDataSize = 0; int navDataSize = 0;
// Update poly flags from areas.
for (int i = 0; i < m_pmesh->npolys; ++i)
{
if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
}
else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
}
else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
}
}
dtNavMeshCreateParams params; dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts; params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts; params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys; params.polys = m_pmesh->polys;
params.polyAreas = m_pmesh->areas;
params.polyFlags = m_pmesh->flags;
params.polyCount = m_pmesh->npolys; params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp; params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes; params.detailMeshes = m_dmesh->meshes;
@ -1037,6 +1058,8 @@ bool Sample_SoloMeshTiled::handleBuild()
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts(); params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads(); params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs(); params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConCount = m_geom->getOffMeshConnectionCount(); params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight; params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius; params.walkableRadius = m_agentRadius;

View File

@ -34,7 +34,7 @@
#include "DetourDebugDraw.h" #include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h" #include "NavMeshTesterTool.h"
#include "OffMeshConnectionTool.h" #include "OffMeshConnectionTool.h"
#include "BoxVolumeTool.h" #include "ConvexVolumeTool.h"
#ifdef WIN32 #ifdef WIN32
# define snprintf _snprintf # define snprintf _snprintf
@ -258,9 +258,9 @@ void Sample_TileMesh::handleTools()
{ {
setTool(new OffMeshConnectionTool); setTool(new OffMeshConnectionTool);
} }
if (imguiCheck("Create Box Volumes", type == TOOL_BOX_VOLUME)) if (imguiCheck("Create Convex Volumes", type == TOOL_CONVEX_VOLUME))
{ {
setTool(new BoxVolumeTool); setTool(new ConvexVolumeTool);
} }
imguiSeparator(); imguiSeparator();
@ -321,7 +321,7 @@ void Sample_TileMesh::handleRender()
if (m_tool) if (m_tool)
m_tool->handleRender(); m_tool->handleRender();
m_geom->drawBoxVolumes(&dd); m_geom->drawConvexVolumes(&dd);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
} }
@ -667,14 +667,10 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
return false; return false;
} }
const float* boxVerts = m_geom->getBoxVolumeVerts(); // (Optional) Mark areas.
const unsigned char* boxTypes = m_geom->getBoxVolumeTypes(); const ConvexVolume* vols = m_geom->getConvexVolumes();
for (int i = 0; i < m_geom->getBoxVolumeCount(); ++i) for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
{ rcMarkConvexPolyArea(vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
const float* v = &boxVerts[i*3*2];
rcMarkBoxArea(&v[0], &v[3], boxTypes[i], *m_chf);
}
// Prepare for region partitioning, by calculating distance field along the walkable surface. // Prepare for region partitioning, by calculating distance field along the walkable surface.
if (!rcBuildDistanceField(*m_chf)) if (!rcBuildDistanceField(*m_chf))
@ -773,11 +769,35 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
return false; return false;
} }
// Update poly flags from areas.
for (int i = 0; i < m_pmesh->npolys; ++i)
{
if (m_pmesh->areas[i] == RC_WALKABLE_AREA)
m_pmesh->areas[i] = SAMPLE_POLYAREA_GROUND;
if (m_pmesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
m_pmesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
m_pmesh->areas[i] == SAMPLE_POLYAREA_ROAD)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
}
else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_WATER)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
}
else if (m_pmesh->areas[i] == SAMPLE_POLYAREA_DOOR)
{
m_pmesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
}
}
dtNavMeshCreateParams params; dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts; params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts; params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys; params.polys = m_pmesh->polys;
params.polyAreas = m_pmesh->areas;
params.polyFlags = m_pmesh->flags;
params.polyCount = m_pmesh->npolys; params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp; params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes; params.detailMeshes = m_dmesh->meshes;
@ -788,6 +808,8 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts(); params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads(); params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs(); params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConCount = m_geom->getOffMeshConnectionCount(); params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight; params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius; params.walkableRadius = m_agentRadius;