Created
April 26, 2017 01:49
-
-
Save mnstrspeed/4d30d7f7efe3135265b64a9eef2ef86f to your computer and use it in GitHub Desktop.
Implementation of rectangular gain locomotion (originally described in this talk at Vision Summit 2016: https://www.youtube.com/watch?v=At_Zac4Xezw)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
public class RectangularGainLocomotion : MonoBehaviour | |
{ | |
public Transform Head; | |
public float Gain = 1f; | |
public Vector2 NeutralAreaSize = Vector2.one; | |
[Header("Visual helpers")] | |
public Transform NeutralAreaPreview; | |
public Transform HeadFloorPreview; | |
private Vector2 halfNeutralAreaSize | |
{ | |
get { return this.NeutralAreaSize * 0.5f; } | |
} | |
private Vector3 neutralAreaPosition; | |
void OnEnable() | |
{ | |
this.neutralAreaPosition = this.transform.InverseTransformPoint(this.Head.position); | |
this.neutralAreaPosition.y = 0f; | |
this.HeadFloorPreview.gameObject.SetActive(true); | |
this.NeutralAreaPreview.gameObject.SetActive(true); | |
this.NeutralAreaPreview.localScale = new Vector3(this.NeutralAreaSize.x, 1, this.NeutralAreaSize.y); | |
} | |
void OnDisable() | |
{ | |
this.HeadFloorPreview.gameObject.SetActive(false); | |
this.NeutralAreaPreview.gameObject.SetActive(false); | |
} | |
void Update() | |
{ | |
Vector3 localPlayerPosition = this.transform.InverseTransformPoint(this.Head.position); | |
Vector3 floorPosition = new Vector3(localPlayerPosition.x, 0f, localPlayerPosition.z); | |
Vector3 positionInNeutralZone = floorPosition - this.neutralAreaPosition; | |
if (Mathf.Abs(positionInNeutralZone.x) > this.halfNeutralAreaSize.x) | |
{ | |
this.neutralAreaPosition.x += | |
Mathf.Sign(positionInNeutralZone.x) * Mathf.Abs(Mathf.Abs(positionInNeutralZone.x) - this.halfNeutralAreaSize.x); | |
} | |
if (Mathf.Abs(positionInNeutralZone.z) > this.halfNeutralAreaSize.y) | |
{ | |
this.neutralAreaPosition.z += | |
Mathf.Sign(positionInNeutralZone.z) * Mathf.Abs(Mathf.Abs(positionInNeutralZone.z) - this.halfNeutralAreaSize.y); | |
} | |
this.transform.localPosition = this.Gain * this.neutralAreaPosition; | |
this.NeutralAreaPreview.localPosition = this.neutralAreaPosition; | |
this.HeadFloorPreview.localPosition = floorPosition; | |
} | |
#region Debug visualization | |
void OnDrawGizmos() | |
{ | |
if (!this.isActiveAndEnabled) | |
return; | |
this.DrawNeutralAreaDebug(); | |
var playArea = this.GetComponent<SteamVR_PlayArea>(); | |
if (playArea != null) | |
{ | |
Gizmos.color = Color.green; | |
this.DrawWireframe(playArea.vertices); | |
} | |
} | |
private void DrawWireframe(Vector3[] vertices) | |
{ | |
if (vertices == null || vertices.Length == 0) | |
return; | |
var offset = transform.TransformVector(Vector3.up * 2f); | |
for (int i = 0; i < 4; i++) | |
{ | |
int next = (i + 1) % 4; | |
var a = vertices[i] + new Vector3( | |
vertices[i].x - Mathf.Sign(vertices[i].x) * this.halfNeutralAreaSize.x, 0, | |
vertices[i].z - Mathf.Sign(vertices[i].z) * this.halfNeutralAreaSize.y) * this.Gain; | |
var b = a + offset; | |
var c = vertices[next] + new Vector3( | |
vertices[next].x - Mathf.Sign(vertices[next].x) * this.halfNeutralAreaSize.x, 0, | |
vertices[next].z - Mathf.Sign(vertices[next].z) * this.halfNeutralAreaSize.y) * this.Gain; | |
var d = c + offset; | |
Gizmos.DrawLine(a, b); | |
Gizmos.DrawLine(a, c); | |
Gizmos.DrawLine(b, d); | |
} | |
} | |
private void DrawNeutralAreaDebug() | |
{ | |
Vector3[] vertices = new Vector3[] | |
{ | |
this.neutralAreaPosition + new Vector3(-this.halfNeutralAreaSize.x, 0, this.halfNeutralAreaSize.y), | |
this.neutralAreaPosition + new Vector3(this.halfNeutralAreaSize.x, 0, this.halfNeutralAreaSize.y), | |
this.neutralAreaPosition + new Vector3(this.halfNeutralAreaSize.x, 0, -this.halfNeutralAreaSize.y), | |
this.neutralAreaPosition + new Vector3(-this.halfNeutralAreaSize.x, 0, -this.halfNeutralAreaSize.y), | |
}; | |
for (int i = 0; i < vertices.Length; i++) | |
{ | |
Vector3 p1 = this.transform.TransformPoint(vertices[i]); | |
Vector3 p2 = this.transform.TransformPoint(vertices[(i + 1) % vertices.Length]); | |
Debug.DrawLine(p1, p2); | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment