fix: Change DtRaycastHit class to struct to resolve SOH issue. step2

This commit is contained in:
ikpil 2024-01-31 00:59:48 +09:00 committed by Ikpil
parent 5bba84883e
commit aaff85b229
4 changed files with 91 additions and 24 deletions

View File

@ -187,20 +187,19 @@ namespace DotRecast.Detour.Crowd
return;
}
// Overshoot a little. This helps to optimize open fields in tiled
// meshes.
// Overshoot a little. This helps to optimize open fields in tiled meshes.
dist = Math.Min(dist + 0.01f, pathOptimizationRange);
// Adjust ray length.
var delta = RcVec3f.Subtract(next, m_pos);
RcVec3f goal = RcVecUtils.Mad(m_pos, delta, pathOptimizationRange / dist);
var status = navquery.Raycast(m_path[0], m_pos, goal, filter, 0, 0, out var rayHit);
var status = navquery.Raycast(m_path[0], m_pos, goal, filter, out var t, out var norm, out var path);
if (status.Succeeded())
{
if (rayHit.path.Count > 1 && rayHit.t > 0.99f)
if (path.Count > 1 && t > 0.99f)
{
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, rayHit.path);
m_path = DtPathUtils.MergeCorridorStartShortcut(m_path, path);
}
}
}

View File

@ -892,8 +892,9 @@ namespace DotRecast.Detour
List<long> shortcut = null;
if (tryLOS)
{
var rayHit = new DtRaycastHit(0);
var rayStatus = Raycast(parentRef, parentNode.pos, neighbourPos, filter,
DtRaycastOptions.DT_RAYCAST_USE_COSTS, grandpaRef, out var rayHit);
DtRaycastOptions.DT_RAYCAST_USE_COSTS, ref rayHit, grandpaRef);
if (rayStatus.Succeeded())
{
foundShortCut = rayHit.t >= 1.0f;
@ -1213,8 +1214,9 @@ namespace DotRecast.Detour
List<long> shortcut = null;
if (tryLOS)
{
var rayHit = new DtRaycastHit(0);
status = Raycast(parentRef, parentNode.pos, neighbourPos, m_query.filter,
DtRaycastOptions.DT_RAYCAST_USE_COSTS, grandpaRef, out var rayHit);
DtRaycastOptions.DT_RAYCAST_USE_COSTS, ref rayHit, grandpaRef);
if (status.Succeeded())
{
foundShortCut = rayHit.t >= 1.0f;
@ -2113,6 +2115,62 @@ namespace DotRecast.Detour
return DtStatus.DT_SUCCESS;
}
/// @par
///
/// This method is meant to be used for quick, short distance checks.
///
/// If the path array is too small to hold the result, it will be filled as
/// far as possible from the start postion toward the end position.
///
/// <b>Using the Hit Parameter (t)</b>
///
/// If the hit parameter is a very high value (FLT_MAX), then the ray has hit
/// the end position. In this case the path represents a valid corridor to the
/// end position and the value of @p hitNormal is undefined.
///
/// If the hit parameter is zero, then the start position is on the wall that
/// was hit and the value of @p hitNormal is undefined.
///
/// If 0 < t < 1.0 then the following applies:
///
/// @code
/// distanceToHitBorder = distanceToEndPosition * t
/// hitPoint = startPos + (endPos - startPos) * t
/// @endcode
///
/// <b>Use Case Restriction</b>
///
/// The raycast ignores the y-value of the end position. (2D check.) This
/// places significant limits on how it can be used. For example:
///
/// Consider a scene where there is a main floor with a second floor balcony
/// that hangs over the main floor. So the first floor mesh extends below the
/// balcony mesh. The start position is somewhere on the first floor. The end
/// position is on the balcony.
///
/// The raycast will search toward the end position along the first floor mesh.
/// If it reaches the end position's xz-coordinates it will indicate FLT_MAX
/// (no wall hit), meaning it reached the end position. This is one example of why
/// this method is meant for short distance checks.
///
public DtStatus Raycast(long startRef, RcVec3f startPos, RcVec3f endPos,
IDtQueryFilter filter,
out float t, out RcVec3f hitNormal, out List<long> path)
{
DtRaycastHit hit = new DtRaycastHit(0);
// hit.path = path;
// hit.maxPath = maxPath;
DtStatus status = Raycast(startRef, startPos, endPos, filter, 0, ref hit, 0);
t = hit.t;
hitNormal = hit.hitNormal;
path = hit.path;
// if (pathCount)
// *pathCount = hit.pathCount;
return status;
}
/// @par
///
@ -2166,11 +2224,10 @@ namespace DotRecast.Detour
/// @param[out] pathCount The number of visited polygons. [opt]
/// @param[in] maxPath The maximum number of polygons the @p path array can hold.
/// @returns The status flags for the query.
public DtStatus Raycast(long startRef, RcVec3f startPos, RcVec3f endPos, IDtQueryFilter filter, int options,
long prevRef, out DtRaycastHit hit)
public DtStatus Raycast(long startRef, RcVec3f startPos, RcVec3f endPos,
IDtQueryFilter filter, int options,
ref DtRaycastHit hit, long prevRef)
{
hit = null;
// Validate input
if (!m_nav.IsValidPolyRef(startRef) || !startPos.IsFinite() || !endPos.IsFinite()
|| null == filter || (prevRef != 0 && !m_nav.IsValidPolyRef(prevRef)))
@ -2178,7 +2235,9 @@ namespace DotRecast.Detour
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
}
hit = new DtRaycastHit();
hit.t = 0;
hit.path.Clear();
hit.pathCost = 0;
RcVec3f[] verts = new RcVec3f[m_nav.GetMaxVertsPerPoly() + 1];
@ -2186,7 +2245,8 @@ namespace DotRecast.Detour
RcVec3f lastPos = RcVec3f.Zero;
curPos = startPos;
var dir = RcVec3f.Subtract(endPos, startPos);
RcVec3f dir = RcVec3f.Subtract(endPos, startPos);
hit.hitNormal = RcVec3f.Zero;
DtMeshTile prevTile, tile, nextTile;
DtPoly prevPoly, poly, nextPoly;

View File

@ -26,22 +26,30 @@ namespace DotRecast.Detour
/// Provides information about raycast hit
/// filled by dtNavMeshQuery::raycast
/// @ingroup detour
public class DtRaycastHit
public struct DtRaycastHit
{
/// The hit parameter. (FLT_MAX if no wall hit.)
public float t;
/// hitNormal The normal of the nearest wall hit. [(x, y, z)]
public RcVec3f hitNormal = new RcVec3f();
public RcVec3f hitNormal;
/// The index of the edge on the final polygon where the wall was hit.
public int hitEdgeIndex;
/// Pointer to an array of reference ids of the visited polygons. [opt]
public readonly List<long> path = new List<long>();
public readonly List<long> path;
/// The cost of the path until hit.
public float pathCost;
public DtRaycastHit(int s)
{
t = 0;
hitEdgeIndex = 0;
hitNormal = RcVec3f.Zero;
path = new List<long>();
pathCost = 0;
}
}
}

View File

@ -257,16 +257,16 @@ namespace DotRecast.Recast.Toolset.Tools
return DtStatus.DT_FAILURE;
}
var status = navQuery.Raycast(startRef, startPos, endPos, filter, 0, 0, out var rayHit);
var status = navQuery.Raycast(startRef, startPos, endPos, filter, out var t, out var hitNormal2, out var path);
if (!status.Succeeded())
{
return status;
}
// results ...
polys = rayHit.path;
polys = path;
if (rayHit.t > 1)
if (t > 1)
{
// No hit
hitPos = endPos;
@ -275,15 +275,15 @@ namespace DotRecast.Recast.Toolset.Tools
else
{
// Hit
hitPos = RcVec3f.Lerp(startPos, endPos, rayHit.t);
hitNormal = rayHit.hitNormal;
hitPos = RcVec3f.Lerp(startPos, endPos, t);
hitNormal = hitNormal2;
hitResult = true;
}
// Adjust height.
if (rayHit.path.Count > 0)
if (path.Count > 0)
{
var result = navQuery.GetPolyHeight(rayHit.path[rayHit.path.Count - 1], hitPos, out var h);
var result = navQuery.GetPolyHeight(path[path.Count - 1], hitPos, out var h);
if (result.Succeeded())
{
hitPos.Y = h;