Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
CameraFitter.cs
Go to the documentation of this file.
1 using System.Collections;
4 using UnityEngine;
5 
6 namespace droid.Runtime.Utilities.GameObjects.NeodroidCamera {
10  [RequireComponent(typeof(Camera))]
11  public class CameraFitter : MonoBehaviour {
12  [SerializeField] BoundingBox bb;
13  [SerializeField] float margin = 0f;
14  Camera _camera;
15 
16  void Start() {
17  if (!this.bb) {
18  this.bb = FindObjectOfType<BoundingBox>();
19  }
20 
21  if (!this._camera) {
22  this._camera = this.GetComponent<Camera>();
23  }
24  }
25 
26  void OnPreRender() {
27  if (this.bb) {
28  this._camera.transform.LookAt(this.bb.transform);
29  var radius = this.bb.Bounds.extents.MaxDim();
30  this._camera.MoveToDisplayInstant(radius, this.bb.transform.position, this.margin);
31  }
32  }
33  }
34 
38  public static class Utils {
39  // cam - camera to use
40  // center - screen pixel center
41  // pixelHeight - height of the rectangle in pixels
42  // time - time to take zooming
43  static IEnumerator ZoomToDisplay(this Camera cam, Vector3 center, float pixel_height, float time) {
44  var cam_tran = cam.transform;
45  var ray = cam.ScreenPointToRay(center);
46  var end_rotation = Quaternion.LookRotation(ray.direction);
47  var position = cam_tran.position;
48  var end_position = ProjectPointOnPlane(cam_tran.forward, position, ray.origin);
49  var opp = Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
50  opp *= pixel_height / Screen.height;
51  var end_fov = Mathf.Atan(opp) * 2.0f * Mathf.Rad2Deg;
52 
53  var timer = 0.0f;
54  var start_rotation = cam_tran.rotation;
55  var start_fov = cam.fieldOfView;
56  var start_position = position;
57 
58  while (timer <= 1.0f) {
59  var t = Mathf.Sin(timer * Mathf.PI * 0.5f);
60  cam_tran.rotation = Quaternion.Slerp(start_rotation, end_rotation, t);
61  cam_tran.position = Vector3.Lerp(start_position, end_position, t);
62  cam.fieldOfView = Mathf.Lerp(start_fov, end_fov, t);
63  timer += Time.deltaTime / time;
64  yield return null;
65  }
66 
67  cam_tran.rotation = end_rotation;
68  cam_tran.position = end_position;
69  cam.fieldOfView = end_fov;
70  }
71 
72  // cam - camera to use
73  // center - screen pixel center
74  // pixelHeight - height of the rectangle in pixels
75  public static void ZoomToDisplayInstant(this Camera cam, Vector2 center, float pixel_height) {
76  var cam_tran = cam.transform;
77  var ray = cam.ScreenPointToRay(center);
78  var end_rotation = Quaternion.LookRotation(ray.direction);
79  var end_position = ProjectPointOnPlane(cam_tran.forward, cam_tran.position, ray.origin);
80 
81  var opp = Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
82  opp *= pixel_height / Screen.height;
83  var end_fov = Mathf.Atan(opp) * 2.0f * Mathf.Rad2Deg;
84 
85  cam_tran.rotation = end_rotation;
86  cam_tran.position = end_position;
87  cam.fieldOfView = end_fov;
88  }
89 
90  // cam - camera to use
91  // center - screen pixel center
92  // pixelHeight - height of the rectangle in pixels
100  public static void MoveToDisplayInstant(this Camera cam,
101  float radius,
102  Vector3 bb_position,
103  float margin = 1f) {
104  var bound_sphere_radius = radius + margin;
105  var fov = Mathf.Deg2Rad * cam.fieldOfView;
106  var cam_distance = bound_sphere_radius * .5f / Mathf.Tan(fov * .5f);
107 
108  var transform = cam.transform;
109  transform.position = bb_position - transform.forward * cam_distance;
110  }
111 
112  public static Vector3 ProjectPointOnPlane(Vector3 plane_normal, Vector3 plane_point, Vector3 point) {
113  plane_normal.Normalize();
114  var distance = -Vector3.Dot(plane_normal.normalized, (point - plane_point));
115  return point + plane_normal * distance;
116  }
117  }
118 }