changed polyLinks to firstLinks

This commit is contained in:
ikpil 2024-05-16 00:30:07 +09:00 committed by Ikpil
parent 4543df0b90
commit c3208f7968
7 changed files with 96 additions and 93 deletions

View File

@ -18,6 +18,8 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
using System;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
/// Defines a link between polygons. /// Defines a link between polygons.
@ -25,6 +27,7 @@ namespace DotRecast.Detour
/// @see dtMeshTile /// @see dtMeshTile
public class DtLink public class DtLink
{ {
public readonly int index; // DtMeshTile.links array index
public long refs; //< Neighbour reference. (The neighbor that is linked to.) public long refs; //< Neighbour reference. (The neighbor that is linked to.)
public int next; //< Index of the next link. public int next; //< Index of the next link.
public int edge; //< Index of the polygon edge that owns this link. public int edge; //< Index of the polygon edge that owns this link.

View File

@ -18,8 +18,6 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
using System.Collections.Generic;
namespace DotRecast.Detour namespace DotRecast.Detour
{ {
using static DtDetour; using static DtDetour;
@ -32,17 +30,13 @@ namespace DotRecast.Detour
public int linksFreeList = DT_NULL_LINK; //< Index to the next free link. public int linksFreeList = DT_NULL_LINK; //< Index to the next free link.
public int salt; //< Counter describing modifications to the tile. public int salt; //< Counter describing modifications to the tile.
public DtMeshData data; // The tile data. public DtMeshData data; // The tile data.
public DtLink[] links; // The tile links. [Size: dtMeshHeader::maxLinkCount]
public int[] polyLinks;
public readonly List<DtLink> links; // The tile links. [Size: dtMeshHeader::maxLinkCount]
public int flags; //< Tile flags. (See: #dtTileFlags) public int flags; //< Tile flags. (See: #dtTileFlags)
public DtMeshTile(int index) public DtMeshTile(int index)
{ {
this.index = index; this.index = index;
this.links = new List<DtLink>();
} }
} }
} }

View File

@ -129,12 +129,7 @@ namespace DotRecast.Detour
private int AllocLink(DtMeshTile tile) private int AllocLink(DtMeshTile tile)
{ {
if (tile.linksFreeList == DT_NULL_LINK) if (tile.linksFreeList == DT_NULL_LINK)
{ return DT_NULL_LINK;
DtLink link = new DtLink();
link.next = DT_NULL_LINK;
tile.links.Add(link);
return tile.links.Count - 1;
}
int linkIdx = tile.linksFreeList; int linkIdx = tile.linksFreeList;
tile.linksFreeList = tile.links[linkIdx].next; tile.linksFreeList = tile.links[linkIdx].next;
@ -420,16 +415,16 @@ namespace DotRecast.Detour
return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY; return DtStatus.DT_FAILURE | DtStatus.DT_OUT_OF_MEMORY;
} }
tile.data = data;
tile.flags = flags;
tile.links.Clear();
tile.polyLinks = new int[data.polys.Length];
Array.Fill(tile.polyLinks, DT_NULL_LINK);
// Insert tile into the position lut. // Insert tile into the position lut.
GetTileListByPos(header.x, header.y).Add(tile); GetTileListByPos(header.x, header.y).Add(tile);
// Patch header pointers. // Patch header pointers.
tile.data = data;
tile.links = new DtLink[data.header.maxLinkCount];
for (int i = 0; i < tile.links.Length; ++i)
{
tile.links[i] = new DtLink();
}
// If there are no items in the bvtree, reset the tree pointer. // If there are no items in the bvtree, reset the tree pointer.
if (tile.data.bvTree != null && tile.data.bvTree.Length == 0) if (tile.data.bvTree != null && tile.data.bvTree.Length == 0)
@ -437,7 +432,14 @@ namespace DotRecast.Detour
tile.data.bvTree = null; tile.data.bvTree = null;
} }
// Build links freelist
tile.linksFreeList = 0;
tile.links[data.header.maxLinkCount - 1].next = DT_NULL_LINK;
for (int i = 0; i < data.header.maxLinkCount - 1; ++i)
tile.links[i].next = i + 1;
// Init tile. // Init tile.
tile.flags = flags;
ConnectIntLinks(tile); ConnectIntLinks(tile);
// Base off-mesh connections to their starting polygons and connect connections inside the tile. // Base off-mesh connections to their starting polygons and connect connections inside the tile.
@ -535,9 +537,8 @@ namespace DotRecast.Detour
// Reset tile. // Reset tile.
tile.data = null; tile.data = null;
tile.flags = 0; tile.flags = 0;
tile.links.Clear(); tile.links = null;
tile.linksFreeList = DT_NULL_LINK; tile.linksFreeList = DT_NULL_LINK;
// Update salt, salt should never be zero. // Update salt, salt should never be zero.
@ -566,7 +567,7 @@ namespace DotRecast.Detour
for (int i = 0; i < tile.data.header.polyCount; ++i) for (int i = 0; i < tile.data.header.polyCount; ++i)
{ {
DtPoly poly = tile.data.polys[i]; DtPoly poly = tile.data.polys[i];
tile.polyLinks[poly.index] = DT_NULL_LINK; poly.firstLink = DT_NULL_LINK;
if (poly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION) if (poly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
@ -590,13 +591,13 @@ namespace DotRecast.Detour
link.side = 0xff; link.side = 0xff;
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
// Add to linked list. // Add to linked list.
link.next = tile.polyLinks[poly.index]; link.next = poly.firstLink;
tile.polyLinks[poly.index] = idx; poly.firstLink = idx;
} }
} }
} }
/// Removes external links at specified side.V /// Removes external links at specified side.
void UnconnectLinks(DtMeshTile tile, DtMeshTile target) void UnconnectLinks(DtMeshTile tile, DtMeshTile target)
{ {
if (tile == null || target == null) if (tile == null || target == null)
@ -609,7 +610,7 @@ namespace DotRecast.Detour
for (int i = 0; i < tile.data.header.polyCount; ++i) for (int i = 0; i < tile.data.header.polyCount; ++i)
{ {
DtPoly poly = tile.data.polys[i]; DtPoly poly = tile.data.polys[i];
int j = tile.polyLinks[poly.index]; int j = poly.firstLink;
int pj = DT_NULL_LINK; int pj = DT_NULL_LINK;
while (j != DT_NULL_LINK) while (j != DT_NULL_LINK)
{ {
@ -619,7 +620,7 @@ namespace DotRecast.Detour
int nj = tile.links[j].next; int nj = tile.links[j].next;
if (pj == DT_NULL_LINK) if (pj == DT_NULL_LINK)
{ {
tile.polyLinks[poly.index] = nj; poly.firstLink = nj;
} }
else else
{ {
@ -679,46 +680,49 @@ namespace DotRecast.Detour
foreach (var connectPoly in connectPolys) foreach (var connectPoly in connectPolys)
{ {
int idx = AllocLink(tile); int idx = AllocLink(tile);
DtLink link = tile.links[idx]; if (idx != DT_NULL_LINK)
link.refs = connectPoly.refs;
link.edge = j;
link.side = dir;
link.next = tile.polyLinks[poly.index];
tile.polyLinks[poly.index] = idx;
// Compress portal limits to a byte value.
if (dir == 0 || dir == 4)
{ {
float tmin = (connectPoly.tmin - tile.data.verts[va + 2]) DtLink link = tile.links[idx];
/ (tile.data.verts[vb + 2] - tile.data.verts[va + 2]); link.refs = connectPoly.refs;
float tmax = (connectPoly.tmax - tile.data.verts[va + 2]) link.edge = j;
/ (tile.data.verts[vb + 2] - tile.data.verts[va + 2]); link.side = dir;
if (tmin > tmax)
{
float temp = tmin;
tmin = tmax;
tmax = temp;
}
link.bmin = (int)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f); link.next = poly.firstLink;
link.bmax = (int)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f); poly.firstLink = idx;
}
else if (dir == 2 || dir == 6)
{
float tmin = (connectPoly.tmin - tile.data.verts[va])
/ (tile.data.verts[vb] - tile.data.verts[va]);
float tmax = (connectPoly.tmax - tile.data.verts[va])
/ (tile.data.verts[vb] - tile.data.verts[va]);
if (tmin > tmax)
{
float temp = tmin;
tmin = tmax;
tmax = temp;
}
link.bmin = (int)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f); // Compress portal limits to a byte value.
link.bmax = (int)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f); if (dir == 0 || dir == 4)
{
float tmin = (connectPoly.tmin - tile.data.verts[va + 2])
/ (tile.data.verts[vb + 2] - tile.data.verts[va + 2]);
float tmax = (connectPoly.tmax - tile.data.verts[va + 2])
/ (tile.data.verts[vb + 2] - tile.data.verts[va + 2]);
if (tmin > tmax)
{
float temp = tmin;
tmin = tmax;
tmax = temp;
}
link.bmin = (int)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f);
link.bmax = (int)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f);
}
else if (dir == 2 || dir == 6)
{
float tmin = (connectPoly.tmin - tile.data.verts[va])
/ (tile.data.verts[vb] - tile.data.verts[va]);
float tmax = (connectPoly.tmax - tile.data.verts[va])
/ (tile.data.verts[vb] - tile.data.verts[va]);
if (tmin > tmax)
{
float temp = tmin;
tmin = tmax;
tmax = temp;
}
link.bmin = (int)MathF.Round(Math.Clamp(tmin, 0.0f, 1.0f) * 255.0f);
link.bmax = (int)MathF.Round(Math.Clamp(tmax, 0.0f, 1.0f) * 255.0f);
}
} }
} }
} }
@ -748,7 +752,7 @@ namespace DotRecast.Detour
DtPoly targetPoly = target.data.polys[targetCon.poly]; DtPoly targetPoly = target.data.polys[targetCon.poly];
// Skip off-mesh connections which start location could not be // Skip off-mesh connections which start location could not be
// connected at all. // connected at all.
if (target.polyLinks[targetPoly.index] == DT_NULL_LINK) if (targetPoly.firstLink == DT_NULL_LINK)
{ {
continue; continue;
} }
@ -789,8 +793,8 @@ namespace DotRecast.Detour
link.side = oppositeSide; link.side = oppositeSide;
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
// Add to linked list. // Add to linked list.
link.next = target.polyLinks[targetPoly.index]; link.next = targetPoly.firstLink;
target.polyLinks[targetPoly.index] = idx; targetPoly.firstLink = idx;
// Link target poly to off-mesh connection. // Link target poly to off-mesh connection.
if ((targetCon.flags & DT_OFFMESH_CON_BIDIR) != 0) if ((targetCon.flags & DT_OFFMESH_CON_BIDIR) != 0)
@ -804,8 +808,8 @@ namespace DotRecast.Detour
link.side = (side == -1 ? 0xff : side); link.side = (side == -1 ? 0xff : side);
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
// Add to linked list. // Add to linked list.
link.next = tile.polyLinks[landPoly.index]; link.next = landPoly.firstLink;
tile.polyLinks[landPoly.index] = tidx; landPoly.firstLink = tidx;
} }
} }
} }
@ -963,8 +967,8 @@ namespace DotRecast.Detour
link.side = 0xff; link.side = 0xff;
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
// Add to linked list. // Add to linked list.
link.next = tile.polyLinks[poly.index]; link.next = poly.firstLink;
tile.polyLinks[poly.index] = idx; poly.firstLink = idx;
// Start end-point is always connect back to off-mesh connection. // Start end-point is always connect back to off-mesh connection.
int tidx = AllocLink(tile); int tidx = AllocLink(tile);
@ -976,8 +980,8 @@ namespace DotRecast.Detour
link.side = 0xff; link.side = 0xff;
link.bmin = link.bmax = 0; link.bmin = link.bmax = 0;
// Add to linked list. // Add to linked list.
link.next = tile.polyLinks[landPoly.index]; link.next = landPoly.firstLink;
tile.polyLinks[landPoly.index] = tidx; landPoly.firstLink = tidx;
} }
} }
@ -1411,7 +1415,7 @@ namespace DotRecast.Detour
int idx0 = 0, idx1 = 1; int idx0 = 0, idx1 = 1;
// Find link that points to first vertex. // Find link that points to first vertex.
for (int i = tile.polyLinks[poly.index]; i != DT_NULL_LINK; i = tile.links[i].next) for (int i = poly.firstLink; i != DT_NULL_LINK; i = tile.links[i].next)
{ {
if (tile.links[i].edge == 0) if (tile.links[i].edge == 0)
{ {

View File

@ -302,7 +302,7 @@ namespace DotRecast.Detour
parentRef = m_nodePool.GetNodeAtIdx(bestNode.pidx).id; parentRef = m_nodePool.GetNodeAtIdx(bestNode.pidx).id;
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestPoly.firstLink; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -853,7 +853,7 @@ namespace DotRecast.Detour
} }
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestPoly.firstLink; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
long neighbourRef = bestTile.links[i].refs; long neighbourRef = bestTile.links[i].refs;
@ -1174,7 +1174,7 @@ namespace DotRecast.Detour
} }
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestPoly.firstLink; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
long neighbourRef = bestTile.links[i].refs; long neighbourRef = bestTile.links[i].refs;
@ -1867,7 +1867,7 @@ namespace DotRecast.Detour
if ((curPoly.neis[j] & DT_EXT_LINK) != 0) if ((curPoly.neis[j] & DT_EXT_LINK) != 0)
{ {
// Tile border. // Tile border.
for (int k = curTile.polyLinks[curPoly.index]; k != DT_NULL_LINK; k = curTile.links[k].next) for (int k = curPoly.firstLink; k != DT_NULL_LINK; k = curTile.links[k].next)
{ {
DtLink link = curTile.links[k]; DtLink link = curTile.links[k];
if (link.edge == j) if (link.edge == j)
@ -2013,7 +2013,7 @@ namespace DotRecast.Detour
// Find the link that points to the 'to' polygon. // Find the link that points to the 'to' polygon.
DtLink link = null; DtLink link = null;
for (int i = fromTile.polyLinks[fromPoly.index]; i != DT_NULL_LINK; i = fromTile.links[i].next) for (int i = fromPoly.firstLink; i != DT_NULL_LINK; i = fromTile.links[i].next)
{ {
if (fromTile.links[i].refs == to) if (fromTile.links[i].refs == to)
{ {
@ -2031,7 +2031,7 @@ namespace DotRecast.Detour
if (fromPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION) if (fromPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
// Find link that points to first vertex. // Find link that points to first vertex.
for (int i = fromTile.polyLinks[fromPoly.index]; i != DT_NULL_LINK; i = fromTile.links[i].next) for (int i = fromPoly.firstLink; i != DT_NULL_LINK; i = fromTile.links[i].next)
{ {
if (fromTile.links[i].refs == to) if (fromTile.links[i].refs == to)
{ {
@ -2053,7 +2053,7 @@ namespace DotRecast.Detour
if (toPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION) if (toPoly.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION)
{ {
for (int i = toTile.polyLinks[toPoly.index]; i != DT_NULL_LINK; i = toTile.links[i].next) for (int i = toPoly.firstLink; i != DT_NULL_LINK; i = toTile.links[i].next)
{ {
if (toTile.links[i].refs == from) if (toTile.links[i].refs == from)
{ {
@ -2329,7 +2329,7 @@ namespace DotRecast.Detour
// Follow neighbours. // Follow neighbours.
long nextRef = 0; long nextRef = 0;
for (int i = tile.polyLinks[poly.index]; i != DT_NULL_LINK; i = tile.links[i].next) for (int i = poly.firstLink; i != DT_NULL_LINK; i = tile.links[i].next)
{ {
DtLink link = tile.links[i]; DtLink link = tile.links[i];
@ -2570,7 +2570,7 @@ namespace DotRecast.Detour
resultParent.Add(parentRef); resultParent.Add(parentRef);
resultCost.Add(bestNode.total); resultCost.Add(bestNode.total);
for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestPoly.firstLink; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -2747,7 +2747,7 @@ namespace DotRecast.Detour
resultParent.Add(parentRef); resultParent.Add(parentRef);
resultCost.Add(bestNode.total); resultCost.Add(bestNode.total);
for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestPoly.firstLink; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -2902,7 +2902,7 @@ namespace DotRecast.Detour
long curRef = curNode.id; long curRef = curNode.id;
m_nav.GetTileAndPolyByRefUnsafe(curRef, out var curTile, out var curPoly); m_nav.GetTileAndPolyByRefUnsafe(curRef, out var curTile, out var curPoly);
for (int i = curTile.polyLinks[curPoly.index]; i != DT_NULL_LINK; i = curTile.links[i].next) for (int i = curPoly.firstLink; i != DT_NULL_LINK; i = curTile.links[i].next)
{ {
DtLink link = curTile.links[i]; DtLink link = curTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;
@ -2970,7 +2970,7 @@ namespace DotRecast.Detour
// Connected polys do not overlap. // Connected polys do not overlap.
bool connected = false; bool connected = false;
for (int k = curTile.polyLinks[curPoly.index]; k != DT_NULL_LINK; k = curTile.links[k].next) for (int k = curPoly.firstLink; k != DT_NULL_LINK; k = curTile.links[k].next)
{ {
if (curTile.links[k].refs == pastRef) if (curTile.links[k].refs == pastRef)
{ {
@ -3079,7 +3079,7 @@ namespace DotRecast.Detour
if ((poly.neis[j] & DT_EXT_LINK) != 0) if ((poly.neis[j] & DT_EXT_LINK) != 0)
{ {
// Tile border. // Tile border.
for (int k = tile.polyLinks[poly.index]; k != DT_NULL_LINK; k = tile.links[k].next) for (int k = poly.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
DtLink link = tile.links[k]; DtLink link = tile.links[k];
if (link.edge == j) if (link.edge == j)
@ -3247,7 +3247,7 @@ namespace DotRecast.Detour
{ {
// Tile border. // Tile border.
bool solid = true; bool solid = true;
for (int k = bestTile.polyLinks[bestPoly.index]; k != DT_NULL_LINK; k = bestTile.links[k].next) for (int k = bestPoly.firstLink; k != DT_NULL_LINK; k = bestTile.links[k].next)
{ {
DtLink link = bestTile.links[k]; DtLink link = bestTile.links[k];
if (link.edge == j) if (link.edge == j)
@ -3303,7 +3303,7 @@ namespace DotRecast.Detour
bestvi = RcVecUtils.Create(bestTile.data.verts, vi); bestvi = RcVecUtils.Create(bestTile.data.verts, vi);
} }
for (int i = bestTile.polyLinks[bestPoly.index]; i != DT_NULL_LINK; i = bestTile.links[i].next) for (int i = bestPoly.firstLink; i != DT_NULL_LINK; i = bestTile.links[i].next)
{ {
DtLink link = bestTile.links[i]; DtLink link = bestTile.links[i];
long neighbourRef = link.refs; long neighbourRef = link.refs;

View File

@ -109,7 +109,7 @@ namespace DotRecast.Detour
} }
for (int k = tile.polyLinks[poly.index]; k != DT_NULL_LINK; k = tile.links[k].next) for (int k = poly.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
DtLink link = tile.links[k]; DtLink link = tile.links[k];
if (link.refs != 0) if (link.refs != 0)

View File

@ -24,8 +24,10 @@ namespace DotRecast.Detour
/// @ingroup detour /// @ingroup detour
public class DtPoly public class DtPoly
{ {
/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
public readonly int index; public readonly int index;
/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
public int firstLink;
/// The indices of the polygon's vertices. /// The indices of the polygon's vertices.
/// The actual vertices are located in dtMeshTile::verts. /// The actual vertices are located in dtMeshTile::verts.

View File

@ -202,7 +202,7 @@ public class RecastDebugDraw : DebugDraw
// Check to see if start and end end-points have links. // Check to see if start and end end-points have links.
bool startSet = false; bool startSet = false;
bool endSet = false; bool endSet = false;
for (int k = tile.polyLinks[p.index]; k != DT_NULL_LINK; k = tile.links[k].next) for (int k = p.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
if (tile.links[k].edge == 0) if (tile.links[k].edge == 0)
{ {
@ -326,7 +326,7 @@ public class RecastDebugDraw : DebugDraw
if ((p.neis[j] & DT_EXT_LINK) != 0) if ((p.neis[j] & DT_EXT_LINK) != 0)
{ {
bool con = false; bool con = false;
for (int k = tile.polyLinks[p.index]; k != DT_NULL_LINK; k = tile.links[k].next) for (int k = p.firstLink; k != DT_NULL_LINK; k = tile.links[k].next)
{ {
if (tile.links[k].edge == j) if (tile.links[k].edge == j)
{ {