- Home /
How to calculate the percentage of a mesh visible by a camera?
I'm trying to calculate the percentage of a mesh visible by a camera (the mesh is always moving). I tried to achieve this using mesh vertices, but it seems that it's not working. When the camera is not moving and the mesh is inside the camera, the percentage stays the same. When I move the camera the percentage changes but is not correct.
I'm using Unity 2017.1.0p5. Here is the code I've made:
float percentage = 0f;
int totalOfVertices = 0;
int count = 0;
totalOfVertices = _meshFilter.mesh.vertices.Length;
for (int i = 0; i < totalOfVertices; i++)
{
Vector3 v = transform.TransformPoint(_meshFilter.mesh.vertices[i]);
if (specificCamera.WorldToViewportPoint(v).x > 0f &&
specificCamera.WorldToViewportPoint(v).x < 1f &&
specificCamera.WorldToViewportPoint(v).y > 0f &&
specificCamera.WorldToViewportPoint(v).y < 1f &&
specificCamera.WorldToViewportPoint(v).z > 0f)
{
count += 1;
}
}
percentage = (count * 100f) / totalOfVertices;
Any idea ? Or another way to figure it out ?
Thank you
Answer by Aisenhein · Aug 31, 2017 at 04:29 AM
@lkvn18 My initial idea would be to try to count++ inside of OnBecameVisible() of a script attached to all objects
Maybe add +1 in a singleton count variable to can calculate it.
Answer by lkvn18 · Aug 31, 2017 at 01:43 PM
@Aisenhein Thanks for your reply ! I believe this might not work in my case because I need to know the visible percentage of only one object (made of one mesh).
Ah ok, I understand now, sorry. Do you need a accurate calc? Because you could to try to put invisible small objects as child objects of the mesh that represents some parts of it and count with the OnBecameVisible this parts to calculate what part is visible or not. Something like that works for you?
Yes, I need a pretty accurate calc, that's why I was trying to calculate that using mesh vertices.
http://imgur.com/a/$$anonymous$$9EpH
With small objects inside the mesh, even if the camera sees just a little part of a child object, that will consider it can see the whole child object. For instance, in the image above, that will consider the camera sees 100% of the mesh.
I thought that you can use very small boxes to get it, anyway, if you need something more accurate, have you ever try this?
http://answers.unity3d.com/questions/393524/check-if-a-mesh-is-fully-visible-to-camera.html
I've seen this post but even if I adapt the code, I can't figure it out. For instance, if my camera doesn't see the mesh, the result is always $$anonymous$$imum 16%, even if it is behind the camera. In fact, it seems that the closest the mesh is to the camera the more the percentage is high. If I add "&& !plane.GetSide(vertice)" in my condition with "GetDistanceToPoint", the result is 0, but only 17% when the mesh is fully visible.
Here is the code after some adaptation:
private Plane[] _planes;
private void Start()
{
_planes = GeometryUtility.CalculateFrustumPlanes(specificCamera);
}
private float GetScreenPercentage($$anonymous$$eshFilter _meshFilter)
{
float percentage = 0f;
int totalTested = 0;
int count = 0;
foreach (Plane plane in _planes)
{
foreach (Vector3 vertice in _meshFilter.mesh.vertices)
{
if (plane.GetDistanceToPoint(_meshFilter.transform.
TransformPoint(vertice)) > 0)
{
count += 1;
}
totalOfVertices += 1;
}
}
percentage = (count * 100f) / totalTested;
return percentage;
}
Thank you
I made a test with this script, see it below, and get a initial value of 1194 with the count, when my mesh that I'm testing is out of screen this value decrease to 995, in my case, 1194 - 995 = 199, exactly the count of verts of my mesh. Almost half of the mesh out, I get 1129 and decreasing till 995 when all out like I told. I think that if you get this initial value with the mesh all inside the screen or all out, it's easy to you calculate the percentage.
public class $$anonymous$$eshCalc : $$anonymous$$onoBehaviour {
public $$anonymous$$eshFilter mesh;
Vector3[] vertex$$anonymous$$esh;
public Camera cam;
int count;
Plane[] planes;
void Start () {
vertex$$anonymous$$esh = mesh.mesh.vertices;
}
void Update () {
planes = GeometryUtility.CalculateFrustumPlanes(cam);
count = 0;
foreach (Plane plane in planes) {
foreach (Vector3 vertex in vertex$$anonymous$$esh) {
if (!(plane.GetDistanceToPoint(mesh.transform.TransformPoint(vertex)) < 0)) {
count++;
}
}
}
print(count);
}
}