- Home /
How can i mimic the "Frame Selected [F]" camera move? (Zoom Extents, Zoom to Fit)
I'm essentially trying to recreate the 'Frame Selected' built in editor function at runtime. unfortunately it seems a bit too generic of search terms to find real info on the forums anywhere!?
So, From a little searching online as best as i can find, The formula for the distance from an object at a certain field of view is something like:
set camera to look at the desired object
Distance from object = BoundingRadius/(sin(fov/2))
will post some results as I make them!
Answer by Jaap Kreijkamp · Mar 16, 2010 at 11:23 PM
A simple implementation in C# (made that you can click on objects to focus so you can test it, although I'm lazy so clicking only works for objects with colliders).
using UnityEngine; using System.Collections;
public class JFocusCamera : MonoBehaviour {
Bounds CalculateBounds(GameObject go) {
Bounds b = new Bounds(go.transform.position, Vector3.zero);
Object[] rList = go.GetComponentsInChildren(typeof(Renderer));
foreach (Renderer r in rList) {
b.Encapsulate(r.bounds);
}
return b;
}
void FocusCameraOnGameObject(Camera c, GameObject go) {
Bounds b = CalculateBounds(go);
Vector3 max = b.size;
float radius = Mathf.Max(max.x, Mathf.Max(max.y, max.z));
float dist = radius / (Mathf.Sin(c.fieldOfView * Mathf.Deg2Rad / 2f));
Debug.Log("Radius = " + radius + " dist = " + dist);
Vector3 pos = Random.onUnitSphere * dist + b.center;
c.transform.position = pos;
c.transform.LookAt(b.center);
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0)) {
Camera c = Camera.main;
Vector3 mp = Input.mousePosition;
Ray ray = c.ScreenPointToRay(mp);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity)) {
FocusCameraOnGameObject(Camera.main, hit.transform.gameObject);
}
}
}
}
Jaap! Thanks a ton, i think the Deg2Rad was screwing me up when i was trying!
Thanks! This helped me as well, it's exactly what I was looking for.
Answer by Amir Ebrahimi · May 24, 2012 at 10:39 PM
The previous answer provided isn't an entirely correct answer although produces fairly good results. There are many parts involved, such as the difference in the vertical and horizontal FOVs as well as properly circumscribing the bounding volume to get the radius. This example also handles orthographic cameras:
Bounds CalculateBounds(GameObject go) {
Bounds b = new Bounds(go.transform.position, Vector3.zero);
Object[] rList = go.GetComponentsInChildren(typeof(Renderer));
foreach (Renderer r in rList) {
b.Encapsulate(r.bounds);
}
return b;
}
public void FocusCameraOnGameObject(Camera c, GameObject go) {
Bounds b = CalculateBounds(go);
Vector3 max = b.size;
// Get the radius of a sphere circumscribing the bounds
float radius = max.magnitude / 2f;
// Get the horizontal FOV, since it may be the limiting of the two FOVs to properly encapsulate the objects
float horizontalFOV = 2f * Mathf.Atan(Mathf.Tan(c.fieldOfView * Mathf.Deg2Rad / 2f) * c.aspect) * Mathf.Rad2Deg;
// Use the smaller FOV as it limits what would get cut off by the frustum
float fov = Mathf.Min(c.fieldOfView, horizontalFOV);
float dist = radius / (Mathf.Sin(fov * Mathf.Deg2Rad / 2f));
Debug.Log("Radius = " + radius + " dist = " + dist);
c.transform.SetLocalPositionZ(dist);
if (c.orthographic)
c.orthographicSize = radius;
// Frame the object hierarchy
c.transform.LookAt(b.center);
}
Your answer
Follow this Question
Related Questions
How to do perspective camera zoom? 1 Answer
Changing camera position to shoot through scope on gun 1 Answer
Raycast misses after camera zoom 2 Answers
Lining up Fov's 0 Answers