a3dc7b3f48
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
1693 lines
77 KiB
C#
1693 lines
77 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
public static partial class Recast {
|
|
|
|
/// The value of PI used by Recast.
|
|
public const float RC_PI = 3.14159265f;
|
|
|
|
/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
|
|
public const int RC_SPAN_HEIGHT_BITS = 13;
|
|
/// Defines the maximum value for rcSpan::smin and rcSpan::smax.
|
|
public const int RC_SPAN_MAX_HEIGHT = (1 << RC_SPAN_HEIGHT_BITS) - 1;
|
|
|
|
/// Recast log categories.
|
|
/// @see rcContext
|
|
public enum rcLogCategory {
|
|
RC_LOG_PROGRESS = 1, //< A progress log entry.
|
|
RC_LOG_WARNING, //< A warning log entry.
|
|
RC_LOG_ERROR, //< An error log entry.
|
|
};
|
|
|
|
/// Recast performance timer categories.
|
|
/// @see rcContext
|
|
public enum rcTimerLabel {
|
|
/// The user defined total time of the build.
|
|
RC_TIMER_TOTAL,
|
|
/// A user defined build time.
|
|
RC_TIMER_TEMP,
|
|
/// The time to rasterize the triangles. (See: #rcRasterizeTriangle)
|
|
RC_TIMER_RASTERIZE_TRIANGLES,
|
|
/// The time to build the compact heightfield. (See: #rcBuildCompactHeightfield)
|
|
RC_TIMER_BUILD_COMPACTHEIGHTFIELD,
|
|
/// The total time to build the contours. (See: #rcBuildContours)
|
|
RC_TIMER_BUILD_CONTOURS,
|
|
/// The time to trace the boundaries of the contours. (See: #rcBuildContours)
|
|
RC_TIMER_BUILD_CONTOURS_TRACE,
|
|
/// The time to simplify the contours. (See: #rcBuildContours)
|
|
RC_TIMER_BUILD_CONTOURS_SIMPLIFY,
|
|
/// The time to filter ledge spans. (See: #rcFilterLedgeSpans)
|
|
RC_TIMER_FILTER_BORDER,
|
|
/// The time to filter low height spans. (See: #rcFilterWalkableLowHeightSpans)
|
|
RC_TIMER_FILTER_WALKABLE,
|
|
/// The time to apply the median filter. (See: #rcMedianFilterWalkableArea)
|
|
RC_TIMER_MEDIAN_AREA,
|
|
/// The time to filter low obstacles. (See: #rcFilterLowHangingWalkableObstacles)
|
|
RC_TIMER_FILTER_LOW_OBSTACLES,
|
|
/// The time to build the polygon mesh. (See: #rcBuildPolyMesh)
|
|
RC_TIMER_BUILD_POLYMESH,
|
|
/// The time to merge polygon meshes. (See: #rcMergePolyMeshes)
|
|
RC_TIMER_MERGE_POLYMESH,
|
|
/// The time to erode the walkable area. (See: #rcErodeWalkableArea)
|
|
RC_TIMER_ERODE_AREA,
|
|
/// The time to mark a box area. (See: #rcMarkBoxArea)
|
|
RC_TIMER_MARK_BOX_AREA,
|
|
/// The time to mark a cylinder area. (See: #rcMarkCylinderArea)
|
|
RC_TIMER_MARK_CYLINDER_AREA,
|
|
/// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea)
|
|
RC_TIMER_MARK_CONVEXPOLY_AREA,
|
|
/// The total time to build the distance field. (See: #rcBuildDistanceField)
|
|
RC_TIMER_BUILD_DISTANCEFIELD,
|
|
/// The time to build the distances of the distance field. (See: #rcBuildDistanceField)
|
|
RC_TIMER_BUILD_DISTANCEFIELD_DIST,
|
|
/// The time to blur the distance field. (See: #rcBuildDistanceField)
|
|
RC_TIMER_BUILD_DISTANCEFIELD_BLUR,
|
|
/// The total time to build the regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
|
|
RC_TIMER_BUILD_REGIONS,
|
|
/// The total time to apply the watershed algorithm. (See: #rcBuildRegions)
|
|
RC_TIMER_BUILD_REGIONS_WATERSHED,
|
|
/// The time to expand regions while applying the watershed algorithm. (See: #rcBuildRegions)
|
|
RC_TIMER_BUILD_REGIONS_EXPAND,
|
|
/// The time to flood regions while applying the watershed algorithm. (See: #rcBuildRegions)
|
|
RC_TIMER_BUILD_REGIONS_FLOOD,
|
|
/// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
|
|
RC_TIMER_BUILD_REGIONS_FILTER,
|
|
/// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers)
|
|
RC_TIMER_BUILD_LAYERS,
|
|
/// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail)
|
|
RC_TIMER_BUILD_POLYMESHDETAIL,
|
|
/// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails)
|
|
RC_TIMER_MERGE_POLYMESHDETAIL,
|
|
/// The maximum number of timers. (Used for iterating timers.)
|
|
RC_MAX_TIMERS
|
|
};
|
|
|
|
|
|
public static void rcCalcBounds(float[] verts, int nv, float[] bmin, float[] bmax) {
|
|
// Calculate bounding box.
|
|
rcVcopy(bmin, verts);
|
|
rcVcopy(bmax, verts);
|
|
for (int i = 1; i < nv; ++i) {
|
|
int vStart = i * 3;
|
|
rcVmin(bmin, 0, verts, vStart);
|
|
rcVmax(bmax, 0, verts, vStart);
|
|
}
|
|
}
|
|
|
|
public static void rcCalcGridSize(float[] bmin, float[] bmax, float cs, out int w, out int h) {
|
|
w = (int)((bmax[0] - bmin[0]) / cs + 0.5f);
|
|
h = (int)((bmax[2] - bmin[2]) / cs + 0.5f);
|
|
}
|
|
|
|
|
|
/// @par
|
|
///
|
|
/// See the #rcConfig documentation for more information on the configuration parameters.
|
|
///
|
|
/// @see rcAllocHeightfield, rcHeightfield
|
|
public static bool rcCreateHeightfield(rcContext ctx, rcHeightfield hf, int width, int height,
|
|
float[] bmin, float[] bmax,
|
|
float cs, float ch) {
|
|
rcIgnoreUnused(ctx);
|
|
|
|
hf.width = width;
|
|
hf.height = height;
|
|
rcVcopy(hf.bmin, bmin);
|
|
rcVcopy(hf.bmax, bmax);
|
|
hf.cs = cs;
|
|
hf.ch = ch;
|
|
hf.spans = new rcSpan[hf.width * hf.height];//(rcSpan**)rcAlloc(sizeof(rcSpan*)*hf.width*hf.height, RC_ALLOC_PERM);
|
|
if (hf.spans == null)
|
|
return false;
|
|
//memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height);
|
|
return true;
|
|
}
|
|
|
|
public static void calcTriNormal(float[] v0, float[] v1, float[] v2, float[] norm) {
|
|
float[] e0 = new float[3];
|
|
float[] e1 = new float[3];
|
|
rcVsub(e0, v1, v0);
|
|
rcVsub(e1, v2, v0);
|
|
rcVcross(norm, e0, e1);
|
|
rcVnormalize(norm);
|
|
}
|
|
|
|
public static void calcTriNormal(float[] v0, int v0Start, float[] v1, int v1Start, float[] v2, int v2Start, float[] norm) {
|
|
float[] e0 = new float[3];
|
|
float[] e1 = new float[3];
|
|
rcVsub(e0, 0, v1, v1Start, v0, v0Start);
|
|
rcVsub(e1, 0, v2, v2Start, v0, v0Start);
|
|
rcVcross(norm, 0, e0, 0, e1, 0);
|
|
rcVnormalize(norm);
|
|
}
|
|
|
|
/// @par
|
|
///
|
|
/// Only sets the aread id's for the walkable triangles. Does not alter the
|
|
/// area id's for unwalkable triangles.
|
|
///
|
|
/// See the #rcConfig documentation for more information on the configuration parameters.
|
|
///
|
|
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
|
|
public static void rcMarkWalkableTriangles(rcContext ctx, float walkableSlopeAngle,
|
|
float[] verts, int nv,
|
|
int[] tris, int nt,
|
|
byte[] areas) {
|
|
rcIgnoreUnused(ctx);
|
|
|
|
float walkableThr = (float)Math.Cos(walkableSlopeAngle / 180.0f * RC_PI);
|
|
|
|
float[] norm = new float[3];
|
|
|
|
for (int i = 0; i < nt; ++i) {
|
|
int triStart = i * 3;
|
|
calcTriNormal(verts, tris[triStart + 0] * 3, verts, tris[triStart + 1] * 3, verts, tris[triStart + 2] * 3, norm);
|
|
// Check if the face is walkable.
|
|
if (norm[1] > walkableThr)
|
|
areas[i] = RC_WALKABLE_AREA;
|
|
}
|
|
}
|
|
|
|
/// @par
|
|
///
|
|
/// Only sets the aread id's for the unwalkable triangles. Does not alter the
|
|
/// area id's for walkable triangles.
|
|
///
|
|
/// See the #rcConfig documentation for more information on the configuration parameters.
|
|
///
|
|
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
|
|
public static void rcClearUnwalkableTriangles(rcContext ctx, float walkableSlopeAngle,
|
|
float[] verts, int nv,
|
|
int[] tris, int nt,
|
|
byte[] areas) {
|
|
rcIgnoreUnused(ctx);
|
|
|
|
float walkableThr = (float)Math.Cos(walkableSlopeAngle / 180.0f * RC_PI);
|
|
|
|
float[] norm = new float[3];
|
|
|
|
for (int i = 0; i < nt; ++i) {
|
|
int triStart = i * 3;
|
|
calcTriNormal(verts, tris[triStart + 0] * 3, verts, tris[triStart + 1] * 3, verts, tris[triStart + 2] * 3, norm);
|
|
// Check if the face is walkable.
|
|
if (norm[1] <= walkableThr)
|
|
areas[i] = RC_NULL_AREA;
|
|
}
|
|
}
|
|
|
|
public static int rcGetHeightFieldSpanCount(rcContext ctx, rcHeightfield hf) {
|
|
rcIgnoreUnused(ctx);
|
|
|
|
int w = hf.width;
|
|
int h = hf.height;
|
|
int spanCount = 0;
|
|
for (int y = 0; y < h; ++y) {
|
|
for (int x = 0; x < w; ++x) {
|
|
for (rcSpan s = hf.spans[x + y * w]; s != null; s = s.next) {
|
|
if (s.area != RC_NULL_AREA)
|
|
spanCount++;
|
|
}
|
|
}
|
|
}
|
|
return spanCount;
|
|
}
|
|
|
|
public static void rccsArrayItemsCreate<T>(T[] array) where T : class, new() {
|
|
for (int i = 0; i < array.Length; ++i) {
|
|
array[i] = new T();
|
|
}
|
|
}
|
|
|
|
/// @par
|
|
///
|
|
/// This is just the beginning of the process of fully building a compact heightfield.
|
|
/// Various filters may be applied applied, then the distance field and regions built.
|
|
/// E.g: #rcBuildDistanceField and #rcBuildRegions
|
|
///
|
|
/// See the #rcConfig documentation for more information on the configuration parameters.
|
|
///
|
|
/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig
|
|
public static bool rcBuildCompactHeightfield(rcContext ctx, int walkableHeight, int walkableClimb,
|
|
rcHeightfield hf, rcCompactHeightfield chf) {
|
|
Debug.Assert(ctx != null, "rcBuildCompactHeightfield Assert(ctx != null)");
|
|
|
|
ctx.startTimer(rcTimerLabel.RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
|
|
|
|
int w = hf.width;
|
|
int h = hf.height;
|
|
int spanCount = rcGetHeightFieldSpanCount(ctx, hf);
|
|
|
|
// Fill in header.
|
|
chf.width = w;
|
|
chf.height = h;
|
|
chf.spanCount = spanCount;
|
|
chf.walkableHeight = walkableHeight;
|
|
chf.walkableClimb = walkableClimb;
|
|
chf.maxRegions = 0;
|
|
rcVcopy(chf.bmin, hf.bmin);
|
|
rcVcopy(chf.bmax, hf.bmax);
|
|
chf.bmax[1] += walkableHeight * hf.ch;
|
|
chf.cs = hf.cs;
|
|
chf.ch = hf.ch;
|
|
chf.cells = new rcCompactCell[w * h];
|
|
//chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM);
|
|
|
|
if (chf.cells == null) {
|
|
ctx.log(rcLogCategory.RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (" + (w * h) + ")");
|
|
return false;
|
|
}
|
|
chf.spans = new rcCompactSpan[spanCount];// (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM);
|
|
if (chf.spans == null) {
|
|
ctx.log(rcLogCategory.RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (" + spanCount + ")");
|
|
return false;
|
|
}
|
|
chf.areas = new byte[spanCount]; //(byte*)rcAlloc(sizeof(byte)*spanCount, RC_ALLOC_PERM);
|
|
if (chf.areas == null) {
|
|
ctx.log(rcLogCategory.RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (" + spanCount + ")"); ;
|
|
return false;
|
|
}
|
|
|
|
int MAX_HEIGHT = 0xffff;
|
|
|
|
// Fill in cells and spans.
|
|
int idx = 0;
|
|
for (int y = 0; y < h; ++y) {
|
|
for (int x = 0; x < w; ++x) {
|
|
rcSpan s = hf.spans[x + y * w];
|
|
// If there are no spans at this cell, just leave the data to index=0, count=0.
|
|
if (s == null) {
|
|
continue;
|
|
}
|
|
rcCompactCell c;// = chf.cells[x + y * w];
|
|
c.index = (uint)idx;
|
|
c.count = 0;
|
|
|
|
while (s != null) {
|
|
if (s.area != RC_NULL_AREA) {
|
|
int bot = (int)s.smax;
|
|
int top = s.next != null ? (int)s.next.smin : MAX_HEIGHT;
|
|
chf.spans[idx].y = (ushort)rcClamp(bot, 0, 0xffff);
|
|
chf.spans[idx].h = (byte)rcClamp(top - bot, 0, 0xff);
|
|
chf.areas[idx] = s.area;
|
|
idx++;
|
|
c.count++;
|
|
}
|
|
s = s.next;
|
|
}
|
|
chf.cells[x + y * w] = c;
|
|
}
|
|
}
|
|
|
|
// Find neighbour connections.
|
|
int MAX_LAYERS = RC_NOT_CONNECTED - 1;
|
|
int tooHighNeighbour = 0;
|
|
for (int y = 0; y < h; ++y) {
|
|
for (int x = 0; x < w; ++x) {
|
|
rcCompactCell c = chf.cells[x + y * w];
|
|
for (int i = (int)c.index, ni = (int)(c.index + c.count); i < ni; ++i) {
|
|
rcCompactSpan s = chf.spans[i];
|
|
|
|
for (int dir = 0; dir < 4; ++dir) {
|
|
rcSetCon(ref s, dir, RC_NOT_CONNECTED);
|
|
int nx = x + rcGetDirOffsetX(dir);
|
|
int ny = y + rcGetDirOffsetY(dir);
|
|
// First check that the neighbour cell is in bounds.
|
|
if (nx < 0 || ny < 0 || nx >= w || ny >= h)
|
|
continue;
|
|
|
|
// Iterate over all neighbour spans and check if any of the is
|
|
// accessible from current cell.
|
|
rcCompactCell nc = chf.cells[nx + ny * w];
|
|
for (int k = (int)nc.index, nk = (int)(nc.index + nc.count); k < nk; ++k) {
|
|
rcCompactSpan ns = chf.spans[k];
|
|
int bot = Math.Max(s.y, ns.y);
|
|
int top = Math.Min(s.y + s.h, ns.y + ns.h);
|
|
|
|
// Check that the gap between the spans is walkable,
|
|
// and that the climb height between the gaps is not too high.
|
|
if ((top - bot) >= walkableHeight && Math.Abs((int)ns.y - (int)s.y) <= walkableClimb) {
|
|
// Mark direction as walkable.
|
|
int lidx = k - (int)nc.index;
|
|
if (lidx < 0 || lidx > MAX_LAYERS) {
|
|
tooHighNeighbour = Math.Max(tooHighNeighbour, lidx);
|
|
continue;
|
|
}
|
|
rcSetCon(ref s, dir, lidx);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
chf.spans[i] = s;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tooHighNeighbour > MAX_LAYERS) {
|
|
ctx.log(rcLogCategory.RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers " + tooHighNeighbour + " (max: " + MAX_LAYERS + ")");
|
|
}
|
|
|
|
ctx.stopTimer(rcTimerLabel.RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
static int getHeightfieldMemoryUsage(const rcHeightfield& hf)
|
|
{
|
|
int size = 0;
|
|
size += sizeof(hf);
|
|
size += hf.width * hf.height * sizeof(rcSpan*);
|
|
|
|
rcSpanPool* pool = hf.pools;
|
|
while (pool)
|
|
{
|
|
size += (sizeof(rcSpanPool) - sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL;
|
|
pool = pool.next;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf)
|
|
{
|
|
int size = 0;
|
|
size += sizeof(rcCompactHeightfield);
|
|
size += sizeof(rcCompactSpan) * chf.spanCount;
|
|
size += sizeof(rcCompactCell) * chf.width * chf.height;
|
|
return size;
|
|
}
|
|
*/
|
|
|
|
/// @class rcContext
|
|
/// @par
|
|
///
|
|
/// This class does not provide logging or timer functionality on its
|
|
/// own. Both must be provided by a concrete implementation
|
|
/// by overriding the protected member functions. Also, this class does not
|
|
/// provide an interface for extracting log messages. (Only adding them.)
|
|
/// So concrete implementations must provide one.
|
|
///
|
|
/// If no logging or timers are required, just pass an instance of this
|
|
/// class through the Recast build process.
|
|
///
|
|
|
|
/// @par
|
|
///
|
|
/// Example:
|
|
/// @code
|
|
/// // Where ctx is an instance of rcContext and filepath is a char array.
|
|
/// ctx.log(rcLogCategory.RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath);
|
|
/// @endcode
|
|
/// Provides an interface for optional logging and performance tracking of the Recast
|
|
/// build process.
|
|
/// @ingroup recast
|
|
public class rcContext {
|
|
|
|
/// True if logging is enabled.
|
|
bool m_logEnabled = true;
|
|
|
|
/// True if the performance timers are enabled.
|
|
bool m_timerEnabled = true;
|
|
|
|
/// Contructor.
|
|
/// @param[in] state TRUE if the logging and performance timers should be enabled. [Default: true]
|
|
public rcContext(bool state = true) {
|
|
m_logEnabled = state;
|
|
m_timerEnabled = state;
|
|
}
|
|
|
|
/// Enables or disables logging.
|
|
/// @param[in] state TRUE if logging should be enabled.
|
|
public void enableLog(bool state) {
|
|
m_logEnabled = state;
|
|
}
|
|
|
|
/// Clears all log entries.
|
|
public void resetLog() {
|
|
if (m_logEnabled) {
|
|
doResetLog();
|
|
}
|
|
}
|
|
|
|
/// Logs a message.
|
|
/// @param[in] category The category of the message.
|
|
/// @param[in] message The message.
|
|
//public void log(rcLogCategory category, string message);
|
|
public void log(rcLogCategory category, string message) {
|
|
if (!m_logEnabled) {
|
|
return;
|
|
}
|
|
|
|
doLog(category, message);
|
|
}
|
|
|
|
/// Enables or disables the performance timers.
|
|
/// @param[in] state TRUE if timers should be enabled.
|
|
public void enableTimer(bool state) {
|
|
m_timerEnabled = state;
|
|
}
|
|
|
|
/// Clears all peformance timers. (Resets all to unused.)
|
|
public void resetTimers() {
|
|
if (m_timerEnabled) {
|
|
doResetTimers();
|
|
}
|
|
}
|
|
|
|
/// Starts the specified performance timer.
|
|
/// @param label The category of timer.
|
|
public void startTimer(rcTimerLabel label) {
|
|
if (m_timerEnabled) {
|
|
doStartTimer(label);
|
|
}
|
|
}
|
|
|
|
/// Stops the specified performance timer.
|
|
/// @param label The category of the timer.
|
|
public void stopTimer(rcTimerLabel label) {
|
|
if (m_timerEnabled) {
|
|
doStopTimer(label);
|
|
}
|
|
}
|
|
|
|
/// Returns the total accumulated time of the specified performance timer.
|
|
/// @param label The category of the timer.
|
|
/// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
|
public long getAccumulatedTime(rcTimerLabel label) {
|
|
return m_timerEnabled ? doGetAccumulatedTime(label) : -1;
|
|
}
|
|
public double getAccumulatedTimeHiResolution(rcTimerLabel label) {
|
|
return m_timerEnabled ? doGetAccumulatedTimeHiResolution(label) : -1.0;
|
|
}
|
|
|
|
|
|
/// Clears all log entries.
|
|
protected virtual void doResetLog() { }
|
|
|
|
/// Logs a message.
|
|
/// @param[in] category The category of the message.
|
|
/// @param[in] msg The formatted message.
|
|
protected virtual void doLog(rcLogCategory category, string msg) { //int len unnecessary because c# string
|
|
}
|
|
|
|
/// Clears all timers. (Resets all to unused.)
|
|
protected virtual void doResetTimers() {
|
|
}
|
|
|
|
/// Starts the specified performance timer.
|
|
/// @param[in] label The category of timer.
|
|
protected virtual void doStartTimer(rcTimerLabel label) {
|
|
}
|
|
|
|
/// Stops the specified performance timer.
|
|
/// @param[in] label The category of the timer.
|
|
protected virtual void doStopTimer(rcTimerLabel label) {
|
|
}
|
|
|
|
/// Returns the total accumulated time of the specified performance timer.
|
|
/// @param[in] label The category of the timer.
|
|
/// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
|
protected virtual long doGetAccumulatedTime(rcTimerLabel label) {
|
|
return -1;
|
|
}
|
|
|
|
//C# port: alternate return type to use high precision timer on platforms where it's available
|
|
/// Returns the total accumulated time of the specified performance timer.
|
|
/// @param[in] label The category of the timer.
|
|
/// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
|
protected virtual double doGetAccumulatedTimeHiResolution(rcTimerLabel label) {
|
|
return -1.0;
|
|
}
|
|
|
|
};
|
|
|
|
/// Specifies a configuration to use when performing Recast builds.
|
|
/// @ingroup recast
|
|
public class rcConfig {
|
|
/// The width of the field along the x-axis. [Limit: >= 0] [Units: vx]
|
|
public int width;
|
|
|
|
/// The height of the field along the z-axis. [Limit: >= 0] [Units: vx]
|
|
public int height;
|
|
|
|
/// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx]
|
|
public int tileSize;
|
|
|
|
/// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx]
|
|
public int borderSize;
|
|
|
|
/// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu]
|
|
public float cs;
|
|
|
|
/// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu]
|
|
public float ch;
|
|
|
|
/// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
|
public float[] bmin = new float[3];
|
|
|
|
/// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
|
public float[] bmax = new float[3];
|
|
|
|
/// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees]
|
|
public float walkableSlopeAngle;
|
|
|
|
/// Minimum floor to 'ceiling' height that will still allow the floor area to
|
|
/// be considered walkable. [Limit: >= 3] [Units: vx]
|
|
public int walkableHeight;
|
|
|
|
/// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx]
|
|
public int walkableClimb;
|
|
|
|
/// The distance to erode/shrink the walkable area of the heightfield away from
|
|
/// obstructions. [Limit: >=0] [Units: vx]
|
|
public int walkableRadius;
|
|
|
|
/// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx]
|
|
public int maxEdgeLen;
|
|
|
|
/// The maximum distance a simplfied contour's border edges should deviate
|
|
/// the original raw contour. [Limit: >=0] [Units: vx]
|
|
public float maxSimplificationError;
|
|
|
|
/// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx]
|
|
public int minRegionArea;
|
|
|
|
/// Any regions with a span count smaller than this value will, if possible,
|
|
/// be merged with larger regions. [Limit: >=0] [Units: vx]
|
|
public int mergeRegionArea;
|
|
|
|
/// The maximum number of vertices allowed for polygons generated during the
|
|
/// contour to polygon conversion process. [Limit: >= 3]
|
|
public int maxVertsPerPoly;
|
|
|
|
/// Sets the sampling distance to use when generating the detail mesh.
|
|
/// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu]
|
|
public float detailSampleDist;
|
|
|
|
/// The maximum distance the detail mesh surface should deviate from heightfield
|
|
/// data. (For height detail only.) [Limit: >=0] [Units: wu]
|
|
public float detailSampleMaxError;
|
|
};
|
|
|
|
|
|
|
|
/// Represents a span in a heightfield.
|
|
/// @see rcHeightfield
|
|
public class rcSpan {
|
|
public ushort smin;// : 13; //< The lower limit of the span. [Limit: < #smax]
|
|
public ushort smax;// : 13; //< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]
|
|
public byte area;// : 6; //< The area id assigned to the span.
|
|
public rcSpan next = null; //< The next span higher up in column.
|
|
}
|
|
// A memory pool used for quick allocation of spans within a heightfield.
|
|
// @see rcHeightfield
|
|
|
|
public class rcSpanPool {
|
|
public rcSpanPool next = null; //< The next span pool.
|
|
public rcSpan[] items = new rcSpan[RC_SPANS_PER_POOL]; //< Array of spans in the pool.
|
|
///
|
|
public rcSpanPool() {
|
|
for (int i = 0; i < items.Length; ++i) {
|
|
items[i] = new rcSpan();
|
|
}
|
|
}
|
|
};
|
|
|
|
/// A dynamic heightfield representing obstructed space.
|
|
/// @ingroup recast
|
|
public class rcHeightfield {
|
|
public int width; //< The width of the heightfield. (Along the x-axis in cell units.)
|
|
public int height; //< The height of the heightfield. (Along the z-axis in cell units.)
|
|
public float[] bmin = new float[3]; //< The minimum bounds in world space. [(x, y, z)]
|
|
public float[] bmax = new float[3]; //< The maximum bounds in world space. [(x, y, z)]
|
|
public float cs; //< The size of each cell. (On the xz-plane.)
|
|
public float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
|
public rcSpan[] spans = null;//** //< Heightfield of spans (width*height).
|
|
public rcSpanPool pools = null; //< Linked list of span pools.
|
|
public rcSpan freelist = null; //< The next free span.
|
|
};
|
|
|
|
/// Provides information on the content of a cell column in a compact heightfield.
|
|
public struct rcCompactCell {
|
|
public uint index;// : 24; //< Index to the first span in the column.
|
|
public ushort count;// : 8; //< Number of spans in the column.
|
|
};
|
|
|
|
/// Represents a span of unobstructed space within a compact heightfield.
|
|
public struct rcCompactSpan {
|
|
public ushort y; //< The lower extent of the span. (Measured from the heightfield's base.)
|
|
public ushort reg; //< The id of the region the span belongs to. (Or zero if not in a region.)
|
|
public uint con;// : 24; //< Packed neighbor connection data.
|
|
public ushort h;// : 8; //< The height of the span. (Measured from #y.)
|
|
};
|
|
|
|
/// A compact, static heightfield representing unobstructed space.
|
|
/// @ingroup recast
|
|
public class rcCompactHeightfield {
|
|
public int width; //< The width of the heightfield. (Along the x-axis in cell units.)
|
|
public int height; //< The height of the heightfield. (Along the z-axis in cell units.)
|
|
public int spanCount; //< The number of spans in the heightfield.
|
|
public int walkableHeight; //< The walkable height used during the build of the field. (See: rcConfig::walkableHeight)
|
|
public int walkableClimb; //< The walkable climb used during the build of the field. (See: rcConfig::walkableClimb)
|
|
public int borderSize; //< The AABB border size used during the build of the field. (See: rcConfig::borderSize)
|
|
public ushort maxDistance; //< The maximum distance value of any span within the field.
|
|
public ushort maxRegions; //< The maximum region id of any span within the field.
|
|
public float[] bmin = new float[3]; //< The minimum bounds in world space. [(x, y, z)]
|
|
public float[] bmax = new float[3]; //< The maximum bounds in world space. [(x, y, z)]
|
|
public float cs; //< The size of each cell. (On the xz-plane.)
|
|
public float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
|
public rcCompactCell[] cells = null; //< Array of cells. [Size: #width*#height]
|
|
public rcCompactSpan[] spans = null; //< Array of spans. [Size: #spanCount]
|
|
public ushort[] dist = null; //< Array containing border distance data. [Size: #spanCount]
|
|
public byte[] areas = null; //< Array containing area id data. [Size: #spanCount]
|
|
};
|
|
|
|
/// Represents a heightfield layer within a layer set.
|
|
/// @see rcHeightfieldLayerSet
|
|
public class rcHeightfieldLayer {
|
|
public float[] bmin = new float[3]; //< The minimum bounds in world space. [(x, y, z)]
|
|
public float[] bmax = new float[3]; //< The maximum bounds in world space. [(x, y, z)]
|
|
public float cs; //< The size of each cell. (On the xz-plane.)
|
|
public float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
|
public int width; //< The width of the heightfield. (Along the x-axis in cell units.)
|
|
public int height; //< The height of the heightfield. (Along the z-axis in cell units.)
|
|
public int minx; //< The minimum x-bounds of usable data.
|
|
public int maxx; //< The maximum x-bounds of usable data.
|
|
public int miny; //< The minimum y-bounds of usable data. (Along the z-axis.)
|
|
public int maxy; //< The maximum y-bounds of usable data. (Along the z-axis.)
|
|
public int hmin; //< The minimum height bounds of usable data. (Along the y-axis.)
|
|
public int hmax; //< The maximum height bounds of usable data. (Along the y-axis.)
|
|
public byte[] heights; //< The heightfield. [Size: (width - borderSize*2) * (h - borderSize*2)]
|
|
public byte[] areas; //< Area ids. [Size: Same as #heights]
|
|
public byte[] cons; //< Packed neighbor connection information. [Size: Same as #heights]
|
|
};
|
|
|
|
/// Represents a set of heightfield layers.
|
|
/// @ingroup recast
|
|
/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet
|
|
public class rcHeightfieldLayerSet {
|
|
public rcHeightfieldLayer[] layers = null; //< The layers in the set. [Size: #nlayers]
|
|
public int nlayers; //< The number of layers in the set.
|
|
};
|
|
|
|
/// Represents a simple, non-overlapping contour in field space.
|
|
public struct rcContour {
|
|
public int[] verts; //< Simplified contour vertex and connection data. [Size: 4 * #nverts]
|
|
public int nverts; //< The number of vertices in the simplified contour.
|
|
public int[] rverts; //< Raw contour vertex and connection data. [Size: 4 * #nrverts]
|
|
public int nrverts; //< The number of vertices in the raw contour.
|
|
public ushort reg; //< The region id of the contour.
|
|
public byte area; //< The area id of the contour.
|
|
///
|
|
public void dumpToTxt(StreamWriter stream) {
|
|
stream.WriteLine("\treg: " + reg);
|
|
stream.WriteLine("\tarea: " + area);
|
|
stream.WriteLine("\tnverts: " + nverts);
|
|
for (int i = 0; i < nverts; ++i) {
|
|
int vIndex = i * 4;
|
|
stream.WriteLine("\t\tverts[" + i + "]: x:" + verts[vIndex] + " y:" + verts[vIndex + 1] + " z:" + verts[vIndex + 2] + " ?:" + verts[vIndex + 3]);
|
|
}
|
|
stream.WriteLine("\tnrverts: " + nrverts);
|
|
for (int i = 0; i < nrverts; ++i) {
|
|
int vIndex = i * 4;
|
|
stream.WriteLine("\t\trverts[" + i + "]: x:" + rverts[vIndex] + " y:" + rverts[vIndex + 1] + " z:" + rverts[vIndex + 2] + " ?:" + rverts[vIndex + 3]);
|
|
}
|
|
}
|
|
public string dumpToString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine("\treg: " + reg);
|
|
sb.AppendLine("\tarea: " + area);
|
|
sb.AppendLine("\tnverts: " + nverts);
|
|
for (int i = 0; i < nverts; ++i) {
|
|
int vIndex = i * 4;
|
|
sb.AppendLine("\t\tverts[" + i + "]: x:" + verts[vIndex] + " y:" + verts[vIndex + 1] + " z:" + verts[vIndex + 2] + " ?:" + verts[vIndex + 3]);
|
|
}
|
|
sb.AppendLine("\tnrverts: " + nrverts);
|
|
for (int i = 0; i < nrverts; ++i) {
|
|
int vIndex = i * 4;
|
|
sb.AppendLine("\t\trverts[" + i + "]: x:" + rverts[vIndex] + " y:" + rverts[vIndex + 1] + " z:" + rverts[vIndex + 2] + " ?:" + rverts[vIndex + 3]);
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
};
|
|
|
|
/// Represents a group of related contours.
|
|
/// @ingroup recast
|
|
public class rcContourSet {
|
|
public rcContour[] conts = null; //< An array of the contours in the set. [Size: #nconts]
|
|
public int nconts; //< The number of contours in the set.
|
|
public float[] bmin = new float[3]; //< The minimum bounds in world space. [(x, y, z)]
|
|
public float[] bmax = new float[3]; //< The maximum bounds in world space. [(x, y, z)]
|
|
public float cs; //< The size of each cell. (On the xz-plane.)
|
|
public float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
|
public int width; //< The width of the set. (Along the x-axis in cell units.)
|
|
public int height; //< The height of the set. (Along the z-axis in cell units.)
|
|
public int borderSize; //< The AABB border size used to generate the source data from which the contours were derived.
|
|
///
|
|
public override string ToString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.AppendLine("nconts: " + nconts);
|
|
sb.AppendLine("bmin: " + bmin[0] + " " + bmin[1] + " " + bmin[2]);
|
|
sb.AppendLine("bmax: " + bmax[0] + " " + bmax[1] + " " + bmax[2]);
|
|
sb.AppendLine("cs: " + cs);
|
|
sb.AppendLine("ch: " + ch);
|
|
sb.AppendLine("width: " + width);
|
|
sb.AppendLine("height: " + height);
|
|
sb.AppendLine("bordersize: " + borderSize);
|
|
|
|
for (int i = 0; i < nconts; ++i) {
|
|
sb.Append("contour[" + i + "]: ");
|
|
sb.AppendLine(conts[i].ToString());
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
};
|
|
|
|
/// Represents a polygon mesh suitable for use in building a navigation mesh.
|
|
/// @ingroup recast
|
|
public class rcPolyMesh {
|
|
public ushort[] verts = null; //< The mesh vertices. [Form: (x, y, z) * #nverts]
|
|
public ushort[] polys = null; //< Polygon and neighbor data. [Length: #maxpolys * 2 * #nvp]
|
|
public ushort[] regs = null; //< The region id assigned to each polygon. [Length: #maxpolys]
|
|
public ushort[] flags = null; //< The user defined flags for each polygon. [Length: #maxpolys]
|
|
public byte[] areas = null; //< The area id assigned to each polygon. [Length: #maxpolys]
|
|
public int nverts; //< The number of vertices.
|
|
public int npolys; //< The number of polygons.
|
|
public int maxpolys; //< The number of allocated polygons.
|
|
public int nvp; //< The maximum number of vertices per polygon.
|
|
public float[] bmin = new float[3]; //< The minimum bounds in world space. [(x, y, z)]
|
|
public float[] bmax = new float[3]; //< The maximum bounds in world space. [(x, y, z)]
|
|
public float cs; //< The size of each cell. (On the xz-plane.)
|
|
public float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
|
public int borderSize; //< The AABB border size used to generate the source data from which the mesh was derived.
|
|
///
|
|
public override string ToString() {
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.AppendLine("bmin: " + bmin[0] + " " + bmin[1] + " " + bmin[2]);
|
|
sb.AppendLine("bmax: " + bmax[0] + " " + bmax[1] + " " + bmax[2]);
|
|
sb.AppendLine("cs: " + cs);
|
|
sb.AppendLine("ch: " + ch);
|
|
sb.AppendLine("bordersize: " + borderSize);
|
|
|
|
sb.AppendLine("nverts: " + nverts);
|
|
for (int i = 0; i < nverts; ++i) {
|
|
int vIndex = i * 3;
|
|
sb.AppendLine("\tverts[" + i + "]: x:" + verts[vIndex] + " y:" + verts[vIndex + 1] + " z:" + verts[vIndex + 2]);
|
|
}
|
|
sb.AppendLine("\tmaxpolys: " + maxpolys);
|
|
sb.AppendLine("\tnvp: " + nvp);
|
|
sb.AppendLine("\tnpolys: " + npolys);
|
|
for (int i = 0; i < maxpolys; ++i) {
|
|
int vIndex = i * nvp;
|
|
sb.Append("\t\tpolys[" + i + "]: ");
|
|
for (int j = 0; j < nvp; ++j) {
|
|
sb.Append(" " + j + ":" + polys[vIndex + j]);
|
|
}
|
|
|
|
vIndex += nvp;
|
|
sb.AppendLine();
|
|
sb.Append("\t\tneighbor[" + i + "]: ");
|
|
for (int j = 0; j < nvp; ++j) {
|
|
sb.Append(" " + j + ":" + polys[vIndex + j]);
|
|
}
|
|
sb.AppendLine();
|
|
}
|
|
|
|
for (int i = 0; i < maxpolys; ++i) {
|
|
sb.AppendLine("regs[" + i + "]: " + regs[i]);
|
|
}
|
|
sb.AppendLine();
|
|
for (int i = 0; i < flags.Length; ++i) {
|
|
sb.AppendLine("flags[" + i + "]: " + flags[i]);
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public string ToObj(){
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.AppendLine("# Recast Navmesh");
|
|
sb.AppendLine("o NavMesh");
|
|
|
|
sb.AppendLine();
|
|
|
|
for (int i = 0; i < nverts; ++i) {
|
|
//ushort* v = &pmesh.verts[i*3];
|
|
int vIndex = i * 3;
|
|
float x = bmin[0] + verts[vIndex + 0] * cs;
|
|
float y = bmin[1] + (verts[vIndex + 1] + 1) * ch + 0.1f;
|
|
float z = bmin[2] + verts[vIndex + 2] * cs;
|
|
//ioprintf(io, "v %f %f %f\n", x,y,z);
|
|
sb.AppendLine("v " + x + " " + y + " " + z);
|
|
}
|
|
|
|
sb.AppendLine();
|
|
|
|
for (int i = 0; i < npolys; ++i) {
|
|
//const unsigned short* p = &pmesh.polys[i*nvp*2];
|
|
int pIndex = i * nvp * 2;
|
|
for (int j = 2; j < nvp; ++j) {
|
|
if (polys[pIndex + j] == RC_MESH_NULL_IDX)
|
|
break;
|
|
//ioprintf(io, "f %d %d %d\n", p[0]+1, p[j-1]+1, p[j]+1);
|
|
int a = polys[pIndex] + 1;
|
|
int b = polys[pIndex + j - 1] + 1;
|
|
int c = polys[pIndex + j] + 1;
|
|
sb.AppendLine("f " + a + " " + b + " " + c);
|
|
}
|
|
}
|
|
return sb.ToString ();
|
|
}
|
|
};
|
|
|
|
/// Contains triangle meshes that represent detailed height data associated
|
|
/// with the polygons in its associated polygon mesh object.
|
|
/// @ingroup recast
|
|
public class rcPolyMeshDetail {
|
|
public uint[] meshes = null; //< The sub-mesh data. [Size: 4*#nmeshes]
|
|
public float[] verts = null; //< The mesh vertices. [Size: 3*#nverts]
|
|
public byte[] tris = null; //< The mesh triangles. [Size: 4*#ntris]
|
|
public int nmeshes; //< The number of sub-meshes defined by #meshes.
|
|
public int nverts; //< The number of vertices in #verts.
|
|
public int ntris; //< The number of triangles in #tris.
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.AppendLine("nmeshes: " + nmeshes);
|
|
for (int i = 0; i < nmeshes; ++i) {
|
|
int vIndex = i * 4;
|
|
sb.AppendLine("\tmeshes[" + i + "]: a:" + meshes[vIndex] + " b:" + meshes[vIndex + 1] + " c:" + meshes[vIndex + 2] + " d:" + meshes[vIndex + 3]);
|
|
}
|
|
sb.AppendLine("nverts: " + nverts);
|
|
for (int i = 0; i < nverts; ++i) {
|
|
int vIndex = i * 3;
|
|
sb.AppendLine("\tverts[" + i + "]: x:" + verts[vIndex] + " y:" + verts[vIndex + 1] + " z:" + verts[vIndex + 2]);
|
|
}
|
|
sb.AppendLine("ntris: " + ntris);
|
|
for (int i = 0; i < ntris; ++i) {
|
|
int vIndex = i * 4;
|
|
sb.AppendLine("\ttris[" + i + "]: a:" + tris[vIndex] + " b:" + tris[vIndex + 1] + " c:" + tris[vIndex + 2] + " d:" + tris[vIndex + 3]);
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public string ToObj()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.AppendLine("# Recast C# Navmesh\n");
|
|
sb.AppendLine("o NavMesh\n");
|
|
|
|
sb.AppendLine("\n");
|
|
|
|
for (int i = 0; i < nverts; ++i) {
|
|
int vIndex = i * 3;
|
|
sb.AppendLine("v " + verts[vIndex + 0] + " " + verts[vIndex + 1] + " " + verts[vIndex + 2]);
|
|
}
|
|
|
|
sb.AppendLine();
|
|
|
|
for (int i = 0; i < nmeshes; ++i) {
|
|
//uint* m = &dmesh.meshes[i*4];
|
|
int mIndex = i * 4;
|
|
uint bverts = meshes[mIndex + 0];
|
|
uint btris = meshes[mIndex + 2];
|
|
uint _ntris = meshes[mIndex + 3];
|
|
uint trisIndex = btris * 4;
|
|
for (uint j = 0; j < _ntris; ++j) {
|
|
sb.AppendLine("f "
|
|
+ ((int)(bverts + tris[trisIndex + j * 4 + 0]) + 1) + " "
|
|
+ ((int)(bverts + tris[trisIndex + j * 4 + 1]) + 1) + " "
|
|
+ ((int)(bverts + tris[trisIndex + j * 4 + 2]) + 1) + " ");
|
|
}
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
};
|
|
|
|
/// @name Allocation Functions
|
|
/// Functions used to allocate and de-allocate Recast objects.
|
|
/// @see rcAllocSetCustom
|
|
/// @{
|
|
|
|
/// Allocates a heightfield object using the Recast allocator.
|
|
/// @return A heightfield that is ready for initialization, or null on failure.
|
|
/// @ingroup recast
|
|
/// @see rcCreateHeightfield, rcFreeHeightField
|
|
//rcHeightfield* rcAllocHeightfield();
|
|
|
|
/// Frees the specified heightfield object using the Recast allocator.
|
|
/// @param[in] hf A heightfield allocated using #rcAllocHeightfield
|
|
/// @ingroup recast
|
|
/// @see rcAllocHeightfield
|
|
//void rcFreeHeightField(rcHeightfield* hf);
|
|
|
|
/// Allocates a compact heightfield object using the Recast allocator.
|
|
/// @return A compact heightfield that is ready for initialization, or null on failure.
|
|
/// @ingroup recast
|
|
/// @see rcBuildCompactHeightfield, rcFreeCompactHeightfield
|
|
//rcCompactHeightfield* rcAllocCompactHeightfield();
|
|
|
|
/// Frees the specified compact heightfield object using the Recast allocator.
|
|
/// @param[in] chf A compact heightfield allocated using #rcAllocCompactHeightfield
|
|
/// @ingroup recast
|
|
/// @see rcAllocCompactHeightfield
|
|
//void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
|
|
|
|
/// Allocates a heightfield layer set using the Recast allocator.
|
|
/// @return A heightfield layer set that is ready for initialization, or null on failure.
|
|
/// @ingroup recast
|
|
/// @see rcBuildHeightfieldLayers, rcFreeHeightfieldLayerSet
|
|
//rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet();
|
|
|
|
/// Frees the specified heightfield layer set using the Recast allocator.
|
|
/// @param[in] lset A heightfield layer set allocated using #rcAllocHeightfieldLayerSet
|
|
/// @ingroup recast
|
|
/// @see rcAllocHeightfieldLayerSet
|
|
//void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset);
|
|
|
|
/// Allocates a contour set object using the Recast allocator.
|
|
/// @return A contour set that is ready for initialization, or null on failure.
|
|
/// @ingroup recast
|
|
/// @see rcBuildContours, rcFreeContourSet
|
|
//rcContourSet* rcAllocContourSet();
|
|
|
|
/// Frees the specified contour set using the Recast allocator.
|
|
/// @param[in] cset A contour set allocated using #rcAllocContourSet
|
|
/// @ingroup recast
|
|
/// @see rcAllocContourSet
|
|
//void rcFreeContourSet(rcContourSet* cset);
|
|
|
|
/// Allocates a polygon mesh object using the Recast allocator.
|
|
/// @return A polygon mesh that is ready for initialization, or null on failure.
|
|
/// @ingroup recast
|
|
/// @see rcBuildPolyMesh, rcFreePolyMesh
|
|
//rcPolyMesh* rcAllocPolyMesh();
|
|
|
|
/// Frees the specified polygon mesh using the Recast allocator.
|
|
/// @param[in] pmesh A polygon mesh allocated using #rcAllocPolyMesh
|
|
/// @ingroup recast
|
|
/// @see rcAllocPolyMesh
|
|
//void rcFreePolyMesh(rcPolyMesh* pmesh);
|
|
|
|
/// Allocates a detail mesh object using the Recast allocator.
|
|
/// @return A detail mesh that is ready for initialization, or null on failure.
|
|
/// @ingroup recast
|
|
/// @see rcBuildPolyMeshDetail, rcFreePolyMeshDetail
|
|
//rcPolyMeshDetail* rcAllocPolyMeshDetail();
|
|
|
|
/// Frees the specified detail mesh using the Recast allocator.
|
|
/// @param[in] dmesh A detail mesh allocated using #rcAllocPolyMeshDetail
|
|
/// @ingroup recast
|
|
/// @see rcAllocPolyMeshDetail
|
|
//void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh);
|
|
|
|
/// The number of spans allocated per span spool.
|
|
/// @see rcSpanPool
|
|
public const int RC_SPANS_PER_POOL = 2048;
|
|
|
|
/// Heighfield border flag.
|
|
/// If a heightfield region ID has this bit set, then the region is a border
|
|
/// region and its spans are considered unwalkable.
|
|
/// (Used during the region and contour build process.)
|
|
/// @see rcCompactSpan::reg
|
|
|
|
public const ushort RC_BORDER_REG = 0x8000;
|
|
|
|
/// Border vertex flag.
|
|
/// If a region ID has this bit set, then the associated element lies on
|
|
/// a tile border. If a contour vertex's region ID has this bit set, the
|
|
/// vertex will later be removed in order to match the segments and vertices
|
|
/// at tile boundaries.
|
|
/// (Used during the build process.)
|
|
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
|
public const int RC_BORDER_VERTEX = 0x10000;
|
|
|
|
/// Area border flag.
|
|
/// If a region ID has this bit set, then the associated element lies on
|
|
/// the border of an area.
|
|
/// (Used during the region and contour build process.)
|
|
/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
|
public const int RC_AREA_BORDER = 0x20000;
|
|
|
|
/// Contour build flags.
|
|
/// @see rcBuildContours
|
|
public enum rcBuildContoursFlags {
|
|
RC_CONTOUR_TESS_WALL_EDGES = 0x01, //< Tessellate solid (impassable) edges during contour simplification.
|
|
RC_CONTOUR_TESS_AREA_EDGES = 0x02, //< Tessellate edges between areas during contour simplification.
|
|
};
|
|
|
|
/// Applied to the region id field of contour vertices in order to extract the region id.
|
|
/// The region id field of a vertex may have several flags applied to it. So the
|
|
/// fields value can't be used directly.
|
|
/// @see rcContour::verts, rcContour::rverts
|
|
public const int RC_CONTOUR_REG_MASK = 0xffff;
|
|
|
|
/// An value which indicates an invalid index within a mesh.
|
|
/// @note This does not necessarily indicate an error.
|
|
/// @see rcPolyMesh::polys
|
|
public const ushort RC_MESH_NULL_IDX = 0xffff;
|
|
|
|
/// Represents the null area.
|
|
/// When a data element is given this value it is considered to no longer be
|
|
/// assigned to a usable area. (E.g. It is unwalkable.)
|
|
public const byte RC_NULL_AREA = 0;
|
|
|
|
/// The default area id used to indicate a walkable polygon.
|
|
/// This is also the maximum allowed area id, and the only non-null area id
|
|
/// recognized by some steps in the build process.
|
|
public const byte RC_WALKABLE_AREA = 63;
|
|
|
|
/// The value returned by #rcGetCon if the specified direction is not connected
|
|
/// to another span. (Has no neighbor.)
|
|
public const int RC_NOT_CONNECTED = 0x3f;
|
|
|
|
/// @name General helper functions
|
|
/// @{
|
|
|
|
/// Used to ignore a function parameter. VS complains about unused parameters
|
|
/// and this silences the warning.
|
|
/// @param [in] _ Unused parameter
|
|
public static void rcIgnoreUnused<T>(T t) { }
|
|
|
|
//Use C# for this kind of things
|
|
/// Swaps the values of the two parameters.
|
|
/// @param[in,out] a Value A
|
|
/// @param[in,out] b Value B
|
|
//public void rcSwap<T>(T a, T b) { T t = a; a = b; b = t; }
|
|
static void rcSwap<T>(ref T lhs, ref T rhs) {
|
|
T temp = lhs;
|
|
lhs = rhs;
|
|
rhs = temp;
|
|
}
|
|
|
|
/// Returns the minimum of two values.
|
|
/// @param[in] a Value A
|
|
/// @param[in] b Value B
|
|
/// @return The minimum of the two values.
|
|
//public T Math.Min<T>(T a, T b) {
|
|
// return a < b ? a : b;
|
|
//}
|
|
|
|
/// Returns the maximum of two values.
|
|
/// @param[in] a Value A
|
|
/// @param[in] b Value B
|
|
/// @return The maximum of the two values.
|
|
//template<class T> inline T Math.Max(T a, T b) { return a > b ? a : b; }
|
|
|
|
/// Returns the absolute value.
|
|
/// @param[in] a The value.
|
|
/// @return The absolute value of the specified value.
|
|
//template<class T> inline T rcAbs(T a) { return a < 0 ? -a : a; }
|
|
|
|
/// Returns the square of the value.
|
|
/// @param[in] a The value.
|
|
/// @return The square of the value.
|
|
//template<class T> inline T rcSqr(T a) { return a*a; }
|
|
|
|
/// Clamps the value to the specified range.
|
|
/// @param[in] v The value to clamp.
|
|
/// @param[in] mn The minimum permitted return value.
|
|
/// @param[in] mx The maximum permitted return value.
|
|
/// @return The value, clamped to the specified range.
|
|
//template<class T> inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
|
|
public static int rcClamp(int v, int mn, int mx) {
|
|
return v < mn ? mn : (v > mx ? mx : v);
|
|
}
|
|
|
|
/// Returns the square root of the value.
|
|
/// @param[in] x The value.
|
|
/// @return The square root of the vlaue.
|
|
//float rcSqrt(float x);
|
|
|
|
/// @}
|
|
/// @name Vector helper functions.
|
|
/// @{
|
|
|
|
/// Derives the cross product of two vectors. (@p v1 x @p v2)
|
|
/// @param[out] dest The cross product. [(x, y, z)]
|
|
/// @param[in] v1 A Vector [(x, y, z)]
|
|
/// @param[in] v2 A vector [(x, y, z)]
|
|
|
|
public static void rcVcross(float[] dest, float[] v1, float[] v2) {
|
|
dest[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
|
dest[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
|
dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
|
}
|
|
public static void rcVcross(float[] dest, int destStart, float[] v1, int v1Start, float[] v2, int v2Start) {
|
|
dest[destStart + 0] = v1[v1Start + 1] * v2[v2Start + 2] - v1[v1Start + 2] * v2[v2Start + 1];
|
|
dest[destStart + 1] = v1[v1Start + 2] * v2[v2Start + 0] - v1[v1Start + 0] * v2[v2Start + 2];
|
|
dest[destStart + 2] = v1[v1Start + 0] * v2[v2Start + 1] - v1[v1Start + 1] * v2[v2Start + 0];
|
|
}
|
|
|
|
/// Derives the dot product of two vectors. (@p v1 . @p v2)
|
|
/// @param[in] v1 A Vector [(x, y, z)]
|
|
/// @param[in] v2 A vector [(x, y, z)]
|
|
/// @return The dot product.
|
|
public static float rcVdot(float[] v1, float[] v2) {
|
|
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
|
}
|
|
|
|
/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s))
|
|
/// @param[out] dest The result vector. [(x, y, z)]
|
|
/// @param[in] v1 The base vector. [(x, y, z)]
|
|
/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)]
|
|
/// @param[in] s The amount to scale @p v2 by before adding to @p v1.
|
|
public static void rcVmad(float[] dest, float[] v1, float[] v2, float s) {
|
|
dest[0] = v1[0] + v2[0] * s;
|
|
dest[1] = v1[1] + v2[1] * s;
|
|
dest[2] = v1[2] + v2[2] * s;
|
|
}
|
|
|
|
/// Performs a vector addition. (@p v1 + @p v2)
|
|
/// @param[out] dest The result vector. [(x, y, z)]
|
|
/// @param[in] v1 The base vector. [(x, y, z)]
|
|
/// @param[in] v2 The vector to add to @p v1. [(x, y, z)]
|
|
public static void rcVadd(float[] dest, float[] v1, float[] v2) {
|
|
dest[0] = v1[0] + v2[0];
|
|
dest[1] = v1[1] + v2[1];
|
|
dest[2] = v1[2] + v2[2];
|
|
}
|
|
|
|
/// Performs a vector subtraction. (@p v1 - @p v2)
|
|
/// @param[out] dest The result vector. [(x, y, z)]
|
|
/// @param[in] v1 The base vector. [(x, y, z)]
|
|
/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)]
|
|
public static void rcVsub(float[] dest, float[] v1, float[] v2) {
|
|
dest[0] = v1[0] - v2[0];
|
|
dest[1] = v1[1] - v2[1];
|
|
dest[2] = v1[2] - v2[2];
|
|
}
|
|
|
|
public static void rcVsub(float[] dest, int destStart, float[] v1, int v1Start, float[] v2, int v2Start) {
|
|
dest[destStart + 0] = v1[v1Start + 0] - v2[v2Start + 0];
|
|
dest[destStart + 1] = v1[v1Start + 1] - v2[v2Start + 1];
|
|
dest[destStart + 2] = v1[v1Start + 2] - v2[v2Start + 2];
|
|
}
|
|
|
|
/// Selects the minimum value of each element from the specified vectors.
|
|
/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)]
|
|
/// @param[in] v A vector. [(x, y, z)]
|
|
public static void rcVmin(float[] mn, float[] v) {
|
|
mn[0] = Math.Min(mn[0], v[0]);
|
|
mn[1] = Math.Min(mn[1], v[1]);
|
|
mn[2] = Math.Min(mn[2], v[2]);
|
|
}
|
|
|
|
public static void rcVmin(float[] mn, int mnStart, float[] v, int vStart) {
|
|
mn[0 + mnStart] = Math.Min(mn[0 + mnStart], v[0 + vStart]);
|
|
mn[1 + mnStart] = Math.Min(mn[1 + mnStart], v[1 + vStart]);
|
|
mn[2 + mnStart] = Math.Min(mn[2 + mnStart], v[2 + vStart]);
|
|
}
|
|
|
|
|
|
/// Selects the maximum value of each element from the specified vectors.
|
|
/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)]
|
|
/// @param[in] v A vector. [(x, y, z)]
|
|
public static void rcVmax(float[] mx, float[] v) {
|
|
mx[0] = Math.Max(mx[0], v[0]);
|
|
mx[1] = Math.Max(mx[1], v[1]);
|
|
mx[2] = Math.Max(mx[2], v[2]);
|
|
}
|
|
|
|
public static void rcVmax(float[] mx, int mxStart, float[] v, int vStart) {
|
|
mx[0 + mxStart] = Math.Max(mx[0 + mxStart], v[0 + vStart]);
|
|
mx[1 + mxStart] = Math.Max(mx[1 + mxStart], v[1 + vStart]);
|
|
mx[2 + mxStart] = Math.Max(mx[2 + mxStart], v[2 + vStart]);
|
|
}
|
|
|
|
/// Performs a vector copy.
|
|
/// @param[out] dest The result. [(x, y, z)]
|
|
/// @param[in] v The vector to copy. [(x, y, z)]
|
|
public static void rcVcopy(float[] dest, float[] v) {
|
|
dest[0] = v[0];
|
|
dest[1] = v[1];
|
|
dest[2] = v[2];
|
|
}
|
|
public static void rcVcopy(float[] dest, int destStart, float[] v, int vStart) {
|
|
dest[destStart + 0] = v[vStart + 0];
|
|
dest[destStart + 1] = v[vStart + 1];
|
|
dest[destStart + 2] = v[vStart + 2];
|
|
}
|
|
|
|
/// Returns the distance between two points.
|
|
/// @param[in] v1 A point. [(x, y, z)]
|
|
/// @param[in] v2 A point. [(x, y, z)]
|
|
/// @return The distance between the two points.
|
|
public static float rcVdist(float[] v1, float[] v2) {
|
|
float dx = v2[0] - v1[0];
|
|
float dy = v2[1] - v1[1];
|
|
float dz = v2[2] - v1[2];
|
|
return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
|
|
}
|
|
|
|
/// Returns the square of the distance between two points.
|
|
/// @param[in] v1 A point. [(x, y, z)]
|
|
/// @param[in] v2 A point. [(x, y, z)]
|
|
/// @return The square of the distance between the two points.
|
|
public static float rcVdistSqr(float[] v1, float[] v2) {
|
|
float dx = v2[0] - v1[0];
|
|
float dy = v2[1] - v1[1];
|
|
float dz = v2[2] - v1[2];
|
|
return dx * dx + dy * dy + dz * dz;
|
|
}
|
|
|
|
/// Normalizes the vector.
|
|
/// @param[in,out] v The vector to normalize. [(x, y, z)]
|
|
public static void rcVnormalize(float[] v) {
|
|
float d = 1.0f / (float)Math.Sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]));
|
|
v[0] *= d;
|
|
v[1] *= d;
|
|
v[2] *= d;
|
|
}
|
|
|
|
/// @}
|
|
/// @name Heightfield Functions
|
|
/// @see rcHeightfield
|
|
/// @{
|
|
|
|
/// Calculates the bounding box of an array of vertices.
|
|
/// @ingroup recast
|
|
/// @param[in] verts An array of vertices. [(x, y, z) * @p nv]
|
|
/// @param[in] nv The number of vertices in the @p verts array.
|
|
/// @param[out] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu]
|
|
/// @param[out] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu]
|
|
//void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax);
|
|
|
|
/// Calculates the grid size based on the bounding box and grid cell size.
|
|
/// @ingroup recast
|
|
/// @param[in] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu]
|
|
/// @param[in] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu]
|
|
/// @param[in] cs The xz-plane cell size. [Limit: > 0] [Units: wu]
|
|
/// @param[out] w The width along the x-axis. [Limit: >= 0] [Units: vx]
|
|
/// @param[out] h The height along the z-axis. [Limit: >= 0] [Units: vx]
|
|
//void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h);
|
|
|
|
/// Initializes a new heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in,out] hf The allocated heightfield to initialize.
|
|
/// @param[in] width The width of the field along the x-axis. [Limit: >= 0] [Units: vx]
|
|
/// @param[in] height The height of the field along the z-axis. [Limit: >= 0] [Units: vx]
|
|
/// @param[in] bmin The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
|
/// @param[in] bmax The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
|
/// @param[in] cs The xz-plane cell size to use for the field. [Limit: > 0] [Units: wu]
|
|
/// @param[in] ch The y-axis cell size to use for field. [Limit: > 0] [Units: wu]
|
|
//bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height,
|
|
// 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.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable.
|
|
/// [Limits: 0 <= value < 90] [Units: Degrees]
|
|
/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
|
/// @param[in] nv The number of vertices.
|
|
/// @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]
|
|
//void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
|
// const int* tris, int nt, byte* areas);
|
|
|
|
/// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable.
|
|
/// [Limits: 0 <= value < 90] [Units: Degrees]
|
|
/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
|
/// @param[in] nv The number of vertices.
|
|
/// @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]
|
|
//void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
|
//const int* tris, int nt, byte* areas);
|
|
|
|
/// Adds a span to the specified heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in,out] hf An initialized heightfield.
|
|
/// @param[in] x The width index where the span is to be added.
|
|
/// [Limits: 0 <= value < rcHeightfield::width]
|
|
/// @param[in] y The height index where the span is to be added.
|
|
/// [Limits: 0 <= value < rcHeightfield::height]
|
|
/// @param[in] smin The minimum height of the span. [Limit: < @p smax] [Units: vx]
|
|
/// @param[in] smax The maximum height of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT] [Units: vx]
|
|
/// @param[in] area The area id of the span. [Limit: <= #RC_WALKABLE_AREA)
|
|
/// @param[in] flagMergeThr The merge theshold. [Limit: >= 0] [Units: vx]
|
|
//void rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y,
|
|
// const ushort smin, const ushort smax,
|
|
// const byte area, const int flagMergeThr);
|
|
|
|
/// Rasterizes a triangle into the specified heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] v0 Triangle vertex 0 [(x, y, z)]
|
|
/// @param[in] v1 Triangle vertex 1 [(x, y, z)]
|
|
/// @param[in] v2 Triangle vertex 2 [(x, y, z)]
|
|
/// @param[in] area The area id of the triangle. [Limit: <= #RC_WALKABLE_AREA]
|
|
/// @param[in,out] solid An initialized heightfield.
|
|
/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
|
/// [Limit: >= 0] [Units: vx]
|
|
//void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
|
|
// const byte area, rcHeightfield& solid,
|
|
// const int flagMergeThr = 1);
|
|
|
|
/// Rasterizes an indexed triangle mesh into the specified heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
|
/// @param[in] nv The number of vertices.
|
|
/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt]
|
|
/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
|
|
/// @param[in] nt The number of triangles.
|
|
/// @param[in,out] solid An initialized heightfield.
|
|
/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
|
/// [Limit: >= 0] [Units: vx]
|
|
//void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
|
|
// const int* tris, const byte* areas, const int nt,
|
|
// rcHeightfield& solid, const int flagMergeThr = 1);
|
|
|
|
/// Rasterizes an indexed triangle mesh into the specified heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
|
/// @param[in] nv The number of vertices.
|
|
/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt]
|
|
/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
|
|
/// @param[in] nt The number of triangles.
|
|
/// @param[in,out] solid An initialized heightfield.
|
|
/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
|
/// [Limit: >= 0] [Units: vx]
|
|
//void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
|
|
// const ushort* tris, const byte* areas, const int nt,
|
|
// rcHeightfield& solid, const int flagMergeThr = 1);
|
|
|
|
/// Rasterizes triangles into the specified heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] verts The triangle vertices. [(ax, ay, az, bx, by, bz, cx, by, cx) * @p nt]
|
|
/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
|
|
/// @param[in] nt The number of triangles.
|
|
/// @param[in,out] solid An initialized heightfield.
|
|
/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
|
/// [Limit: >= 0] [Units: vx]
|
|
//void rcRasterizeTriangles(rcContext* ctx, const float* verts, const byte* areas, const int nt,
|
|
// rcHeightfield& solid, const int flagMergeThr = 1);
|
|
|
|
/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neihbor.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.
|
|
/// [Limit: >=0] [Units: vx]
|
|
/// @param[in,out] solid A fully built heightfield. (All spans have been added.)
|
|
//void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid);
|
|
|
|
/// Marks spans that are ledges as not-walkable.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to
|
|
/// be considered walkable. [Limit: >= 3] [Units: vx]
|
|
/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.
|
|
/// [Limit: >=0] [Units: vx]
|
|
/// @param[in,out] solid A fully built heightfield. (All spans have been added.)
|
|
//void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight,
|
|
// const int walkableClimb, rcHeightfield& solid);
|
|
|
|
/// Marks walkable spans as not walkable if the clearence above the span is less than the specified height.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to
|
|
/// be considered walkable. [Limit: >= 3] [Units: vx]
|
|
/// @param[in,out] solid A fully built heightfield. (All spans have been added.)
|
|
//void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid);
|
|
|
|
/// Returns the number of spans contained in the specified heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] hf An initialized heightfield.
|
|
/// @returns The number of spans in the heightfield.
|
|
//int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf);
|
|
|
|
/// @}
|
|
/// @name Compact Heightfield Functions
|
|
/// @see rcCompactHeightfield
|
|
/// @{
|
|
|
|
/// Builds a compact heightfield representing open space, from a heightfield representing solid space.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area
|
|
/// to be considered walkable. [Limit: >= 3] [Units: vx]
|
|
/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.
|
|
/// [Limit: >=0] [Units: vx]
|
|
/// @param[in] hf The heightfield to be compacted.
|
|
/// @param[out] chf The resulting compact heightfield. (Must be pre-allocated.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
|
// rcHeightfield& hf, rcCompactHeightfield& chf);
|
|
|
|
|
|
/// Erodes the walkable area within the heightfield by the specified radius.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] radius The radius of erosion. [Limits: 0 < value < 255] [Units: vx]
|
|
/// @param[in,out] chf The populated compact heightfield to erode.
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf);
|
|
|
|
/// Applies a median filter to walkable area types (based on area id), removing noise.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in,out] chf A populated compact heightfield.
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf);
|
|
|
|
/// Applies an area id to all spans within the specified bounding box. (AABB)
|
|
/// @ingroup recast
|
|
/// @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,out] chf A populated compact heightfield.
|
|
//void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, byte areaId,
|
|
// rcCompactHeightfield& chf);
|
|
|
|
/// Applies the area id to the all spans within the specified convex polygon.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] verts The vertices of the polygon [Fomr: (x, y, z) * @p nverts]
|
|
/// @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,out] chf A populated compact heightfield.
|
|
//void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
|
// const float hmin, const float hmax, byte areaId,
|
|
// rcCompactHeightfield& chf);
|
|
|
|
/// Helper function to offset voncex polygons for rcMarkConvexPolyArea.
|
|
/// @ingroup recast
|
|
/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p nverts]
|
|
/// @param[in] nverts The number of vertices in the polygon.
|
|
/// @param[out] outVerts The offset vertices (should hold up to 2 * @p nverts) [Form: (x, y, z) * return value]
|
|
/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts.
|
|
/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts.
|
|
//int rcOffsetPoly(const float* verts, const int nverts, const float offset,
|
|
// float* outVerts, const int maxOutVerts);
|
|
|
|
/// Applies the area id to all spans within the specified cylinder.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @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,out] chf A populated compact heightfield.
|
|
//void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
|
// const float r, const float h, byte areaId,
|
|
// rcCompactHeightfield& chf);
|
|
|
|
/// Builds the distance field for the specified compact heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in,out] chf A populated compact heightfield.
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf);
|
|
|
|
/// Builds region data for the heightfield using watershed partitioning.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in,out] chf A populated compact heightfield.
|
|
/// @param[in] borderSize The size of the non-navigable border around the heightfield.
|
|
/// [Limit: >=0] [Units: vx]
|
|
/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas.
|
|
/// [Limit: >=0] [Units: vx].
|
|
/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible,
|
|
/// be merged with larger regions. [Limit: >=0] [Units: vx]
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
|
// const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
|
|
|
/// Builds region data for the heightfield using simple monotone partitioning.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in,out] chf A populated compact heightfield.
|
|
/// @param[in] borderSize The size of the non-navigable border around the heightfield.
|
|
/// [Limit: >=0] [Units: vx]
|
|
/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas.
|
|
/// [Limit: >=0] [Units: vx].
|
|
/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible,
|
|
/// be merged with larger regions. [Limit: >=0] [Units: vx]
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
|
// const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
|
|
|
|
|
/// Sets the neighbor connection data for the specified direction.
|
|
/// @param[in] s The span to update.
|
|
/// @param[in] dir The direction to set. [Limits: 0 <= value < 4]
|
|
/// @param[in] i The index of the neighbor span.
|
|
public static void rcSetCon(ref rcCompactSpan s, int dir, int i) {
|
|
uint udir = (uint)dir;
|
|
int shift = (int)(udir * 6);
|
|
uint con = s.con;
|
|
s.con = (uint)(con & ~(0x3f << shift)) | (((uint)i & 0x3f) << shift);
|
|
}
|
|
|
|
/// Gets neighbor connection data for the specified direction.
|
|
/// @param[in] s The span to check.
|
|
/// @param[in] dir The direction to check. [Limits: 0 <= value < 4]
|
|
/// @return The neighbor connection data for the specified direction,
|
|
/// or #RC_NOT_CONNECTED if there is no connection.
|
|
public static int rcGetCon(rcCompactSpan s, int dir) {
|
|
uint udir = (uint)dir;
|
|
int shift = (int)(udir * 6);
|
|
return (int)((s.con >> shift) & 0x3f);
|
|
}
|
|
|
|
/// Gets the standard width (x-axis) offset for the specified direction.
|
|
/// @param[in] dir The direction. [Limits: 0 <= value < 4]
|
|
/// @return The width offset to apply to the current cell position to move
|
|
/// in the direction.
|
|
public static int rcGetDirOffsetX(int dir) {
|
|
int[] offset = new int[] { -1, 0, 1, 0, };
|
|
return offset[dir & 0x03];
|
|
}
|
|
|
|
/// Gets the standard height (z-axis) offset for the specified direction.
|
|
/// @param[in] dir The direction. [Limits: 0 <= value < 4]
|
|
/// @return The height offset to apply to the current cell position to move
|
|
/// in the direction.
|
|
public static int rcGetDirOffsetY(int dir) {
|
|
int[] offset = new int[] { 0, 1, 0, -1 };
|
|
return offset[dir & 0x03];
|
|
}
|
|
|
|
/// @}
|
|
/// @name Layer, Contour, Polymesh, and Detail Mesh Functions
|
|
/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail
|
|
/// @{
|
|
|
|
/// Builds a layer set from the specified compact heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] chf A fully built compact heightfield.
|
|
/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0]
|
|
/// [Units: vx]
|
|
/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area
|
|
/// to be considered walkable. [Limit: >= 3] [Units: vx]
|
|
/// @param[out] lset The resulting layer set. (Must be pre-allocated.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
|
// const int borderSize, const int walkableHeight,
|
|
// rcHeightfieldLayerSet& lset);
|
|
|
|
/// Builds a contour set from the region outlines in the provided compact heightfield.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] chf A fully built compact heightfield.
|
|
/// @param[in] maxError The maximum distance a simplfied contour's border edges should deviate
|
|
/// the original raw contour. [Limit: >=0] [Units: wu]
|
|
/// @param[in] maxEdgeLen The maximum allowed length for contour edges along the border of the mesh.
|
|
/// [Limit: >=0] [Units: vx]
|
|
/// @param[out] cset The resulting contour set. (Must be pre-allocated.)
|
|
/// @param[in] buildFlags The build flags. (See: #rcBuildContoursFlags)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
|
// const float maxError, const int maxEdgeLen,
|
|
// rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES);
|
|
|
|
/// Builds a polygon mesh from the provided contours.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] cset A fully built contour set.
|
|
/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the
|
|
/// contour to polygon conversion process. [Limit: >= 3]
|
|
/// @param[out] mesh The resulting polygon mesh. (Must be re-allocated.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh);
|
|
|
|
/// Merges multiple polygon meshes into a single mesh.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] meshes An array of polygon meshes to merge. [Size: @p nmeshes]
|
|
/// @param[in] nmeshes The number of polygon meshes in the meshes array.
|
|
/// @param[in] mesh The resulting polygon mesh. (Must be pre-allocated.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh);
|
|
|
|
/// Builds a detail mesh from the provided polygon mesh.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] mesh A fully built polygon mesh.
|
|
/// @param[in] chf The compact heightfield used to build the polygon mesh.
|
|
/// @param[in] sampleDist Sets the distance to use when samping the heightfield. [Limit: >=0] [Units: wu]
|
|
/// @param[in] sampleMaxError The maximum distance the detail mesh surface should deviate from
|
|
/// heightfield data. [Limit: >=0] [Units: wu]
|
|
/// @param[out] dmesh The resulting detail mesh. (Must be pre-allocated.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
|
|
// const float sampleDist, const float sampleMaxError,
|
|
// rcPolyMeshDetail& dmesh);
|
|
|
|
/// Copies the poly mesh data from src to dst.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] src The source mesh to copy from.
|
|
/// @param[out] dst The resulting detail mesh. (Must be pre-allocated, must be empty mesh.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst);
|
|
|
|
/// Merges multiple detail meshes into a single detail mesh.
|
|
/// @ingroup recast
|
|
/// @param[in,out] ctx The build context to use during the operation.
|
|
/// @param[in] meshes An array of detail meshes to merge. [Size: @p nmeshes]
|
|
/// @param[in] nmeshes The number of detail meshes in the meshes array.
|
|
/// @param[out] mesh The resulting detail mesh. (Must be pre-allocated.)
|
|
/// @returns True if the operation completed successfully.
|
|
//bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh);
|
|
|
|
/// @}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Due to the large amount of detail documentation for this file,
|
|
// the content normally located at the end of the header file has been separated
|
|
// out to a file in /Docs/Extern.
|