AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SolverConstantViewSize.cs
Go to the documentation of this file.
1 //
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // Licensed under the MIT License. See LICENSE in the project root for license information.
4 //
5 using UnityEngine;
6 using System.Collections;
7 
8 namespace HoloToolkit.Unity
9 {
14  {
15  #region public members
16  [Tooltip("The object take up this percent vertically in our view (not technically a percent use 0.5 for 50%)")]
17  public float TargetViewPercentV = 0.5f;
18 
19  [Tooltip("If the object is closer than MinDistance, the distance used is clamped here")]
20  public float MinDistance = 0.5f;
21 
22  [Tooltip("If the object is farther than MaxDistance, the distance used is clamped here")]
23  public float MaxDistance = 3.5f;
24 
25  [Tooltip("Minimum scale value possible (world space scale)")]
26  public float MinScale = 0.01f;
27 
28  [Tooltip("Maximum scale value possible (world space scale)")]
29  public float MaxScale = 100f;
30 
31  [Tooltip("Used for dead zone for scaling")]
32  public float ScaleBuffer = 0.01f;
33 
34  [Tooltip("If you don't trust or don't like the auto size calculation, specify a manual size here. 0 is ignored")]
35  public float ManualObjectSize = 0;
36  public enum ScaleStateEnum
37  {
38  Static,
39  Shrinking,
40  Growing
41  }
42 
43  [HideInInspector]
44  public ScaleStateEnum ScaleState = ScaleStateEnum.Static;
45 
46  // 0 to 1 between MinScale and MaxScale. If currently < max, then scaling is being applied.
47  // This value is subject to inaccuracies due to smoothing/interpolation/momentum
48  public float CurrentScalePercent
49  {
50  get
51  {
52  return objectScalePercent;
53  }
54  }
55 
56  // 0 to 1 between MinDistance and MaxDistance. If current < max, object is potentially on a surface [or some other condition like interpolating] (since it may still be on surface, but scale percent may be clamped at max)
57  // This value is subject to inaccuracies due to smoothing/interpolation/momentum
58  public float CurrentDistancePercent
59  {
60  get
61  {
62  return objectDistancePercent;
63  }
64  }
65  #endregion
66 
67  #region private members
68  private float fovScalar = 1f;
69  private float objectSize = 1f;
70  private float objectScalePercent = 1f;
71  private float objectDistancePercent = 1f;
72  #endregion
73 
74  protected void Start()
75  {
76  float baseSize = CalculateObjectSize();
77 
78  if (baseSize > 0)
79  {
80  objectSize = baseSize;
81  }
82  else
83  {
84  Debug.LogWarning("ConstantViewSize: Object base size calculate was 0, defaulting to 1");
85  objectSize = 1f;
86  }
87  }
88 
96  private float CalculateObjectSize()
97  {
98  if (ManualObjectSize > 0)
99  {
100  return ManualObjectSize;
101  }
102 
103  Vector3 rootScale = transform.root.localScale;
104  transform.root.localScale = Vector3.one;
105 
106  float maxSize = 1f;
107 
108  Bounds combinedBounds = new Bounds(transform.position, Vector3.zero);
109  Renderer[] renderers = this.GetComponentsInChildren<Renderer>();
110 
111  foreach (Renderer render in renderers)
112  {
113  combinedBounds.Encapsulate(render.bounds);
114  }
115 
116  maxSize = combinedBounds.extents.magnitude;
117 
118  transform.root.localScale = rootScale;
119 
120  return maxSize;
121  }
122 
123 
124  public override void SolverUpdate()
125  {
126  float lastScalePct = objectScalePercent;
127  AdjustSizeForView(solverHandler.TransformTarget);
128  float scaleDiff = (objectScalePercent - lastScalePct) / solverHandler.DeltaTime;
129 
130  if (scaleDiff > ScaleBuffer)
131  {
132  ScaleState = ScaleStateEnum.Growing;
133  }
134  else if (scaleDiff < -ScaleBuffer)
135  {
136  ScaleState = ScaleStateEnum.Shrinking;
137  }
138  else
139  {
140  ScaleState = ScaleStateEnum.Static;
141  }
142  }
143 
149  public float GetFOVScalar()
150  {
151  float camFOVrad = (CameraCache.Main.aspect * CameraCache.Main.fieldOfView) * Mathf.Deg2Rad;
152 
153  float sinfov = Mathf.Sin(camFOVrad * 0.5f);
154  float scalar = 2f * TargetViewPercentV * sinfov / objectSize;
155 
156  return scalar;
157  }
158 
159  private void AdjustSizeForView(Transform targTransform)
160  {
161  if (targTransform != null)
162  {
163  // Get current fov each time instead of trying to cache it. Can never count on init order these days
164  fovScalar = GetFOVScalar();
165 
166  // Set the linked alt scale ahead of our work. This is an attempt to minimize jittering by having solvers work with an interpolated scale.
167  solverHandler.AltScale.SetGoal(this.transform.localScale);
168 
169  // Calculate scale based on distance from view. Do not interpolate so we can appear at a constant size if possible. Borrowed from greybox.
170  //bool ignoreParent = false;
171  float scalePower = 1f;
172 
173  Vector3 targetPosition = targTransform.position;
174  float distance = Mathf.Clamp(Vector3.Distance(transform.position, targetPosition), MinDistance, MaxDistance);
175  float scale = Mathf.Clamp(fovScalar * Mathf.Pow(distance, scalePower), MinScale, MaxScale);
176  GoalScale = Vector3.one * scale;
177 
178  // Save some state information for external use
179  objectDistancePercent = Mathf.InverseLerp(MinDistance, MaxDistance, distance);
180  objectScalePercent = Mathf.InverseLerp(MinScale, MaxScale, scale);
181 
182  UpdateWorkingScaleToGoal();
183  }
184  }
185  }
186 
187 }
SolverBase is the base abstract class for all Solvers to derive from. It provides state tracking...
Definition: Solver.cs:15
float GetFOVScalar()
Returns the scale to be applied based on the FOV. This scale will be multiplied by distance as part o...
ConstantViewSize solver scales to maintain a constant size relative to the view (currently tied to th...
The purpose of this class is to provide a cached reference to the main camera. Calling Camera...
Definition: CameraCache.cs:12
static Camera Main
Returns a cached reference to the main camera and uses Camera.main if it hasn&#39;t been cached yet...
Definition: CameraCache.cs:20