AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SolverRadialView.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 {
13  public class SolverRadialView : Solver
14  {
15  #region public enums
17  {
21  ObjectOriented,
25  FacingWorldUp,
29  HeadMoveDirection,
33  GravityAligned
34  }
35  #endregion
36 
37  #region public members
38  [Tooltip("Which direction to position the element relative to: HeadOriented rolls with the head, HeadFacingWorldUp view dir but ignores head roll, and HeadMoveDirection uses the direction the head last moved without roll")]
39  public ReferenceDirectionEnum ReferenceDirection = ReferenceDirectionEnum.FacingWorldUp;
40 
41  [Tooltip("Min distance from eye to position element around, i.e. the sphere radius")]
42  public float MinDistance = 1f;
43  [Tooltip("Max distance from eye to element")]
44  public float MaxDistance = 2f;
45 
46  [Tooltip("The element will stay at least this far away from the center of view")]
47  public float MinViewDegrees = 0f;
48  [Tooltip("The element will stay at least this close to the center of view")]
49  public float MaxViewDegrees = 30f;
50  [Tooltip("Apply a different clamp to vertical FOV than horizontal. Vertical = Horizontal * AspectV")]
51  public float AspectV = 1f;
52 
53  [Tooltip("Option to ignore angle clamping")]
54  public bool IgnoreAngleClamp = false;
55  [Tooltip("Option to ignore distance clamping")]
56  public bool IgnoreDistanceClamp = false;
57 
58  [Tooltip("If true, element will orient to ReferenceDirection, otherwise it will orient to ref pos (the head is the only option currently)")]
59  public bool OrientToRefDir = false;
60  #endregion
61 
66  private Vector3 GetReferenceDirection()
67  {
68  Vector3 ret = Vector3.one;
69  if (ReferenceDirection == ReferenceDirectionEnum.HeadMoveDirection && solverHandler.TrackedObjectToReference == SolverHandler.TrackedObjectToReferenceEnum.Head)
70  {
71  ret = Camera.main.GetComponent<InputModule.CameraMotionInfo>().MoveDirection;
72  }
73  else
74  {
75  ret = base.solverHandler.TransformTarget != null ? base.solverHandler.TransformTarget.forward : Vector3.forward;
76  }
77  return ret;
78  }
79 
84  private Vector3 GetReferenceUp()
85  {
86  Vector3 ret = Vector3.up;
87  if (ReferenceDirection == ReferenceDirectionEnum.ObjectOriented)
88  {
89  ret = base.solverHandler.TransformTarget != null ? base.solverHandler.TransformTarget.up : Vector3.up;
90  }
91  return ret;
92  }
93 
94  private Vector3 GetReferencePoint()
95  {
96  return base.solverHandler.TransformTarget != null ? base.solverHandler.TransformTarget.position : Vector3.zero;
97  }
98 
102  public override void SolverUpdate()
103  {
104 
105  Vector3 desiredPos = this.WorkingPos;
106 
107  if (IgnoreAngleClamp)
108  {
109  if (IgnoreDistanceClamp)
110  {
111  desiredPos = transform.position;
112  }
113  else
114  {
115  GetDesiredOrientation_DistanceOnly(ref desiredPos);
116  }
117  }
118  else
119  {
120  GetDesiredOrientation(ref desiredPos);
121  }
122 
123  // Element orientation
124  Vector3 refDirUp = GetReferenceUp();
125  Quaternion desiredRot = Quaternion.identity;
126 
127  if (OrientToRefDir)
128  {
129  desiredRot = Quaternion.LookRotation(GetReferenceDirection(), refDirUp);
130  }
131  else
132  {
133  Vector3 refPoint = GetReferencePoint();
134  desiredRot = Quaternion.LookRotation(desiredPos - refPoint, refDirUp);
135  }
136 
137  // If gravity aligned then zero out the x and z eulers on the rotation
138  if (ReferenceDirection == ReferenceDirectionEnum.GravityAligned)
139  {
140  desiredRot.x = desiredRot.z = 0f;
141  }
142 
143  this.GoalPosition = desiredPos;
144  this.GoalRotation = desiredRot;
145 
146  UpdateWorkingPosToGoal();
147  UpdateWorkingRotToGoal();
148  }
149 
154  private void GetDesiredOrientation_DistanceOnly(ref Vector3 desiredPos)
155  {
156  // Determine reference locations and directions
157  Vector3 refPoint = GetReferencePoint();
158  Vector3 elementPoint = transform.position;
159  Vector3 elementDelta = elementPoint - refPoint;
160  float elementDist = elementDelta.magnitude;
161  Vector3 elementDir = elementDist > 0 ? elementDelta / elementDist : Vector3.one;
162 
163  // Clamp distance too
164  float clampedDistance = Mathf.Clamp(elementDist, MinDistance, MaxDistance);
165 
166  if (clampedDistance != elementDist)
167  {
168  desiredPos = refPoint + clampedDistance * elementDir;
169  }
170  }
171 
172  private void GetDesiredOrientation(ref Vector3 desiredPos)
173  {
174  // Determine reference locations and directions
175  Vector3 refDir = GetReferenceDirection();
176  Vector3 refDirUp = GetReferenceUp();
177  Vector3 refPoint = GetReferencePoint();
178  Vector3 elementPoint = transform.position;
179  Vector3 elementDelta = elementPoint - refPoint;
180  float elementDist = elementDelta.magnitude;
181  Vector3 elementDir = elementDist > 0 ? elementDelta / elementDist : Vector3.one;
182 
183  // Generate basis: First get axis perp to refDir pointing toward element
184  Vector3 elementDirPerp = (elementDir - refDir);
185  elementDirPerp -= refDir * Vector3.Dot(elementDirPerp, refDir);
186  elementDirPerp.Normalize();
187 
188  // Calculate the clamping angles, accounting for aspect (need the angle relative to view plane)
189  float HtoVAng = Vector3.Angle(elementDirPerp, refDirUp);
190  float VAspectScale = Mathf.Lerp(AspectV, 1f, Mathf.Abs(Mathf.Sin(HtoVAng * Mathf.Deg2Rad)));
191 
192  // Calculate the current angle
193  float angDegree = Vector3.Angle(elementDir, refDir);
194  float angDegreeClamped = Mathf.Clamp(angDegree, MinViewDegrees * VAspectScale, MaxViewDegrees * VAspectScale);
195 
196  // Clamp distance too, if desired
197  float clampedDistance = IgnoreDistanceClamp ? elementDist : Mathf.Clamp(elementDist, MinDistance, MaxDistance);
198 
199  // If the angle was clamped, do some special update stuff
200  if (angDegree != angDegreeClamped)
201  {
202  float angRad = angDegreeClamped * Mathf.Deg2Rad;
203 
204  // Calculate new position
205  desiredPos = refPoint + clampedDistance * (refDir * Mathf.Cos(angRad) + elementDirPerp * Mathf.Sin(angRad));
206  }
207  else if (clampedDistance != elementDist)
208  {
209  // Only need to apply distance
210  desiredPos = refPoint + clampedDistance * elementDir;
211  }
212  }
213  }
214 }
RadialViewPoser solver locks a tag-along type object within a view cone
override void SolverUpdate()
Solver update function used to orient to the user
SolverBase is the base abstract class for all Solvers to derive from. It provides state tracking...
Definition: Solver.cs:15
SolverHandler solverHandler
Definition: Solver.cs:49