/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
using UnityEngine;
namespace NRKernal.NRExamples
{
/// A camera smooth follow.
public class CameraSmoothFollow : MonoBehaviour
{
/// The anchor.
[Header("Window Settings")]
[SerializeField, Tooltip("What part of the view port to anchor the window to.")]
private TextAnchor Anchor = TextAnchor.LowerCenter;
/// The follow speed.
[SerializeField, Range(0.0f, 100.0f), Tooltip("How quickly to interpolate the window towards its target position and rotation.")]
private float FollowSpeed = 5.0f;
/// The default distance.
private float defaultDistance;
/// default rotation at start.
private Vector2 defaultRotation = new Vector2(0f, 0f);
/// The horizontal rotation.
private Quaternion HorizontalRotation;
/// The horizontal rotation inverse.
private Quaternion HorizontalRotationInverse;
/// The vertical rotation.
private Quaternion VerticalRotation;
/// The vertical rotation inverse.
private Quaternion VerticalRotationInverse;
/// The offset.
[SerializeField, Tooltip("The offset from the view port center applied based on the window anchor selection.")]
private Vector2 Offset = new Vector2(0.1f, 0.1f);
private Transform m_CenterCamera;
private Transform CenterCamera
{
get
{
if (m_CenterCamera == null)
{
if (NRSessionManager.Instance.CenterCameraAnchor != null)
{
m_CenterCamera = NRSessionManager.Instance.CenterCameraAnchor;
}
else if (Camera.main != null)
{
m_CenterCamera = Camera.main.transform;
}
}
return m_CenterCamera;
}
}
/// Starts this object.
void Start()
{
HorizontalRotation = Quaternion.AngleAxis(defaultRotation.y, Vector3.right);
HorizontalRotationInverse = Quaternion.Inverse(HorizontalRotation);
VerticalRotation = Quaternion.AngleAxis(defaultRotation.x, Vector3.up);
VerticalRotationInverse = Quaternion.Inverse(VerticalRotation);
defaultDistance = Vector3.Distance(transform.position, CenterCamera.position);
}
/// Late update.
private void LateUpdate()
{
if (CenterCamera == null)
{
return;
}
float t = Time.deltaTime * FollowSpeed;
transform.position = Vector3.Lerp(transform.position, CalculatePosition(CenterCamera), t);
transform.rotation = Quaternion.Slerp(transform.rotation, CalculateRotation(CenterCamera), t);
}
/// Calculates the position.
/// The camera transform.
/// The calculated position.
private Vector3 CalculatePosition(Transform cameraTransform)
{
Vector3 position = cameraTransform.position + (cameraTransform.forward * defaultDistance);
Vector3 horizontalOffset = cameraTransform.right * Offset.x;
Vector3 verticalOffset = cameraTransform.up * Offset.y;
switch (Anchor)
{
case TextAnchor.UpperLeft: position += verticalOffset - horizontalOffset; break;
case TextAnchor.UpperCenter: position += verticalOffset; break;
case TextAnchor.UpperRight: position += verticalOffset + horizontalOffset; break;
case TextAnchor.MiddleLeft: position -= horizontalOffset; break;
case TextAnchor.MiddleRight: position += horizontalOffset; break;
case TextAnchor.LowerLeft: position -= verticalOffset + horizontalOffset; break;
case TextAnchor.LowerCenter: position -= verticalOffset; break;
case TextAnchor.LowerRight: position -= verticalOffset - horizontalOffset; break;
}
return position;
}
/// Calculates the rotation.
/// The camera transform.
/// The calculated rotation.
private Quaternion CalculateRotation(Transform cameraTransform)
{
Quaternion rotation = cameraTransform.rotation;
switch (Anchor)
{
case TextAnchor.UpperLeft: rotation *= HorizontalRotationInverse * VerticalRotationInverse; break;
case TextAnchor.UpperCenter: rotation *= HorizontalRotationInverse; break;
case TextAnchor.UpperRight: rotation *= HorizontalRotationInverse * VerticalRotation; break;
case TextAnchor.MiddleLeft: rotation *= VerticalRotationInverse; break;
case TextAnchor.MiddleRight: rotation *= VerticalRotation; break;
case TextAnchor.LowerLeft: rotation *= HorizontalRotation * VerticalRotationInverse; break;
case TextAnchor.LowerCenter: rotation *= HorizontalRotation; break;
case TextAnchor.LowerRight: rotation *= HorizontalRotation * VerticalRotation; break;
}
return rotation;
}
}
}