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];
if (p->flags & DT_POLY_OFFMESH_CONNECTION) continue;
if (p->type == DT_POLYTYPE_OFFMESH_CONNECTION) continue;
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)
{
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;
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))
col = duRGBA(255,196,0,64);
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)
{
@ -163,14 +168,14 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTil
for (int i = 0; i < header->polyCount; ++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;
unsigned int col;
if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,220);
else
col = duRGBA(255,255,255,220);
col = duDarkenColor(duIntToCol(p->area, 220));
const dtOffMeshConnection* con = &header->offMeshCons[i - header->offMeshBase];
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);
if (p->flags & DT_POLY_OFFMESH_CONNECTION)
if (p->type == DT_POLYTYPE_OFFMESH_CONNECTION)
{
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_OFFMESH_CON_BIDIR = 1;
static const int DT_MAX_AREAS = 64;
// Flags returned by findStraightPath().
enum dtStraightPathFlags
{
@ -41,10 +43,10 @@ enum dtStraightPathFlags
};
// Flags describing polygon properties.
enum dtPolyFlags
enum dtPolyTypes
{
DT_POLY_GROUND = 0x01, // Regular ground polygons.
DT_POLY_OFFMESH_CONNECTION = 0x02, // Off-mesh connections.
DT_POLYTYPE_GROUND = 0, // Regular ground polygons.
DT_POLYTYPE_OFFMESH_CONNECTION = 1, // Off-mesh connections.
};
struct dtQueryFilter
@ -62,6 +64,8 @@ struct dtPoly
unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
unsigned short flags; // Flags (see dtPolyFlags).
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.
@ -363,6 +367,17 @@ public:
// height - (out) height at the location.
// Returns: true if over polygon.
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.
const dtPoly* getPolyByRef(dtPolyRef ref) const;
@ -432,8 +447,9 @@ private:
dtQueryFilter* filter, float* nearestPt);
// Returns closest point on polygon.
bool closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, const float* pos, float* closest) const;
unsigned short getPolyFlags(dtPolyRef ref);
unsigned char getPolyType(dtPolyRef ref);
float getCost(dtPolyRef prev, 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;
@ -441,7 +457,7 @@ private:
// Returns portal points between two polygons.
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.
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_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 dtNodeQueue* m_openList; // Pointer to open list queue.
};

View File

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

View File

@ -421,7 +421,7 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile)
dtPoly* poly = &header->polys[i];
poly->firstLink = DT_NULL_LINK;
if (poly->flags & DT_POLY_OFFMESH_CONNECTION)
if (poly->type == DT_POLYTYPE_OFFMESH_CONNECTION)
continue;
// 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];
// 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;
// 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;
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* v1 = &header->verts[poly->verts[1]*3];
@ -903,6 +903,18 @@ bool dtNavMesh::getPolyHeight(dtPolyRef ref, const float* pos, float* height) co
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)
{
@ -1271,8 +1283,8 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
int leftIndex = 0;
int rightIndex = 0;
unsigned short leftPolyFlags = 0;
unsigned short rightPolyFlags = 0;
unsigned char leftPolyType = 0;
unsigned char rightPolyType = 0;
dtPolyRef leftPolyRef = 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)
{
float left[3], right[3];
unsigned short fromFlags, toFlags;
unsigned char fromType, toType;
if (i+1 < pathSize)
{
// 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))
return 0;
@ -1306,7 +1318,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(left, closestEndPos);
vcopy(right, closestEndPos);
fromFlags = toFlags = 0;
fromType = toType = DT_POLYTYPE_GROUND;
}
// Right vertex.
@ -1314,7 +1326,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{
vcopy(portalRight, right);
rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
rightPolyFlags = toFlags;
rightPolyType = toType;
rightIndex = i;
}
else
@ -1325,7 +1337,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{
vcopy(portalRight, right);
rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
rightPolyFlags = toFlags;
rightPolyType = toType;
rightIndex = i;
}
else
@ -1333,7 +1345,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(portalApex, portalLeft);
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;
if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex))
@ -1375,7 +1387,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{
vcopy(portalLeft, left);
leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
leftPolyFlags = toFlags;
leftPolyType = toType;
leftIndex = i;
}
else
@ -1386,7 +1398,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
{
vcopy(portalLeft, left);
leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0;
leftPolyFlags = toFlags;
leftPolyType = toType;
leftIndex = i;
}
else
@ -1394,7 +1406,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(portalApex, portalRight);
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;
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];
// 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)
{
float left[3], right[3];
unsigned short fromFlags, toFlags;
if (!getPortalPoints(path[n], path[n+1], left, right, fromFlags, toFlags))
unsigned char fromType, toType;
if (!getPortalPoints(path[n], path[n+1], left, right, fromType, toType))
return n;
vcopy(resultPos, endPos);
}
@ -1523,8 +1535,8 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
if (n+1 >= pathSize)
return n;
float left[3], right[3];
unsigned short fromFlags, toFlags;
if (!getPortalPoints(path[n], path[n+1], left, right, fromFlags, toFlags))
unsigned char fromType, toType;
if (!getPortalPoints(path[n], path[n+1], left, right, fromType, toType))
return n;
// If the clamped point is close to the next portal edge, advance to next poly.
float t;
@ -1540,7 +1552,7 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
// Returns portal points between two polygons.
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;
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;
const dtMeshHeader* fromHeader = m_tiles[it].header;
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)
{
@ -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;
const dtMeshHeader* toHeader = m_tiles[it].header;
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.
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;
}
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)
{
@ -1638,8 +1650,8 @@ bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float
bool dtNavMesh::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const
{
float left[3], right[3];
unsigned short fromFlags, toFlags;
if (!getPortalPoints(from, to, left,right, fromFlags, toFlags)) return false;
unsigned char fromType, toType;
if (!getPortalPoints(from, to, left,right, fromType, toType)) return false;
mid[0] = (left[0]+right[0])*0.5f;
mid[1] = (left[1]+right[1])*0.5f;
mid[2] = (left[2]+right[2])*0.5f;
@ -1658,6 +1670,18 @@ unsigned short dtNavMesh::getPolyFlags(dtPolyRef ref)
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,
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
// whose start point is inside the tile.
unsigned char* offMeshConFlags = new unsigned char [params->offMeshConCount*2];
if (!offMeshConFlags)
unsigned char* offMeshConClass = new unsigned char [params->offMeshConCount*2];
if (!offMeshConClass)
return false;
int storedOffMeshConCount = 0;
@ -266,16 +266,16 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i)
{
offMeshConFlags[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+0] = classifyOffMeshPoint(&params->offMeshConVerts[(i*2+0)*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.
if (offMeshConFlags[i*2+0] == 0xff)
if (offMeshConClass[i*2+0] == 0xff)
offMeshConLinkCount++;
if (offMeshConFlags[i*2+1] == 0xff)
if (offMeshConClass[i*2+1] == 0xff)
offMeshConLinkCount++;
if (offMeshConFlags[i*2+0] == 0xff)
if (offMeshConClass[i*2+0] == 0xff)
storedOffMeshConCount++;
}
@ -400,7 +400,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i)
{
// 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];
float* v = &navVerts[(offMeshVertsBase + n*2)*3];
@ -417,7 +417,9 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
{
dtPoly* p = &navPolys[i];
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)
{
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)
{
// 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];
p->vertCount = 2;
p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0);
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++;
}
}
@ -503,7 +507,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
for (int i = 0; i < params->offMeshConCount; ++i)
{
// Only store connections which start from this tile.
if (offMeshConFlags[i*2+0] == 0xff)
if (offMeshConClass[i*2+0] == 0xff)
{
dtOffMeshConnection* con = &offMeshCons[n];
con->poly = offMeshPolyBase + n;
@ -513,12 +517,12 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
vcopy(&con->pos[3], &endPts[3]);
con->rad = params->offMeshConRad[i];
con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
con->side = offMeshConFlags[i*2+1];
con->side = offMeshConClass[i*2+1];
n++;
}
}
delete [] offMeshConFlags;
delete [] offMeshConClass;
*outData = data;
*outDataSize = dataSize;

View File

@ -159,13 +159,14 @@ struct rcContourSet
// z = bmin[2] + verts[i*3+2]*cs;
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* polys; // Polygons of the mesh, nvp*2 elements per polygon.
unsigned short* regs; // Region ID of the polygons.
unsigned short* flags; // Per polygon flags.
unsigned char* areas; // Area ID of polygons.
int nverts; // Number of vertices.
int npolys; // Number of polygons.
@ -508,11 +509,31 @@ bool rcBuildCompactHeightfield(const int walkableHeight, const int walkableClimb
rcHeightfield& hf,
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 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);
// 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.

View File

@ -207,30 +207,35 @@ bool rcErodeArea(unsigned char areaId, int radius, rcCompactHeightfield& chf)
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)
{
int minx = (int)floorf((bmin[0]-chf.bmin[0])/chf.cs);
int miny = (int)floorf((bmin[1]-chf.bmin[1])/chf.ch);
int minz = (int)floorf((bmin[2]-chf.bmin[2])/chf.cs);
int maxx = (int)ceilf((bmax[0]-chf.bmin[0])/chf.cs);
int maxy = (int)ceilf((bmax[1]-chf.bmin[1])/chf.ch);
int maxz = (int)ceilf((bmax[2]-chf.bmin[2])/chf.cs);
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);
minx = rcClamp(minx, 0, chf.width);
minz = rcClamp(minz, 0, chf.height);
maxx = rcClamp(maxx, 0, chf.width);
maxz = rcClamp(maxz, 0, chf.height);
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;
for (int z = minz; z < maxz; ++z)
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];
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 ((int)s.y >= miny && (int)s.y <= maxy)
{
if (areaId < chf.areas[i])
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

@ -1066,6 +1066,15 @@ bool rcBuildPolyMesh(rcContourSet& cset, int nvp, rcPolyMesh& mesh)
rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed.");
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();
@ -1138,6 +1147,15 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
return false;
}
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];
if (!nextVert)
@ -1187,6 +1205,7 @@ bool rcMergePolyMeshes(rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
unsigned short* src = &pmesh->polys[j*2*mesh.nvp];
mesh.regs[mesh.npolys] = pmesh->regs[j];
mesh.areas[mesh.npolys] = pmesh->areas[j];
mesh.flags[mesh.npolys] = pmesh->flags[j];
mesh.npolys++;
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>
<array>
<array>
<integer>55</integer>
<integer>43</integer>
<integer>35</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 606}, {358, 643}}</string>
<string>{{0, 269}, {358, 643}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@ -322,7 +323,7 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A30F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>imguiRenderGL.cpp</string>
<string>Sample_TileMesh.cpp</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@ -330,30 +331,25 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A40F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>imguiRenderGL.cpp</string>
<string>Sample_TileMesh.cpp</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>6B324AE9111C07AB00EBD2FD</string>
<string>6B324D05111C7B0900EBD2FD</string>
<key>history</key>
<array>
<string>6B8DE70D10B01BBF00DF20FB</string>
<string>6BB93D1510CFFC6D00F74F2B</string>
<string>6BBB883C10EA9B6F008FEA1F</string>
<string>6BB7FDC010F37703006DA0A6</string>
<string>6BB7FDC110F37703006DA0A6</string>
<string>6BB7FF6D10F4E8E2006DA0A6</string>
<string>6B69739F10FFCA4500984788</string>
<string>6BCF341A1105EC43009445BF</string>
<string>6BF7BE1F110F0792002B3F46</string>
<string>6BF7C0E511116E74002B3F46</string>
<string>6BF7C0EE11116E74002B3F46</string>
<string>6BF7C1D01111BCF2002B3F46</string>
<string>6BF7C2441111DAC1002B3F46</string>
<string>6BF7C2761112BE4F002B3F46</string>
<string>6BF7C2851112C348002B3F46</string>
<string>6BF7C2BD1112D453002B3F46</string>
<string>6BF7C2EF1112D646002B3F46</string>
<string>6BF7C3211112DB82002B3F46</string>
<string>6BF7C3431112E74B002B3F46</string>
<string>6BF7C36E1112EB25002B3F46</string>
@ -361,48 +357,52 @@
<string>6BF7C394111316AD002B3F46</string>
<string>6BF7C395111316AD002B3F46</string>
<string>6BF7C3CC11131F26002B3F46</string>
<string>6BF7C3CF11131F26002B3F46</string>
<string>6BF7C4021113209A002B3F46</string>
<string>6BF7C4641115C514002B3F46</string>
<string>6BF7C4821115C7C4002B3F46</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>6BF7C6581117142A002B3F46</string>
<string>6BF7C6591117142A002B3F46</string>
<string>6BF7C67C1117163B002B3F46</string>
<string>6BF7C67D1117163B002B3F46</string>
<string>6BF7C68C111720C6002B3F46</string>
<string>6BF7C69A11172159002B3F46</string>
<string>6BF7C69B11172159002B3F46</string>
<string>6BF7C6AA11172278002B3F46</string>
<string>6BF7C6B1111722A5002B3F46</string>
<string>6BF7C6B5111761C3002B3F46</string>
<string>6B324A7C111BF65400EBD2FD</string>
<string>6B324AA7111BF92500EBD2FD</string>
<string>6B324AC1111C00D700EBD2FD</string>
<string>6B324AC2111C00D700EBD2FD</string>
<string>6B324AC3111C00D700EBD2FD</string>
<string>6B324AC4111C00D700EBD2FD</string>
<string>6B324AC5111C00D700EBD2FD</string>
<string>6B324AC6111C00D700EBD2FD</string>
<string>6B324AC8111C00D700EBD2FD</string>
<string>6B324AC9111C00D700EBD2FD</string>
<string>6B324ACA111C00D700EBD2FD</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>
<key>prevStack</key>
<array>
<string>6B9869FC10DFFA98007D8D84</string>
<string>6BBB87E510EA97CC008FEA1F</string>
<string>6BBB87E910EA97CC008FEA1F</string>
<string>6BBB883F10EA9B6F008FEA1F</string>
<string>6BBB885510EA9ECC008FEA1F</string>
<string>6BBB889D10EAA094008FEA1F</string>
@ -412,7 +412,6 @@
<string>6BB7FE2110F37CF7006DA0A6</string>
<string>6BB7FE2210F37CF7006DA0A6</string>
<string>6BB7FE5410F3817A006DA0A6</string>
<string>6BB7FECF10F4B5E1006DA0A6</string>
<string>6BB7FF2410F4D699006DA0A6</string>
<string>6BB7FF9610F4E8E2006DA0A6</string>
<string>6BB700C310FA3AB1006DA0A6</string>
@ -428,37 +427,26 @@
<string>6BF7C0F611116E74002B3F46</string>
<string>6BF7C10811116E74002B3F46</string>
<string>6BF7C10E11116E74002B3F46</string>
<string>6BF7C11511116E74002B3F46</string>
<string>6BF7C16E11119D8F002B3F46</string>
<string>6BF7C1E51111BD81002B3F46</string>
<string>6BF7C1F21111C0A6002B3F46</string>
<string>6BF7C15711119BB4002B3F46</string>
<string>6BF7C30C1112D8C1002B3F46</string>
<string>6BF7C399111316AD002B3F46</string>
<string>6BF7C39C111316AD002B3F46</string>
<string>6BB7FDD910F37703006DA0A6</string>
<string>6BF7C16711119C69002B3F46</string>
<string>6BF7C3D711131F26002B3F46</string>
<string>6BF7C3E211131F26002B3F46</string>
<string>6BF7C4661115C514002B3F46</string>
<string>6BF7C4671115C514002B3F46</string>
<string>6BF7C46A1115C514002B3F46</string>
<string>6BF7C52F1115FA3B002B3F46</string>
<string>6BF7C5F11116F280002B3F46</string>
<string>6BF7C6081116F61A002B3F46</string>
<string>6BF7C11111116E74002B3F46</string>
<string>6BF7C66A1117142A002B3F46</string>
<string>6BF7C678111715D1002B3F46</string>
<string>6BF7C6801117163B002B3F46</string>
<string>6BF7C690111720C6002B3F46</string>
<string>6BF7C6A411172253002B3F46</string>
<string>6B324A7E111BF65400EBD2FD</string>
<string>6B324AA8111BF92500EBD2FD</string>
<string>6B324AA9111BF92500EBD2FD</string>
<string>6B324AAA111BF92500EBD2FD</string>
<string>6B324AB5111BFEFD00EBD2FD</string>
<string>6B324AB6111BFEFD00EBD2FD</string>
<string>6B324ACC111C00D700EBD2FD</string>
<string>6B324ACD111C00D700EBD2FD</string>
<string>6B324ACE111C00D700EBD2FD</string>
<string>6B324ACF111C00D700EBD2FD</string>
@ -468,9 +456,108 @@
<string>6B324AD3111C00D700EBD2FD</string>
<string>6B324AD4111C00D700EBD2FD</string>
<string>6B324AD5111C00D700EBD2FD</string>
<string>6B324AD6111C00D700EBD2FD</string>
<string>6B324AD7111C00D700EBD2FD</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>
</dict>
<key>SplitCount</key>
@ -484,18 +571,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {876, 423}}</string>
<string>{{0, 0}, {876, 545}}</string>
<key>RubberWindowFrame</key>
<string>11 76 1256 702 0 0 1280 778 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
<string>423pt</string>
<string>545pt</string>
</dict>
<dict>
<key>Proportion</key>
<string>233pt</string>
<string>111pt</string>
<key>Tabs</key>
<array>
<dict>
@ -509,7 +596,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {876, 88}}</string>
<string>{{10, 27}, {876, 48}}</string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@ -525,7 +612,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {876, 138}}</string>
<string>{{10, 27}, {876, 197}}</string>
</dict>
<key>Module</key>
<string>PBXProjectFindModule</string>
@ -563,7 +650,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {876, 206}}</string>
<string>{{10, 27}, {876, 84}}</string>
<key>RubberWindowFrame</key>
<string>11 76 1256 702 0 0 1280 778 </string>
</dict>
@ -672,8 +759,8 @@
<string>yes</string>
<key>sizes</key>
<array>
<string>{{0, 0}, {623, 109}}</string>
<string>{{623, 0}, {633, 109}}</string>
<string>{{0, 0}, {625, 125}}</string>
<string>{{625, 0}, {631, 125}}</string>
</array>
</dict>
<key>VerticalSplitView</key>
@ -688,8 +775,8 @@
<string>yes</string>
<key>sizes</key>
<array>
<string>{{0, 0}, {1256, 109}}</string>
<string>{{0, 109}, {1256, 287}}</string>
<string>{{0, 0}, {1256, 125}}</string>
<string>{{0, 125}, {1256, 271}}</string>
</array>
</dict>
</dict>
@ -719,10 +806,10 @@
<string>Value</string>
<real>85</real>
<string>Summary</string>
<real>403</real>
<real>401</real>
</array>
<key>Frame</key>
<string>{{623, 0}, {633, 109}}</string>
<string>{{625, 0}, {631, 125}}</string>
</dict>
</dict>
<key>Module</key>
@ -785,6 +872,8 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
<string>6B324BD2111C4F7D00EBD2FD</string>
<string>6B324BD3111C4F7D00EBD2FD</string>
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
</array>
<key>WindowString</key>

View File

@ -25,6 +25,7 @@
6B25B6190FFA62BE004F1BC4 /* Sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B25B6140FFA62BE004F1BC4 /* Sample.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 */; };
6B324C66111C5D9A00EBD2FD /* ConvexVolumeTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B324C65111C5D9A00EBD2FD /* ConvexVolumeTool.cpp */; };
6B555DB1100B212E00247EA3 /* imguiRenderGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B555DB0100B212E00247EA3 /* imguiRenderGL.cpp */; };
6B62416A103434880002E346 /* RecastMeshDetail.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6B624169103434880002E346 /* RecastMeshDetail.cpp */; };
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 */; };
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.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 */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
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; };
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; };
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; };
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; };
@ -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; };
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; };
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; };
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; };
@ -270,12 +270,12 @@
6BB7FE8E10F4A175006DA0A6 /* Tools */ = {
isa = PBXGroup;
children = (
6B324C64111C5D9A00EBD2FD /* ConvexVolumeTool.h */,
6B324C65111C5D9A00EBD2FD /* ConvexVolumeTool.cpp */,
6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */,
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */,
6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */,
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */,
6BF7C3C311131B0F002B3F46 /* BoxVolumeTool.h */,
6BF7C3C411131B1F002B3F46 /* BoxVolumeTool.cpp */,
);
name = Tools;
sourceTree = "<group>";
@ -397,8 +397,8 @@
6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */,
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */,
6BF7C1401111953A002B3F46 /* TestCase.cpp in Sources */,
6BF7C3C511131B1F002B3F46 /* BoxVolumeTool.cpp in Sources */,
6BF7C4541115C277002B3F46 /* RecastArea.cpp in Sources */,
6B324C66111C5D9A00EBD2FD /* ConvexVolumeTool.cpp in Sources */,
);
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 "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
{
rcChunkyTriMesh* m_chunkyMesh;
@ -33,13 +42,14 @@ class InputGeom
float m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS*3*2];
float m_offMeshConRads[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;
// Box Volumes.
static const int MAX_BOX_VOLUMES = 256;
float m_boxVolVerts[MAX_BOX_VOLUMES*3*2];
unsigned char m_boxVolTypes[MAX_BOX_VOLUMES];
int m_boxVolCount;
// Convex Volumes.
static const int MAX_VOLUMES = 256;
ConvexVolume m_volumes[MAX_VOLUMES];
int m_volumeCount;
public:
InputGeom();
@ -62,17 +72,20 @@ public:
const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; }
const float* getOffMeshConnectionRads() const { return m_offMeshConRads; }
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 drawOffMeshConnections(struct duDebugDraw* dd, bool hilight = false);
// Box Volumes.
int getBoxVolumeCount() const { return m_boxVolCount; }
const float* getBoxVolumeVerts() const { return m_boxVolVerts; }
const unsigned char* getBoxVolumeTypes() const { return m_boxVolTypes; }
void addBoxVolume(const float* bmin, const float* bmax, unsigned char type);
void deleteBoxVolume(int i);
void drawBoxVolumes(struct duDebugDraw* dd, bool hilight = false);
int getConvexVolumeCount() const { return m_volumeCount; }
const ConvexVolume* getConvexVolumes() const { return m_volumes; }
void addConvexVolume(const float* verts, const int nverts,
const float minh, const float maxh, unsigned char area);
void deleteConvexVolume(int i);
void drawConvexVolumes(struct duDebugDraw* dd, bool hilight = false);
};
#endif // INPUTGEOM_H

View File

@ -22,6 +22,29 @@
#include "DebugDraw.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
{
virtual void depthMask(bool state);
@ -31,6 +54,7 @@ struct DebugDrawGL : public duDebugDraw
virtual void end();
};
// Tool types.
enum SampleToolType
{
TOOL_NONE = 0,
@ -38,7 +62,7 @@ enum SampleToolType
TOOL_TILE_HIGHLIGHT,
TOOL_NAVMESH_TESTER,
TOOL_OFFMESH_CONNECTION,
TOOL_BOX_VOLUME,
TOOL_CONVEX_VOLUME,
};
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 <stdio.h>
#include <ctype.h>
#include <string.h>
#include "Recast.h"
#include "RecastLog.h"
#include "InputGeom.h"
@ -108,7 +109,7 @@ InputGeom::InputGeom() :
m_chunkyMesh(0),
m_mesh(0),
m_offMeshConCount(0),
m_boxVolCount(0)
m_volumeCount(0)
{
}
@ -128,7 +129,7 @@ bool InputGeom::loadMesh(const char* filepath)
m_mesh = 0;
}
m_offMeshConCount = 0;
m_boxVolCount = 0;
m_volumeCount = 0;
m_mesh = new rcMeshLoaderObj;
if (!m_mesh)
@ -182,7 +183,7 @@ bool InputGeom::load(const char* filePath)
fclose(fp);
m_offMeshConCount = 0;
m_boxVolCount = 0;
m_volumeCount = 0;
delete m_mesh;
m_mesh = 0;
@ -216,26 +217,30 @@ bool InputGeom::load(const char* filePath)
if (m_offMeshConCount < MAX_OFFMESH_CONNECTIONS)
{
float* v = &m_offMeshConVerts[m_offMeshConCount*3*2];
int bidir;
int bidir, area = 0, flags = 0;
float rad;
sscanf(row+1, "%f %f %f %f %f %f %f %d",
&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &rad, &bidir);
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, &area, &flags);
m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConDirs[m_offMeshConCount] = bidir;
m_offMeshConAreas[m_offMeshConCount] = area;
m_offMeshConFlags[m_offMeshConCount] = flags;
m_offMeshConCount++;
}
}
else if (row[0] == 'b')
else if (row[0] == 'v')
{
// Box volumes
if (m_boxVolCount < MAX_BOX_VOLUMES)
// Convex volumes
if (m_volumeCount < MAX_VOLUMES)
{
float* v = &m_boxVolVerts[m_boxVolCount*3*2];
int type;
sscanf(row+1, "%f %f %f %f %f %f %d",
&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &type);
m_boxVolTypes[m_boxVolCount] = (unsigned char)type;
m_boxVolCount++;
ConvexVolume* vol = &m_volumes[m_volumeCount++];
sscanf(row+1, "%d %d %f %f", &vol->nverts, &vol->area, &vol->hmin, &vol->hmax);
for (int i = 0; i < vol->nverts; ++i)
{
row[0] = '\0';
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 rad = m_offMeshConRads[i];
const int bidir = m_offMeshConDirs[i];
fprintf(fp, "c %f %f %f %f %f %f %f %d\n",
v[0], v[1], v[2], v[3], v[4], v[5], rad, bidir);
const int area = m_offMeshConAreas[i];
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
for (int i = 0; i < m_boxVolCount; ++i)
// Convex volumes
for (int i = 0; i < m_volumeCount; ++i)
{
const float* v = &m_boxVolVerts[i*3*2];
const int bidir = m_boxVolTypes[i];
fprintf(fp, "b %f %f %f %f %f %f %d\n",
v[0], v[1], v[2], v[3], v[4], v[5], bidir);
ConvexVolume* vol = &m_volumes[i];
fprintf(fp, "v %d %d %f %f\n", vol->nverts, vol->area, vol->hmin, vol->hmax);
for (int i = 0; i < vol->nverts; ++i)
fprintf(fp, "%f %f %f\n", vol->verts[i*3+0], vol->verts[i*3+1], vol->verts[i*3+2]);
}
fclose(fp);
@ -312,12 +319,15 @@ bool InputGeom::raycastMesh(float* src, float* dst, float& tmin)
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;
float* v = &m_offMeshConVerts[m_offMeshConCount*3*2];
m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConDirs[m_offMeshConCount] = bidir;
m_offMeshConAreas[m_offMeshConCount] = area;
m_offMeshConFlags[m_offMeshConCount] = flags;
vcopy(&v[0], spos);
vcopy(&v[3], epos);
m_offMeshConCount++;
@ -332,6 +342,8 @@ void InputGeom::deleteOffMeshConnection(int i)
vcopy(&dst[3], &src[3]);
m_offMeshConRads[i] = m_offMeshConRads[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)
@ -365,47 +377,89 @@ void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool hilight)
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;
float* v = &m_boxVolVerts[m_boxVolCount*3*2];
m_boxVolTypes[m_boxVolCount] = type;
vcopy(&v[0], bmin);
vcopy(&v[3], bmax);
m_boxVolCount++;
if (m_volumeCount >= MAX_VOLUMES) return;
ConvexVolume* vol = &m_volumes[m_volumeCount++];
memset(vol, 0, sizeof(ConvexVolume));
memcpy(vol->verts, verts, sizeof(float)*3*nverts);
vol->hmin = minh;
vol->hmax = maxh;
vol->nverts = nverts;
vol->area = area;
}
void InputGeom::deleteBoxVolume(int i)
void InputGeom::deleteConvexVolume(int i)
{
m_boxVolCount--;
float* src = &m_boxVolVerts[m_boxVolCount*3*2];
float* dst = &m_boxVolVerts[i*3*2];
vcopy(&dst[0], &src[0]);
vcopy(&dst[3], &src[3]);
m_boxVolTypes[i] = m_boxVolTypes[m_boxVolCount];
m_volumeCount--;
m_volumes[i] = m_volumes[m_volumeCount];
}
void InputGeom::drawBoxVolumes(struct duDebugDraw* dd, bool hilight)
void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool hilight)
{
dd->depthMask(false);
dd->begin(DU_DRAW_TRIS);
dd->begin(DU_DRAW_LINES, 2.0f);
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 float* bounds = &m_boxVolVerts[i*3*2];
duAppendBoxWire(dd, bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5], col);
const ConvexVolume* vol = &m_volumes[i];
unsigned int col = duIntToCol(vol->area, 32);
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->begin(DU_DRAW_POINTS, 4.0f);
for (int i = 0; i < m_boxVolCount; ++i)
dd->begin(DU_DRAW_POINTS, 3.0f);
for (int i = 0; i < m_volumeCount; ++i)
{
unsigned int col = duDarkenColor(duIntToCol(m_boxVolTypes[i]+1, 255));
const float* bounds = &m_boxVolVerts[i*3*2];
duAppendBoxPoints(dd, bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5], col);
const ConvexVolume* vol = &m_volumes[i];
unsigned int col = duDarkenColor(duIntToCol(vol->area, 255));
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->depthMask(true);
}

View File

@ -60,7 +60,7 @@ NavMeshTesterTool::NavMeshTesterTool() :
m_sposSet(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_polyPickExt[0] = 2;
@ -127,29 +127,56 @@ void NavMeshTesterTool::handleMenu()
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();
}
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();
}
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");
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();
}
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();
}
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)
{

View File

@ -123,7 +123,9 @@ void OffMeshConnectionTool::handleClick(const float* p, bool shift)
}
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;
}
}

View File

@ -35,7 +35,7 @@
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "OffMeshConnectionTool.h"
#include "BoxVolumeTool.h"
#include "ConvexVolumeTool.h"
#ifdef WIN32
# define snprintf _snprintf
@ -100,9 +100,9 @@ void Sample_SoloMeshSimple::handleTools()
{
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();
@ -293,7 +293,7 @@ void Sample_SoloMeshSimple::handleRender()
glDepthMask(GL_TRUE);
}
m_geom->drawBoxVolumes(&dd);
m_geom->drawConvexVolumes(&dd);
if (m_tool)
m_tool->handleRender();
@ -471,13 +471,9 @@ bool Sample_SoloMeshSimple::handleBuild()
}
// (Optional) Mark areas.
const float* boxVerts = m_geom->getBoxVolumeVerts();
const unsigned char* boxTypes = m_geom->getBoxVolumeTypes();
for (int i = 0; i < m_geom->getBoxVolumeCount(); ++i)
{
const float* v = &boxVerts[i*3*2];
rcMarkBoxArea(&v[0], &v[3], boxTypes[i], *m_chf);
}
const ConvexVolume* vols = m_geom->getConvexVolumes();
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);
// Prepare for region partitioning, by calculating distance field along the walkable surface.
if (!rcBuildDistanceField(*m_chf))
@ -572,11 +568,36 @@ bool Sample_SoloMeshSimple::handleBuild()
unsigned char* navData = 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;
memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys;
params.polyAreas = m_pmesh->areas;
params.polyFlags = m_pmesh->flags;
params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes;
@ -587,6 +608,8 @@ bool Sample_SoloMeshSimple::handleBuild()
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius;

View File

@ -34,7 +34,7 @@
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "OffMeshConnectionTool.h"
#include "BoxVolumeTool.h"
#include "ConvexVolumeTool.h"
#ifdef WIN32
# define snprintf _snprintf
@ -187,9 +187,9 @@ void Sample_SoloMeshTiled::handleTools()
{
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))
{
@ -486,7 +486,7 @@ void Sample_SoloMeshTiled::handleRender()
}
}
m_geom->drawBoxVolumes(&dd);
m_geom->drawConvexVolumes(&dd);
if (m_tool)
m_tool->handleRender();
@ -840,13 +840,10 @@ bool Sample_SoloMeshTiled::handleBuild()
continue;
}
const float* boxVerts = m_geom->getBoxVolumeVerts();
const unsigned char* boxTypes = m_geom->getBoxVolumeTypes();
for (int i = 0; i < m_geom->getBoxVolumeCount(); ++i)
{
const float* v = &boxVerts[i*3*2];
rcMarkBoxArea(&v[0], &v[3], boxTypes[i], *chf);
}
// (Optional) Mark areas.
const ConvexVolume* vols = m_geom->getConvexVolumes();
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);
if (!rcBuildDistanceField(*chf))
{
@ -1022,11 +1019,35 @@ bool Sample_SoloMeshTiled::handleBuild()
unsigned char* navData = 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;
memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys;
params.polyAreas = m_pmesh->areas;
params.polyFlags = m_pmesh->flags;
params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes;
@ -1037,6 +1058,8 @@ bool Sample_SoloMeshTiled::handleBuild()
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius;

View File

@ -34,7 +34,7 @@
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "OffMeshConnectionTool.h"
#include "BoxVolumeTool.h"
#include "ConvexVolumeTool.h"
#ifdef WIN32
# define snprintf _snprintf
@ -258,9 +258,9 @@ void Sample_TileMesh::handleTools()
{
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();
@ -321,7 +321,7 @@ void Sample_TileMesh::handleRender()
if (m_tool)
m_tool->handleRender();
m_geom->drawBoxVolumes(&dd);
m_geom->drawConvexVolumes(&dd);
glDepthMask(GL_TRUE);
}
@ -667,14 +667,10 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
return false;
}
const float* boxVerts = m_geom->getBoxVolumeVerts();
const unsigned char* boxTypes = m_geom->getBoxVolumeTypes();
for (int i = 0; i < m_geom->getBoxVolumeCount(); ++i)
{
const float* v = &boxVerts[i*3*2];
rcMarkBoxArea(&v[0], &v[3], boxTypes[i], *m_chf);
}
// (Optional) Mark areas.
const ConvexVolume* vols = m_geom->getConvexVolumes();
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);
// Prepare for region partitioning, by calculating distance field along the walkable surface.
if (!rcBuildDistanceField(*m_chf))
@ -773,11 +769,35 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
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;
memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys;
params.polyAreas = m_pmesh->areas;
params.polyFlags = m_pmesh->flags;
params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp;
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.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius;