Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

236 lines
6.5 KiB

/************************************************************************************
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
See SampleFramework license.txt for license terms. Unless required by applicable law
or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the license for specific
language governing permissions and limitations under the license.
************************************************************************************/
using UnityEngine;
using UnityEngine.Assertions;
namespace OculusSampleFramework
{
public class TrackSegment : MonoBehaviour
{
public enum SegmentType
{
Straight = 0,
LeftTurn,
RightTurn,
Switch
}
[SerializeField] private SegmentType _segmentType = SegmentType.Straight;
[SerializeField] private MeshFilter _straight = null;
[SerializeField] private MeshFilter _leftTurn = null;
[SerializeField] private MeshFilter _rightTurn = null;
private float _gridSize = 0.8f;
private int _subDivCount = 20;
private const float _originalGridSize = 0.8f;
private const float _trackWidth = 0.15f;
private GameObject _mesh = null;
public float StartDistance { get; set; }
// create variables here to avoid realtime allocation
private Pose _p1 = new Pose();
private Pose _p2 = new Pose();
public float GridSize
{
get
{
return _gridSize;
}
private set
{
_gridSize = value;
}
}
public int SubDivCount
{
get
{
return _subDivCount;
}
set
{
_subDivCount = value;
}
}
public SegmentType Type
{
get
{
return _segmentType;
}
}
private Pose _endPose = new Pose();
public Pose EndPose
{
get
{
UpdatePose(SegmentLength, _endPose);
return _endPose;
}
}
public float Radius
{
get
{
return 0.5f * GridSize;
}
}
public float setGridSize(float size)
{
GridSize = size;
return GridSize / _originalGridSize;
}
public float SegmentLength
{
get
{
switch (Type)
{
case SegmentType.Straight:
return GridSize;
case SegmentType.LeftTurn:
case SegmentType.RightTurn:
// return quarter of circumference.
return 0.5f * Mathf.PI * Radius;
}
return 1f;
}
}
private void Awake()
{
Assert.IsNotNull(_straight);
Assert.IsNotNull(_leftTurn);
Assert.IsNotNull(_rightTurn);
}
/// <summary>
/// Updates pose given distance into segment. While this mutates a value,
/// it avoids generating a new object.
/// </summary>
public void UpdatePose(float distanceIntoSegment, Pose pose)
{
if (Type == SegmentType.Straight)
{
pose.Position = transform.position + distanceIntoSegment * transform.forward;
pose.Rotation = transform.rotation;
}
else if (Type == SegmentType.LeftTurn)
{
float normalizedDistanceIntoSegment = distanceIntoSegment / SegmentLength;
// the turn is 90 degrees, so find out how far we are into it
float angle = 0.5f * Mathf.PI * normalizedDistanceIntoSegment;
// unity is left handed so the rotations go the opposite directions in X for left turns --
// invert that by subtracting by radius. also note the angle negation below
Vector3 localPosition = new Vector3(Radius * Mathf.Cos(angle) - Radius, 0, Radius * Mathf.Sin(angle));
Quaternion localRotation = Quaternion.Euler(0, -angle * Mathf.Rad2Deg, 0);
pose.Position = transform.TransformPoint(localPosition);
pose.Rotation = transform.rotation * localRotation;
}
else if (Type == SegmentType.RightTurn)
{
// when going to right, start from PI (180) and go toward 90
float angle = Mathf.PI - 0.5f * Mathf.PI * distanceIntoSegment / SegmentLength;
// going right means we start at radius distance away, and decrease toward zero
Vector3 localPosition = new Vector3(Radius * Mathf.Cos(angle) + Radius, 0, Radius * Mathf.Sin(angle));
Quaternion localRotation = Quaternion.Euler(0, (Mathf.PI - angle) * Mathf.Rad2Deg, 0);
pose.Position = transform.TransformPoint(localPosition);
pose.Rotation = transform.rotation * localRotation;
}
else
{
pose.Position = Vector3.zero;
pose.Rotation = Quaternion.identity;
}
}
private void Update()
{
// uncomment to debug the track path
//DrawDebugLines();
}
private void OnDisable()
{
Destroy(_mesh);
}
private void DrawDebugLines()
{
for (int i = 1; i < SubDivCount + 1; i++)
{
float len = SegmentLength / SubDivCount;
UpdatePose((i - 1) * len, _p1);
UpdatePose(i * len, _p2);
// right segment from p1 to p2
var halfTrackWidth = 0.5f * _trackWidth;
Debug.DrawLine(_p1.Position + halfTrackWidth * (_p1.Rotation * Vector3.right),
_p2.Position + halfTrackWidth * (_p2.Rotation * Vector3.right));
// left segment from p1 to p2
Debug.DrawLine(_p1.Position - halfTrackWidth * (_p1.Rotation * Vector3.right),
_p2.Position - halfTrackWidth * (_p2.Rotation * Vector3.right));
}
// bottom bound
Debug.DrawLine(transform.position - 0.5f * GridSize * transform.right,
transform.position + 0.5f * GridSize * transform.right, Color.yellow);
// left bound
Debug.DrawLine(transform.position - 0.5f * GridSize * transform.right,
transform.position - 0.5f * GridSize * transform.right + GridSize * transform.forward, Color.yellow);
// right bound
Debug.DrawLine(transform.position + 0.5f * GridSize * transform.right,
transform.position + 0.5f * GridSize * transform.right + GridSize * transform.forward, Color.yellow);
// top bound
Debug.DrawLine(transform.position - 0.5f * GridSize * transform.right +
GridSize * transform.forward, transform.position +
0.5f * GridSize * transform.right + GridSize * transform.forward,
Color.yellow);
}
public void RegenerateTrackAndMesh()
{
if (transform.childCount > 0 && !_mesh)
{
_mesh = transform.GetChild(0).gameObject;
}
if (_mesh)
{
DestroyImmediate(_mesh);
}
if (_segmentType == SegmentType.LeftTurn)
{
_mesh = Instantiate(_leftTurn.gameObject);
}
else if (_segmentType == SegmentType.RightTurn)
{
_mesh = Instantiate(_rightTurn.gameObject);
}
else
{
_mesh = Instantiate(_straight.gameObject);
}
_mesh.transform.SetParent(transform, false);
_mesh.transform.position += GridSize / 2.0f * transform.forward;
_mesh.transform.localScale = new Vector3(GridSize / _originalGridSize, GridSize / _originalGridSize,
GridSize / _originalGridSize);
}
}
}