Updated Mesh Colliders of all Humans and added FOV Representation

This commit is contained in:
Thorbjoern
2025-07-16 00:02:07 +02:00
parent 8e711ca067
commit 74f2ecabd2
38 changed files with 7876 additions and 44 deletions
+144
View File
@@ -0,0 +1,144 @@
using System.Collections.Generic;
using UnityEngine;
public class FieldOfView : MonoBehaviour
{
public float viewRadius;
[Range(0,360)]
public float periAngle;
[Range(0,180)]
public float foveaAngle;
public Transform eyeLeft;
public Transform eyeRight;
public LayerMask targetMask;
public LayerMask obstacleMask;
public float meshResolution;
public MeshFilter periMeshFilter;
public MeshFilter foveaMeshFilter;
private Mesh periMesh;
private Mesh foveaMesh;
private void Start()
{
periMesh = new Mesh();
periMesh.name = "View Mesh";
periMeshFilter.mesh = periMesh;
foveaMesh = new Mesh();
foveaMesh.name = "View Mesh";
foveaMeshFilter.mesh = foveaMesh;
}
private void LateUpdate()
{
Vector3 gazeDirection = ((eyeLeft.forward + eyeRight.forward) * 0.5f).normalized;
float gazeAngle = AngleFromDir(gazeDirection, true);
DrawFOV(transform.eulerAngles.y, periMesh, periAngle);
DrawFOV(gazeAngle, foveaMesh, foveaAngle);
}
public Vector3 DirFromAngle(float angleDeg, bool angleIsGlobal)
{
if (!angleIsGlobal)
{
angleDeg += transform.eulerAngles.y;
}
return new Vector3(Mathf.Sin(angleDeg * Mathf.Deg2Rad), 0, Mathf.Cos(angleDeg * Mathf.Deg2Rad));
}
public float AngleFromDir(Vector3 dir, bool angleIsGlobal)
{
// Sicherheitsnetz: yKomponente ignorieren und Vektor normalisieren
dir.y = 0;
if (dir.sqrMagnitude < 0.0001f) return 0f;
// Atan2: (x, z) → Winkel in Rad, dann nach ° umrechnen
float angleDeg = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
// Bereich schön sauber auf 0360 bringen
angleDeg = (angleDeg + 360f) % 360f;
// Soll der Winkel relativ zum Objekt sein?
if (!angleIsGlobal)
angleDeg -= transform.eulerAngles.y;
// Und noch einmal normalisieren, damit auch hier 0360 garantiert ist
return (angleDeg + 360f) % 360f;
}
void DrawFOV(float startAngle, Mesh viewMesh, float viewAngle)
{
int stepCount = Mathf.RoundToInt(foveaAngle * meshResolution);
float stepAngleSize = viewAngle / stepCount;
List<Vector3> viewPoints = new List<Vector3>();
for (int i = 0; i <= stepCount; i++)
{
float angle = startAngle - viewAngle / 2 + stepAngleSize * i;
Debug.DrawLine(transform.position, transform.position + DirFromAngle(angle, true) * viewRadius, Color.red);
ViewCastInfo newViewCast = ViewCast(angle);
viewPoints.Add(newViewCast.hitPoint);
}
int vertexcount = viewPoints.Count + 1;
Vector3[] vertices = new Vector3[vertexcount];
int[] triangles = new int[(vertexcount-2) * 3];
vertices[0] = Vector3.zero;
for (int i = 0; i < vertexcount-1; i++)
{
vertices[i+1] = transform.InverseTransformPoint(viewPoints[i]);
if (i < vertexcount - 2)
{
triangles[i * 3] = 0;
triangles[i * 3 + 1] = i + 1;
triangles[i * 3 + 2] = i + 2;
}
}
viewMesh.Clear();
viewMesh.vertices = vertices;
viewMesh.triangles = triangles;
viewMesh.RecalculateNormals();
}
ViewCastInfo ViewCast(float globalAngle)
{
Vector3 direction = DirFromAngle(globalAngle, true);
RaycastHit hit;
if (Physics.Raycast(transform.position, direction, out hit, viewRadius, obstacleMask))
{
return new ViewCastInfo(true, hit.point, hit.distance, globalAngle);
}
else
{
return new ViewCastInfo(false, transform.position + direction * viewRadius, viewRadius, globalAngle);
}
}
public struct ViewCastInfo
{
public bool didHit;
public Vector3 hitPoint;
public float distance;
public float angle;
public ViewCastInfo(bool _hit, Vector3 _hitPoint, float _distance, float _angle)
{
didHit = _hit;
hitPoint = _hitPoint;
distance = _distance;
angle = _angle;
}
}
}