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:
Domenico Albani
2017-03-12 12:18:29 +01:00
committed by Jakob Botsch Nielsen
parent ef3ea40f7a
commit 433986a5a4
15 changed files with 200 additions and 134 deletions
+33 -10
View File
@@ -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.
+47 -2
View File
@@ -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]);
}
}
+6 -6
View File
@@ -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]);
}
}
}
+1 -1
View File
@@ -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;
+4 -2
View File
@@ -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
View File
@@ -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:
+21 -15
View File
@@ -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);
}
}
+7 -7
View File
@@ -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);
+6 -6
View File
@@ -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;
+1 -1
View File
@@ -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;
+40 -12
View File
@@ -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() :
+3 -19
View File
@@ -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]);
}
+4 -19
View File
@@ -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();
+3 -19
View File
@@ -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;
+4 -4
View File
@@ -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);
}
}