mirror of
https://github.com/recastnavigation/recastnavigation.git
synced 2026-10-30 20:45:49 +00:00
Implement more complex area modifications (#260)
This implements rcAreaModification which allows combining of area types when they overlap and otherwise usage of the area type as a bit mask.
This commit is contained in:
committed by
Jakob Botsch Nielsen
parent
ef3ea40f7a
commit
433986a5a4
+33
-10
@@ -441,6 +441,29 @@ struct rcPolyMeshDetail
|
||||
int ntris; ///< The number of triangles in #tris.
|
||||
};
|
||||
|
||||
static const unsigned char RC_AREA_FLAGS_MASK = 0x3F;
|
||||
|
||||
/// @ingroup recast
|
||||
class rcAreaModification
|
||||
{
|
||||
public:
|
||||
/// Mask is set to all available bits, which means value is fully applied
|
||||
/// @param[in] value The area id to apply. [Limit: <= #RC_AREA_FLAGS_MASK]
|
||||
rcAreaModification(unsigned char value);
|
||||
/// @param[in] value The area id to apply. [Limit: <= #RC_AREA_FLAGS_MASK]
|
||||
/// @param[in] mask Bitwise mask used when applying value. [Limit: <= #RC_AREA_FLAGS_MASK]
|
||||
rcAreaModification(unsigned char value, unsigned char mask);
|
||||
rcAreaModification(const rcAreaModification& other);
|
||||
void operator = (const rcAreaModification& other);
|
||||
bool operator == (const rcAreaModification& other) const;
|
||||
bool operator != (const rcAreaModification& other) const;
|
||||
void apply(unsigned char& area) const;
|
||||
unsigned char getMaskedValue() const;
|
||||
|
||||
unsigned char m_value; ///< Value to apply to target area id
|
||||
unsigned char m_mask; ///< Bitwise mask used when applying value to target area id
|
||||
};
|
||||
|
||||
/// @name Allocation Functions
|
||||
/// Functions used to allocate and de-allocate Recast objects.
|
||||
/// @see rcAllocSetCustom
|
||||
@@ -790,8 +813,7 @@ bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int heigh
|
||||
const float* bmin, const float* bmax,
|
||||
float cs, float ch);
|
||||
|
||||
/// Sets the area id of all triangles with a slope below the specified value
|
||||
/// to #RC_WALKABLE_AREA.
|
||||
/// Modifies the area id of all triangles with a slope below the specified value.
|
||||
/// @ingroup recast
|
||||
/// @param[in,out] ctx The build context to use during the operation.
|
||||
/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable.
|
||||
@@ -801,10 +823,11 @@ bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int heigh
|
||||
/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt]
|
||||
/// @param[in] nt The number of triangles.
|
||||
/// @param[out] areas The triangle area ids. [Length: >= @p nt]
|
||||
/// @param[in] areaMod The area modification to apply.
|
||||
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
||||
const int* tris, int nt, unsigned char* areas);
|
||||
const int* tris, int nt, unsigned char* areas, rcAreaModification areaMod);
|
||||
|
||||
/// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA.
|
||||
/// Modifies the area id of all triangles with a slope greater than or equal to the specified value.
|
||||
/// @ingroup recast
|
||||
/// @param[in,out] ctx The build context to use during the operation.
|
||||
/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable.
|
||||
@@ -966,9 +989,9 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf);
|
||||
/// @param[in,out] ctx The build context to use during the operation.
|
||||
/// @param[in] bmin The minimum of the bounding box. [(x, y, z)]
|
||||
/// @param[in] bmax The maximum of the bounding box. [(x, y, z)]
|
||||
/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
|
||||
/// @param[in] areaMod The area modification to apply.
|
||||
/// @param[in,out] chf A populated compact heightfield.
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, rcAreaModification areaMod,
|
||||
rcCompactHeightfield& chf);
|
||||
|
||||
/// Applies the area id to the all spans within the specified convex polygon.
|
||||
@@ -978,10 +1001,10 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne
|
||||
/// @param[in] nverts The number of vertices in the polygon.
|
||||
/// @param[in] hmin The height of the base of the polygon.
|
||||
/// @param[in] hmax The height of the top of the polygon.
|
||||
/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
|
||||
/// @param[in] areaMod The area modification to apply.
|
||||
/// @param[in,out] chf A populated compact heightfield.
|
||||
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||||
const float hmin, const float hmax, unsigned char areaId,
|
||||
const float hmin, const float hmax, rcAreaModification areaMod,
|
||||
rcCompactHeightfield& chf);
|
||||
|
||||
/// Helper function to offset voncex polygons for rcMarkConvexPolyArea.
|
||||
@@ -1000,10 +1023,10 @@ int rcOffsetPoly(const float* verts, const int nverts, const float offset,
|
||||
/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)]
|
||||
/// @param[in] r The radius of the cylinder.
|
||||
/// @param[in] h The height of the cylinder.
|
||||
/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
|
||||
/// @param[in] areaMod The area modification to apply.
|
||||
/// @param[in,out] chf A populated compact heightfield.
|
||||
void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
||||
const float r, const float h, unsigned char areaId,
|
||||
const float r, const float h, rcAreaModification areaMod,
|
||||
rcCompactHeightfield& chf);
|
||||
|
||||
/// Builds the distance field for the specified compact heightfield.
|
||||
|
||||
@@ -71,6 +71,50 @@ void rcContext::log(const rcLogCategory category, const char* format, ...)
|
||||
doLog(category, msg, len);
|
||||
}
|
||||
|
||||
rcAreaModification::rcAreaModification(unsigned char value) :
|
||||
m_value(value),
|
||||
m_mask(RC_AREA_FLAGS_MASK)
|
||||
{
|
||||
}
|
||||
|
||||
rcAreaModification::rcAreaModification(unsigned char value, unsigned char mask) :
|
||||
m_value(value),
|
||||
m_mask(mask)
|
||||
{
|
||||
}
|
||||
|
||||
rcAreaModification::rcAreaModification(const rcAreaModification& other) :
|
||||
m_value(other.m_value),
|
||||
m_mask(other.m_mask)
|
||||
{
|
||||
}
|
||||
|
||||
void rcAreaModification::operator = (const rcAreaModification& other)
|
||||
{
|
||||
m_value = other.m_value;
|
||||
m_mask = other.m_mask;
|
||||
}
|
||||
|
||||
bool rcAreaModification::operator == (const rcAreaModification& other) const
|
||||
{
|
||||
return ((m_value == other.m_value) && (m_mask == other.m_mask));
|
||||
}
|
||||
|
||||
bool rcAreaModification::operator != (const rcAreaModification& other) const
|
||||
{
|
||||
return ((m_value == other.m_value) && (m_mask == other.m_mask));
|
||||
}
|
||||
|
||||
void rcAreaModification::apply(unsigned char& area) const
|
||||
{
|
||||
area = ((m_value & m_mask) | (area & ~m_mask));
|
||||
}
|
||||
|
||||
unsigned char rcAreaModification::getMaskedValue() const
|
||||
{
|
||||
return (m_value & m_mask);
|
||||
}
|
||||
|
||||
rcHeightfield* rcAllocHeightfield()
|
||||
{
|
||||
return new (rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM)) rcHeightfield;
|
||||
@@ -263,7 +307,8 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
|
||||
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
|
||||
const float* verts, int nv,
|
||||
const int* tris, int nt,
|
||||
unsigned char* areas)
|
||||
unsigned char* areas,
|
||||
rcAreaModification areaMod)
|
||||
{
|
||||
rcIgnoreUnused(ctx);
|
||||
rcIgnoreUnused(nv);
|
||||
@@ -278,7 +323,7 @@ void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] > walkableThr)
|
||||
areas[i] = RC_WALKABLE_AREA;
|
||||
areaMod.apply(areas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
|
||||
/// The value of spacial parameters are in world units.
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||||
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, rcAreaModification areaMod,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
@@ -348,7 +348,7 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne
|
||||
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||||
{
|
||||
if (chf.areas[i] != RC_NULL_AREA)
|
||||
chf.areas[i] = areaId;
|
||||
areaMod.apply(chf.areas[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,7 +379,7 @@ static int pointInPoly(int nvert, const float* verts, const float* p)
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||||
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||||
const float hmin, const float hmax, unsigned char areaId,
|
||||
const float hmin, const float hmax, rcAreaModification areaMod,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
@@ -435,7 +435,7 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||||
|
||||
if (pointInPoly(nverts, verts, p))
|
||||
{
|
||||
chf.areas[i] = areaId;
|
||||
areaMod.apply(chf.areas[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,7 +527,7 @@ int rcOffsetPoly(const float* verts, const int nverts, const float offset,
|
||||
///
|
||||
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||||
void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
||||
const float r, const float h, unsigned char areaId,
|
||||
const float r, const float h, rcAreaModification areaMod,
|
||||
rcCompactHeightfield& chf)
|
||||
{
|
||||
rcAssert(ctx);
|
||||
@@ -582,7 +582,7 @@ void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
||||
|
||||
if (dx*dx + dz*dz < r2)
|
||||
{
|
||||
chf.areas[i] = areaId;
|
||||
areaMod.apply(chf.areas[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
class ConvexVolumeTool : public SampleTool
|
||||
{
|
||||
Sample* m_sample;
|
||||
int m_areaType;
|
||||
rcAreaModification m_areaMod;
|
||||
float m_polyOffset;
|
||||
float m_boxHeight;
|
||||
float m_boxDescent;
|
||||
|
||||
@@ -21,14 +21,16 @@
|
||||
|
||||
#include "ChunkyTriMesh.h"
|
||||
#include "MeshLoaderObj.h"
|
||||
#include "Recast.h"
|
||||
|
||||
static const int MAX_CONVEXVOL_PTS = 12;
|
||||
struct ConvexVolume
|
||||
{
|
||||
ConvexVolume(): areaMod(RC_AREA_FLAGS_MASK) {}
|
||||
float verts[MAX_CONVEXVOL_PTS*3];
|
||||
float hmin, hmax;
|
||||
int nverts;
|
||||
int area;
|
||||
rcAreaModification areaMod;
|
||||
};
|
||||
|
||||
struct BuildSettings
|
||||
@@ -136,7 +138,7 @@ public:
|
||||
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);
|
||||
const float minh, const float maxh, rcAreaModification areaMod);
|
||||
void deleteConvexVolume(int i);
|
||||
void drawConvexVolumes(struct duDebugDraw* dd, bool hilight = false);
|
||||
///@}
|
||||
|
||||
+20
-11
@@ -38,17 +38,24 @@ enum SampleToolType
|
||||
MAX_TOOLS
|
||||
};
|
||||
|
||||
/// 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,
|
||||
};
|
||||
/// Mask of the ceil part of the area id (3 lower bits)
|
||||
/// the 0 value (RC_NULL_AREA) is left unused
|
||||
static const unsigned char SAMPLE_POLYAREA_TYPE_MASK = 0x07;
|
||||
/// Value for the kind of ceil "ground"
|
||||
static const unsigned char SAMPLE_POLYAREA_TYPE_GROUND = 0x1;
|
||||
/// Value for the kind of ceil "water"
|
||||
static const unsigned char SAMPLE_POLYAREA_TYPE_WATER = 0x2;
|
||||
/// Value for the kind of ceil "road"
|
||||
static const unsigned char SAMPLE_POLYAREA_TYPE_ROAD = 0x3;
|
||||
/// Value for the kind of ceil "grass"
|
||||
static const unsigned char SAMPLE_POLYAREA_TYPE_GRASS = 0x4;
|
||||
/// Flag for door area. Can be combined with area types and jump flag.
|
||||
static const unsigned char SAMPLE_POLYAREA_FLAG_DOOR = 0x08;
|
||||
/// Flag for jump area. Can be combined with area types and door flag.
|
||||
static const unsigned char SAMPLE_POLYAREA_FLAG_JUMP = 0x10;
|
||||
|
||||
extern rcAreaModification const SAMPLE_AREAMOD_GROUND;
|
||||
|
||||
enum SamplePolyFlags
|
||||
{
|
||||
SAMPLE_POLYFLAGS_WALK = 0x01, // Ability to walk (ground, grass, road)
|
||||
@@ -59,6 +66,8 @@ enum SamplePolyFlags
|
||||
SAMPLE_POLYFLAGS_ALL = 0xffff // All abilities.
|
||||
};
|
||||
|
||||
unsigned short sampleAreaToFlags(unsigned char area);
|
||||
|
||||
class SampleDebugDraw : public DebugDrawGL
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -97,10 +97,16 @@ static int pointInPoly(int nvert, const float* verts, const float* p)
|
||||
return c;
|
||||
}
|
||||
|
||||
rcAreaModification const SAMPLE_AREAMOD_GROUND(SAMPLE_POLYAREA_TYPE_GROUND, SAMPLE_POLYAREA_TYPE_MASK);
|
||||
static rcAreaModification const SAMPLE_AREAMOD_WATER(SAMPLE_POLYAREA_TYPE_WATER, SAMPLE_POLYAREA_TYPE_MASK);
|
||||
static rcAreaModification const SAMPLE_AREAMOD_ROAD(SAMPLE_POLYAREA_TYPE_ROAD, SAMPLE_POLYAREA_TYPE_MASK);
|
||||
static rcAreaModification const SAMPLE_AREAMOD_GRASS(SAMPLE_POLYAREA_TYPE_GRASS, SAMPLE_POLYAREA_TYPE_MASK);
|
||||
static rcAreaModification const SAMPLE_AREAMOD_DOOR(SAMPLE_POLYAREA_FLAG_DOOR, SAMPLE_POLYAREA_FLAG_DOOR);
|
||||
static rcAreaModification const SAMPLE_AREAMOD_JUMP(SAMPLE_POLYAREA_FLAG_JUMP, SAMPLE_POLYAREA_FLAG_JUMP);
|
||||
|
||||
ConvexVolumeTool::ConvexVolumeTool() :
|
||||
m_sample(0),
|
||||
m_areaType(SAMPLE_POLYAREA_GRASS),
|
||||
m_areaMod(SAMPLE_AREAMOD_GRASS),
|
||||
m_polyOffset(0.0f),
|
||||
m_boxHeight(6.0f),
|
||||
m_boxDescent(1.0f),
|
||||
@@ -130,18 +136,18 @@ void ConvexVolumeTool::handleMenu()
|
||||
|
||||
imguiLabel("Area Type");
|
||||
imguiIndent();
|
||||
if (imguiCheck("Ground", m_areaType == SAMPLE_POLYAREA_GROUND))
|
||||
m_areaType = SAMPLE_POLYAREA_GROUND;
|
||||
if (imguiCheck("Water", m_areaType == SAMPLE_POLYAREA_WATER))
|
||||
m_areaType = SAMPLE_POLYAREA_WATER;
|
||||
if (imguiCheck("Road", m_areaType == SAMPLE_POLYAREA_ROAD))
|
||||
m_areaType = SAMPLE_POLYAREA_ROAD;
|
||||
if (imguiCheck("Door", m_areaType == SAMPLE_POLYAREA_DOOR))
|
||||
m_areaType = SAMPLE_POLYAREA_DOOR;
|
||||
if (imguiCheck("Grass", m_areaType == SAMPLE_POLYAREA_GRASS))
|
||||
m_areaType = SAMPLE_POLYAREA_GRASS;
|
||||
if (imguiCheck("Jump", m_areaType == SAMPLE_POLYAREA_JUMP))
|
||||
m_areaType = SAMPLE_POLYAREA_JUMP;
|
||||
if (imguiCheck("Ground", m_areaMod == SAMPLE_AREAMOD_GROUND))
|
||||
m_areaMod = SAMPLE_AREAMOD_GROUND;
|
||||
if (imguiCheck("Water", m_areaMod == SAMPLE_AREAMOD_WATER))
|
||||
m_areaMod = SAMPLE_AREAMOD_WATER;
|
||||
if (imguiCheck("Road", m_areaMod == SAMPLE_AREAMOD_ROAD))
|
||||
m_areaMod = SAMPLE_AREAMOD_ROAD;
|
||||
if (imguiCheck("Grass", m_areaMod == SAMPLE_AREAMOD_GRASS))
|
||||
m_areaMod = SAMPLE_AREAMOD_GRASS;
|
||||
if (imguiCheck("Door", m_areaMod == SAMPLE_AREAMOD_DOOR))
|
||||
m_areaMod = SAMPLE_AREAMOD_DOOR;
|
||||
if (imguiCheck("Jump", m_areaMod == SAMPLE_AREAMOD_JUMP))
|
||||
m_areaMod = SAMPLE_AREAMOD_JUMP;
|
||||
imguiUnindent();
|
||||
|
||||
imguiSeparator();
|
||||
@@ -203,11 +209,11 @@ void ConvexVolumeTool::handleClick(const float* /*s*/, const float* p, bool shif
|
||||
float offset[MAX_PTS*2*3];
|
||||
int noffset = rcOffsetPoly(verts, m_nhull, m_polyOffset, offset, MAX_PTS*2);
|
||||
if (noffset > 0)
|
||||
geom->addConvexVolume(offset, noffset, minh, maxh, (unsigned char)m_areaType);
|
||||
geom->addConvexVolume(offset, noffset, minh, maxh, m_areaMod);
|
||||
}
|
||||
else
|
||||
{
|
||||
geom->addConvexVolume(verts, m_nhull, minh, maxh, (unsigned char)m_areaType);
|
||||
geom->addConvexVolume(verts, m_nhull, minh, maxh, m_areaMod);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ bool InputGeom::loadGeomSet(rcContext* ctx, const std::string& filepath)
|
||||
if (m_volumeCount < MAX_VOLUMES)
|
||||
{
|
||||
ConvexVolume* vol = &m_volumes[m_volumeCount++];
|
||||
sscanf(row+1, "%d %d %f %f", &vol->nverts, &vol->area, &vol->hmin, &vol->hmax);
|
||||
sscanf(row+1, "%d %c %c %f %f", &vol->nverts, &vol->areaMod.m_value, &vol->areaMod.m_mask, &vol->hmin, &vol->hmax);
|
||||
for (int i = 0; i < vol->nverts; ++i)
|
||||
{
|
||||
row[0] = '\0';
|
||||
@@ -375,7 +375,7 @@ bool InputGeom::saveGeomSet(const BuildSettings* settings)
|
||||
for (int i = 0; i < m_volumeCount; ++i)
|
||||
{
|
||||
ConvexVolume* vol = &m_volumes[i];
|
||||
fprintf(fp, "v %d %d %f %f\n", vol->nverts, vol->area, vol->hmin, vol->hmax);
|
||||
fprintf(fp, "v %d %c %c %f %f\n", vol->nverts, vol->areaMod.m_value, vol->areaMod.m_mask, vol->hmin, vol->hmax);
|
||||
for (int j = 0; j < vol->nverts; ++j)
|
||||
fprintf(fp, "%f %f %f\n", vol->verts[j*3+0], vol->verts[j*3+1], vol->verts[j*3+2]);
|
||||
}
|
||||
@@ -529,7 +529,7 @@ void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool hilight)
|
||||
}
|
||||
|
||||
void InputGeom::addConvexVolume(const float* verts, const int nverts,
|
||||
const float minh, const float maxh, unsigned char area)
|
||||
const float minh, const float maxh, rcAreaModification areaMod)
|
||||
{
|
||||
if (m_volumeCount >= MAX_VOLUMES) return;
|
||||
ConvexVolume* vol = &m_volumes[m_volumeCount++];
|
||||
@@ -538,7 +538,7 @@ void InputGeom::addConvexVolume(const float* verts, const int nverts,
|
||||
vol->hmin = minh;
|
||||
vol->hmax = maxh;
|
||||
vol->nverts = nverts;
|
||||
vol->area = area;
|
||||
vol->areaMod = areaMod;
|
||||
}
|
||||
|
||||
void InputGeom::deleteConvexVolume(int i)
|
||||
@@ -556,7 +556,7 @@ void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool /*hilight*/)
|
||||
for (int i = 0; i < m_volumeCount; ++i)
|
||||
{
|
||||
const ConvexVolume* vol = &m_volumes[i];
|
||||
unsigned int col = duTransCol(dd->areaToCol(vol->area), 32);
|
||||
unsigned int col = duTransCol(dd->areaToCol(vol->areaMod.getMaskedValue()), 32);
|
||||
for (int j = 0, k = vol->nverts-1; j < vol->nverts; k = j++)
|
||||
{
|
||||
const float* va = &vol->verts[k*3];
|
||||
@@ -582,7 +582,7 @@ void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool /*hilight*/)
|
||||
for (int i = 0; i < m_volumeCount; ++i)
|
||||
{
|
||||
const ConvexVolume* vol = &m_volumes[i];
|
||||
unsigned int col = duTransCol(dd->areaToCol(vol->area), 220);
|
||||
unsigned int col = duTransCol(dd->areaToCol(vol->areaMod.getMaskedValue()), 220);
|
||||
for (int j = 0, k = vol->nverts-1; j < vol->nverts; k = j++)
|
||||
{
|
||||
const float* va = &vol->verts[k*3];
|
||||
@@ -601,7 +601,7 @@ void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool /*hilight*/)
|
||||
for (int i = 0; i < m_volumeCount; ++i)
|
||||
{
|
||||
const ConvexVolume* vol = &m_volumes[i];
|
||||
unsigned int col = duDarkenCol(duTransCol(dd->areaToCol(vol->area), 220));
|
||||
unsigned int col = duDarkenCol(duTransCol(dd->areaToCol(vol->areaMod.getMaskedValue()), 220));
|
||||
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);
|
||||
|
||||
@@ -257,12 +257,12 @@ void NavMeshTesterTool::init(Sample* sample)
|
||||
if (m_navQuery)
|
||||
{
|
||||
// Change costs.
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_WATER, 10.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_ROAD, 1.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_DOOR, 1.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_GRASS, 2.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_JUMP, 1.5f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_TYPE_GROUND, 1.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_TYPE_WATER, 10.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_TYPE_ROAD, 1.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_FLAG_DOOR, 1.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_TYPE_GRASS, 2.0f);
|
||||
m_filter.setAreaCost(SAMPLE_POLYAREA_FLAG_JUMP, 1.5f);
|
||||
}
|
||||
|
||||
m_neighbourhoodRadius = sample->getAgentRadius() * 20.0f;
|
||||
|
||||
@@ -119,7 +119,7 @@ void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, bool
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned char area = SAMPLE_POLYAREA_JUMP;
|
||||
const unsigned char area = SAMPLE_POLYAREA_FLAG_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;
|
||||
|
||||
@@ -35,25 +35,53 @@
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
unsigned short sampleAreaToFlags(unsigned char area)
|
||||
{
|
||||
unsigned char areaType = (area & SAMPLE_POLYAREA_TYPE_MASK);
|
||||
unsigned short flags = (unsigned short)((areaType == SAMPLE_POLYAREA_TYPE_WATER) ? SAMPLE_POLYFLAGS_SWIM : SAMPLE_POLYFLAGS_WALK);
|
||||
if((areaType & SAMPLE_POLYAREA_FLAG_DOOR) != 0)
|
||||
{
|
||||
flags |= SAMPLE_POLYFLAGS_DOOR;
|
||||
}
|
||||
if((areaType & SAMPLE_POLYAREA_FLAG_JUMP) != 0)
|
||||
{
|
||||
flags |= SAMPLE_POLYFLAGS_JUMP;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
unsigned int SampleDebugDraw::areaToCol(unsigned int area)
|
||||
{
|
||||
switch(area)
|
||||
unsigned int col;
|
||||
|
||||
unsigned char ceil = (area & SAMPLE_POLYAREA_TYPE_MASK);
|
||||
switch(ceil)
|
||||
{
|
||||
// Ground (0) : light blue
|
||||
case SAMPLE_POLYAREA_GROUND: return duRGBA(0, 192, 255, 255);
|
||||
// Ground : light blue
|
||||
case SAMPLE_POLYAREA_TYPE_GROUND: col = duRGBA(0, 192, 255, 255); break;
|
||||
// Water : blue
|
||||
case SAMPLE_POLYAREA_WATER: return duRGBA(0, 0, 255, 255);
|
||||
case SAMPLE_POLYAREA_TYPE_WATER: col = duRGBA(0, 0, 255, 255); break;
|
||||
// Road : brown
|
||||
case SAMPLE_POLYAREA_ROAD: return duRGBA(50, 20, 12, 255);
|
||||
// Door : cyan
|
||||
case SAMPLE_POLYAREA_DOOR: return duRGBA(0, 255, 255, 255);
|
||||
case SAMPLE_POLYAREA_TYPE_ROAD: col = duRGBA(50, 20, 12, 255); break;
|
||||
// Grass : green
|
||||
case SAMPLE_POLYAREA_GRASS: return duRGBA(0, 255, 0, 255);
|
||||
// Jump : yellow
|
||||
case SAMPLE_POLYAREA_JUMP: return duRGBA(255, 255, 0, 255);
|
||||
// Unexpected : red
|
||||
default: return duRGBA(255, 0, 0, 255);
|
||||
case SAMPLE_POLYAREA_TYPE_GRASS: col = duRGBA(0, 255, 0, 255); break;
|
||||
// Unexpected ceil : red
|
||||
default: col = duRGBA(255, 0, 0, 255); break;
|
||||
}
|
||||
|
||||
if(area & SAMPLE_POLYAREA_FLAG_DOOR)
|
||||
{
|
||||
// Door : cyan
|
||||
col = duLerpCol(col, duRGBA(0, 255, 255, 255), 127);
|
||||
}
|
||||
if(area & SAMPLE_POLYAREA_FLAG_JUMP)
|
||||
{
|
||||
// Jump : yellow
|
||||
col = duLerpCol(col, duRGBA(255, 255, 0, 255), 127);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
Sample::Sample() :
|
||||
|
||||
@@ -435,7 +435,7 @@ bool Sample_SoloMesh::handleBuild()
|
||||
// If your input data is multiple meshes, you can transform them here, calculate
|
||||
// the are type for each of the meshes and rasterize them.
|
||||
memset(m_triareas, 0, ntris*sizeof(unsigned char));
|
||||
rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triareas);
|
||||
rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triareas, SAMPLE_AREAMOD_GROUND);
|
||||
if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, m_triareas, ntris, *m_solid, m_cfg.walkableClimb))
|
||||
{
|
||||
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not rasterize triangles.");
|
||||
@@ -498,7 +498,7 @@ bool Sample_SoloMesh::handleBuild()
|
||||
// (Optional) Mark areas.
|
||||
const ConvexVolume* vols = m_geom->getConvexVolumes();
|
||||
for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
|
||||
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
|
||||
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, vols[i].areaMod, *m_chf);
|
||||
|
||||
|
||||
// Partition the heightfield so that we can use simple algorithm later to triangulate the walkable areas.
|
||||
@@ -639,23 +639,7 @@ bool Sample_SoloMesh::handleBuild()
|
||||
// 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;
|
||||
}
|
||||
m_pmesh->flags[i] = sampleAreaToFlags(m_pmesh->areas[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -195,23 +195,7 @@ struct MeshProcess : public dtTileCacheMeshProcess
|
||||
// Update poly flags from areas.
|
||||
for (int i = 0; i < params->polyCount; ++i)
|
||||
{
|
||||
if (polyAreas[i] == DT_TILECACHE_WALKABLE_AREA)
|
||||
polyAreas[i] = SAMPLE_POLYAREA_GROUND;
|
||||
|
||||
if (polyAreas[i] == SAMPLE_POLYAREA_GROUND ||
|
||||
polyAreas[i] == SAMPLE_POLYAREA_GRASS ||
|
||||
polyAreas[i] == SAMPLE_POLYAREA_ROAD)
|
||||
{
|
||||
polyFlags[i] = SAMPLE_POLYFLAGS_WALK;
|
||||
}
|
||||
else if (polyAreas[i] == SAMPLE_POLYAREA_WATER)
|
||||
{
|
||||
polyFlags[i] = SAMPLE_POLYFLAGS_SWIM;
|
||||
}
|
||||
else if (polyAreas[i] == SAMPLE_POLYAREA_DOOR)
|
||||
{
|
||||
polyFlags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
|
||||
}
|
||||
polyFlags[i] = sampleAreaToFlags(polyAreas[i]);
|
||||
}
|
||||
|
||||
// Pass in off-mesh connections.
|
||||
@@ -351,7 +335,8 @@ int Sample_TempObstacles::rasterizeTileLayers(
|
||||
|
||||
memset(rc.triareas, 0, ntris*sizeof(unsigned char));
|
||||
rcMarkWalkableTriangles(m_ctx, tcfg.walkableSlopeAngle,
|
||||
verts, nverts, tris, ntris, rc.triareas);
|
||||
verts, nverts, tris, ntris, rc.triareas,
|
||||
SAMPLE_AREAMOD_GROUND);
|
||||
|
||||
if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, rc.triareas, ntris, *rc.solid, tcfg.walkableClimb))
|
||||
return 0;
|
||||
@@ -393,7 +378,7 @@ int Sample_TempObstacles::rasterizeTileLayers(
|
||||
{
|
||||
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts,
|
||||
vols[i].hmin, vols[i].hmax,
|
||||
(unsigned char)vols[i].area, *rc.chf);
|
||||
vols[i].areaMod, *rc.chf);
|
||||
}
|
||||
|
||||
rc.lset = rcAllocHeightfieldLayerSet();
|
||||
|
||||
@@ -1039,7 +1039,7 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
|
||||
|
||||
memset(m_triareas, 0, nctris*sizeof(unsigned char));
|
||||
rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle,
|
||||
verts, nverts, ctris, nctris, m_triareas);
|
||||
verts, nverts, ctris, nctris, m_triareas, SAMPLE_AREAMOD_GROUND);
|
||||
|
||||
if (!rcRasterizeTriangles(m_ctx, verts, nverts, ctris, m_triareas, nctris, *m_solid, m_cfg.walkableClimb))
|
||||
return 0;
|
||||
@@ -1092,7 +1092,7 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
|
||||
// (Optional) Mark areas.
|
||||
const ConvexVolume* vols = m_geom->getConvexVolumes();
|
||||
for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
|
||||
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
|
||||
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, vols[i].areaMod, *m_chf);
|
||||
|
||||
|
||||
// Partition the heightfield so that we can use simple algorithm later to triangulate the walkable areas.
|
||||
@@ -1226,23 +1226,7 @@ unsigned char* Sample_TileMesh::buildTileMesh(const int tx, const int ty, const
|
||||
// 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;
|
||||
}
|
||||
m_pmesh->flags[i] = sampleAreaToFlags(m_pmesh->areas[i]);
|
||||
}
|
||||
|
||||
dtNavMeshCreateParams params;
|
||||
|
||||
@@ -448,27 +448,27 @@ TEST_CASE("rcMarkWalkableTriangles")
|
||||
|
||||
SECTION("One walkable triangle")
|
||||
{
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas, rcAreaModification(RC_WALKABLE_AREA));
|
||||
REQUIRE(areas[0] == RC_WALKABLE_AREA);
|
||||
}
|
||||
|
||||
SECTION("One non-walkable triangle")
|
||||
{
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas, rcAreaModification(RC_WALKABLE_AREA));
|
||||
REQUIRE(areas[0] == RC_NULL_AREA);
|
||||
}
|
||||
|
||||
SECTION("Non-walkable triangle area id's are not modified")
|
||||
{
|
||||
areas[0] = 42;
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas);
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, unwalkable_tri, nt, areas, rcAreaModification(RC_WALKABLE_AREA));
|
||||
REQUIRE(areas[0] == 42);
|
||||
}
|
||||
|
||||
SECTION("Slopes equal to the max slope are considered unwalkable.")
|
||||
{
|
||||
walkableSlopeAngle = 0;
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas);
|
||||
rcMarkWalkableTriangles(ctx, walkableSlopeAngle, verts, nv, walkable_tri, nt, areas, rcAreaModification(RC_WALKABLE_AREA));
|
||||
REQUIRE(areas[0] == RC_NULL_AREA);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user