Skip to content

Instantly share code, notes, and snippets.

@L4ZZA
Last active May 6, 2021 17:07
Show Gist options
  • Save L4ZZA/3e7612b099caece4499ef655b8ab3e88 to your computer and use it in GitHub Desktop.
Save L4ZZA/3e7612b099caece4499ef655b8ab3e88 to your computer and use it in GitHub Desktop.
Mesh triangles retrieval in Unity
/// <summary>
/// Holds the data for each mesh triangle in world coordinates.
/// </summary>
[Serializable]
public class Triangle
{
public Vector3 vertexA;
public Vector3 vertexB;
public Vector3 vertexC;
public Vector3 normalA;
public Vector3 normalB;
public Vector3 normalC;
public Vector3 centroid => (vertexA + vertexB + vertexC) / 3f;
public Vector3 centroidNormal => (normalA + normalB + normalC) / 3f;
public Bounds bounds
{
get
{
var min = Vector3.Min(vertexA, Vector3.Min(vertexB, vertexC));
var max = Vector3.Max(vertexA, Vector3.Max(vertexB, vertexC));
var b = new Bounds(centroid, max-min);
return b;
}
}
}
/// <summary>
/// Navigates each triangle in the mesh and stores them in a list.
/// </summary>
void NavigateTrianglesInMesh(MeshFilter meshFilter, Transform meshTransform)
{
var originalMesh = meshFilter.sharedMesh;
//Mesh data calls can be VERY expensive so cache them first
Vector3[] verts = originalMesh.vertices;
int[] indices = originalMesh.triangles;
Vector3[] norms = originalMesh.normals;
for(int i = 0; i < originalMesh.triangles.Length;)
{
var triangle = new Triangle();
// get triangle's related indices
int indexA = indices[i++];
int indexB = indices[i++];
int indexC = indices[i++];
// and use them to get the vertices
triangle.vertexA = meshTransform.TransformPoint(verts[indexA]);
triangle.vertexB = meshTransform.TransformPoint(verts[indexB]);
triangle.vertexC = meshTransform.TransformPoint(verts[indexC]);
// and the normals
triangle.normalA = meshTransform.TransformDirection(norms[indexA]);
triangle.normalB = meshTransform.TransformDirection(norms[indexB]);
triangle.normalC = meshTransform.TransformDirection(norms[indexC]);
// check if triangle bounds are inside fov
bool withinFOV = IsWithinFOV(triangle, Camera.main);
bool isHorizontalPlane = triangle.centroidNormal == Vector3.up;
if(withinFOV && !isHorizontalPlane)
{
// transform to world coordinates
var debugOrigin = triangle.centroid;
var debugLength = triangle.centroidNormal;
Debug.DrawLine(debugOrigin, debugOrigin + debugLength, Color.yellow, 0.1f);
}
}
}
/// <summary>
/// Returns true if the bounds of the renderer are inside the camera frustum.
/// Reference https://forum.unity.com/threads/is-target-in-view-frustum.86136/#post-626470
/// </summary>
/// <param name="renderer"></param>
/// <param name="camera"></param>
/// <returns></returns>
public bool IsWithinFOV(Renderer renderer, Camera camera)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
}
/// <summary>
/// Override for triangle
/// </summary>
/// <param name="triangle"></param>
/// <param name="camera"></param>
/// <returns></returns>
public bool IsWithinFOV(Triangle triangle, Camera camera)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, triangle.bounds);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment