Last active
May 6, 2021 17:07
-
-
Save L4ZZA/3e7612b099caece4499ef655b8ab3e88 to your computer and use it in GitHub Desktop.
Mesh triangles retrieval in Unity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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