Theoretically this should be easy, but I’m running into some issues when sanity-checking in two ways. I’m trying to measure the sphere’s visual size in degrees using ().bounds(), but the output does not match what you would expect from simple trig. The result unexpectedly changes with the camera’s field of view (which can be adjusted manually in the inspector).
The output of the getWidthFromExtents() should match the “ground truth” analytic solution I find from the getTrigSizeDegs() function (about 28 degrees), but it does not - it changes with FOV. It is only the same when the vertical height of the sphere matches the editor window height. Ultimately, my goal is to make the angular size to be invariant over distance as well.
The script resize.cs with these functions is below. The small project can be accessed at GitHub - gabrielDiaz-performlab/Ball-size-on-screen.
Any advice? Thanks.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class resize : MonoBehaviour
{
// Update is called once per frame
void Update()
{
getWidthFromExtents();
getTrigSizeDegs();
}
public void getTrigSizeDegs()
{
float dist = Vector3.Distance(Camera.main.transform.position, transform.position);
float halfHeight = transform.localScale.y/2.0f;
float trigSizeDegs = 2.0f * Mathf.Atan( halfHeight / dist) * Mathf.Rad2Deg;
// Debug.Log(Time.frameCount.ToString() + " dist: " + dist.ToString());
// Debug.Log(Time.frameCount.ToString() + " radius: " + halfHeight.ToString());
Debug.Log(Time.frameCount.ToString() + " trigSizeDegs: " + trigSizeDegs.ToString());
}
public void getWidthFromExtents()
{
Renderer rend = GetComponent<Renderer>();
Vector3 cen = rend.bounds.center;
Vector3 ext = rend.bounds.extents;
// https://docs.unity3d.com/ScriptReference/Camera.WorldToViewportPoint.html
float minY = Camera.main.WorldToViewportPoint(new Vector3(cen.x, cen.y-ext.y, cen.z)).y;
float maxY = Camera.main.WorldToViewportPoint(new Vector3(cen.x, cen.y+ext.y, cen.z)).y;
float normHeight = (maxY-minY);
float sizeDegs = Camera.main.fieldOfView * normHeight;
Debug.Log(Time.frameCount.ToString() + " norm height: " + normHeight.ToString());
//Debug.Log(Time.frameCount.ToString() + " Vert screen res: " + screenVertRes.ToString());
//Debug.Log(Time.frameCount.ToString() + " fov: " + Camera.main.fieldOfView.ToString());
Debug.Log(Time.frameCount.ToString() + " extent size: " + sizeDegs.ToString());
Vector3 minVec = new Vector3(cen.x, cen.y-ext.y, cen.z);
Vector3 maxVec = new Vector3(cen.x, cen.y+ext.y, cen.z);
Debug.DrawLine(minVec, maxVec, Color.red, 2.5f);
}
}
