Optimized FOV Representation

This commit is contained in:
Thorbjoern
2025-07-16 23:45:04 +02:00
parent 74f2ecabd2
commit 13cd053279
6 changed files with 103 additions and 22 deletions
+63 -1
View File
@@ -18,6 +18,9 @@ public class FieldOfView : MonoBehaviour
public LayerMask obstacleMask;
public float meshResolution;
public int edgeResolveIterations;
public float edgeDistanceThreshold;
public MeshFilter periMeshFilter;
public MeshFilter foveaMeshFilter;
private Mesh periMesh;
@@ -73,9 +76,10 @@ public class FieldOfView : MonoBehaviour
void DrawFOV(float startAngle, Mesh viewMesh, float viewAngle)
{
int stepCount = Mathf.RoundToInt(foveaAngle * meshResolution);
int stepCount = Mathf.RoundToInt(viewAngle * meshResolution);
float stepAngleSize = viewAngle / stepCount;
List<Vector3> viewPoints = new List<Vector3>();
ViewCastInfo oldViewCast = new ViewCastInfo();
for (int i = 0; i <= stepCount; i++)
{
@@ -84,7 +88,25 @@ public class FieldOfView : MonoBehaviour
Debug.DrawLine(transform.position, transform.position + DirFromAngle(angle, true) * viewRadius, Color.red);
ViewCastInfo newViewCast = ViewCast(angle);
if (i > 0)
{
bool edgeDistThresholdExeeded = Mathf.Abs(oldViewCast.distance - newViewCast.distance) > edgeDistanceThreshold;
if (oldViewCast.didHit != newViewCast.didHit || (oldViewCast.didHit && newViewCast.didHit && edgeDistThresholdExeeded))
{
EdgeInfo edge = FingEdge(oldViewCast, newViewCast);
if (edge.pointmin != Vector3.zero)
{
viewPoints.Add(edge.pointmin);
}
if (edge.pointmax != Vector3.zero)
{
viewPoints.Add(edge.pointmax);
}
}
}
viewPoints.Add(newViewCast.hitPoint);
oldViewCast = newViewCast;
}
int vertexcount = viewPoints.Count + 1;
@@ -141,4 +163,44 @@ public class FieldOfView : MonoBehaviour
angle = _angle;
}
}
public struct EdgeInfo
{
public Vector3 pointmin;
public Vector3 pointmax;
public EdgeInfo(Vector3 _pointmin, Vector3 _pointmax)
{
pointmin = _pointmin;
pointmax = _pointmax;
}
}
EdgeInfo FingEdge(ViewCastInfo minViewCast, ViewCastInfo maxViewCast)
{
float minAngle = minViewCast.angle;
float maxAngle = maxViewCast.angle;
Vector3 minPoint = Vector3.zero;
Vector3 maxPoint = Vector3.zero;
for (int i = 0; i < edgeResolveIterations; i++)
{
float angle = (minAngle + maxAngle) / 2;
ViewCastInfo newViewCast = ViewCast(angle);
bool edgeDistThresholdExeeded = Mathf.Abs(minViewCast.distance - newViewCast.distance) > edgeDistanceThreshold;
if (newViewCast.didHit == minViewCast.didHit && !edgeDistThresholdExeeded)
{
minAngle = angle;
minPoint = newViewCast.hitPoint;
}
else
{
maxAngle = angle;
maxPoint = newViewCast.hitPoint;
}
}
return new EdgeInfo(minPoint, maxPoint);
}
}