|
|
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Draws different sized room-scale play areas for targeting content
- //
- //=============================================================================
-
- using UnityEngine;
- using UnityEngine.Rendering;
- using System.Collections;
- using Valve.VR;
-
- [ExecuteInEditMode, RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
- public class SteamVR_PlayArea : MonoBehaviour
- {
- public float borderThickness = 0.15f;
- public float wireframeHeight = 2.0f;
- public bool drawWireframeWhenSelectedOnly = false;
- public bool drawInGame = true;
-
- public enum Size
- {
- Calibrated,
- _400x300,
- _300x225,
- _200x150
- }
-
- public Size size;
- public Color color = Color.cyan;
-
- [HideInInspector]
- public Vector3[] vertices;
-
- public static bool GetBounds( Size size, ref HmdQuad_t pRect )
- {
- if (size == Size.Calibrated)
- {
- var initOpenVR = (!SteamVR.active && !SteamVR.usingNativeSupport);
- if (initOpenVR)
- {
- var error = EVRInitError.None;
- OpenVR.Init(ref error, EVRApplicationType.VRApplication_Utility);
- }
-
- var chaperone = OpenVR.Chaperone;
- bool success = (chaperone != null) && chaperone.GetPlayAreaRect(ref pRect);
- if (!success)
- Debug.LogWarning("Failed to get Calibrated Play Area bounds! Make sure you have tracking first, and that your space is calibrated.");
-
- if (initOpenVR)
- OpenVR.Shutdown();
-
- return success;
- }
- else
- {
- try
- {
- var str = size.ToString().Substring(1);
- var arr = str.Split(new char[] {'x'}, 2);
-
- // convert to half size in meters (from cm)
- var x = float.Parse(arr[0]) / 200;
- var z = float.Parse(arr[1]) / 200;
-
- pRect.vCorners0.v0 = x;
- pRect.vCorners0.v1 = 0;
- pRect.vCorners0.v2 = -z;
-
- pRect.vCorners1.v0 = -x;
- pRect.vCorners1.v1 = 0;
- pRect.vCorners1.v2 = -z;
-
- pRect.vCorners2.v0 = -x;
- pRect.vCorners2.v1 = 0;
- pRect.vCorners2.v2 = z;
-
- pRect.vCorners3.v0 = x;
- pRect.vCorners3.v1 = 0;
- pRect.vCorners3.v2 = z;
-
- return true;
- }
- catch {}
- }
-
- return false;
- }
-
- public void BuildMesh()
- {
- var rect = new HmdQuad_t();
- if ( !GetBounds( size, ref rect ) )
- return;
-
- var corners = new HmdVector3_t[] { rect.vCorners0, rect.vCorners1, rect.vCorners2, rect.vCorners3 };
-
- vertices = new Vector3[corners.Length * 2];
- for (int i = 0; i < corners.Length; i++)
- {
- var c = corners[i];
- vertices[i] = new Vector3(c.v0, 0.01f, c.v2);
- }
-
- if (borderThickness == 0.0f)
- {
- GetComponent<MeshFilter>().mesh = null;
- return;
- }
-
- for (int i = 0; i < corners.Length; i++)
- {
- int next = (i + 1) % corners.Length;
- int prev = (i + corners.Length - 1) % corners.Length;
-
- var nextSegment = (vertices[next] - vertices[i]).normalized;
- var prevSegment = (vertices[prev] - vertices[i]).normalized;
-
- var vert = vertices[i];
- vert += Vector3.Cross(nextSegment, Vector3.up) * borderThickness;
- vert += Vector3.Cross(prevSegment, Vector3.down) * borderThickness;
-
- vertices[corners.Length + i] = vert;
- }
-
- var triangles = new int[]
- {
- 0, 4, 1,
- 1, 4, 5,
- 1, 5, 2,
- 2, 5, 6,
- 2, 6, 3,
- 3, 6, 7,
- 3, 7, 0,
- 0, 7, 4
- };
-
- var uv = new Vector2[]
- {
- new Vector2(0.0f, 0.0f),
- new Vector2(1.0f, 0.0f),
- new Vector2(0.0f, 0.0f),
- new Vector2(1.0f, 0.0f),
- new Vector2(0.0f, 1.0f),
- new Vector2(1.0f, 1.0f),
- new Vector2(0.0f, 1.0f),
- new Vector2(1.0f, 1.0f)
- };
-
- var colors = new Color[]
- {
- color,
- color,
- color,
- color,
- new Color(color.r, color.g, color.b, 0.0f),
- new Color(color.r, color.g, color.b, 0.0f),
- new Color(color.r, color.g, color.b, 0.0f),
- new Color(color.r, color.g, color.b, 0.0f)
- };
-
- var mesh = new Mesh();
- GetComponent<MeshFilter>().mesh = mesh;
- mesh.vertices = vertices;
- mesh.uv = uv;
- mesh.colors = colors;
- mesh.triangles = triangles;
-
- var renderer = GetComponent<MeshRenderer>();
- renderer.material = new Material(Shader.Find("Sprites/Default"));
- renderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
- renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
- renderer.receiveShadows = false;
- renderer.lightProbeUsage = LightProbeUsage.Off;
- }
-
- #if UNITY_EDITOR
- Hashtable values;
- void Update()
- {
- if (!Application.isPlaying)
- {
- var fields = GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
-
- bool rebuild = false;
-
- if (values == null || (borderThickness != 0.0f && GetComponent<MeshFilter>().sharedMesh == null))
- {
- rebuild = true;
- }
- else
- {
- foreach (var f in fields)
- {
- if (!values.Contains(f) || !f.GetValue(this).Equals(values[f]))
- {
- rebuild = true;
- break;
- }
- }
- }
-
- if (rebuild)
- {
- BuildMesh();
-
- values = new Hashtable();
- foreach (var f in fields)
- values[f] = f.GetValue(this);
- }
- }
- }
- #endif
-
- void OnDrawGizmos()
- {
- if (!drawWireframeWhenSelectedOnly)
- DrawWireframe();
- }
-
- void OnDrawGizmosSelected()
- {
- if (drawWireframeWhenSelectedOnly)
- DrawWireframe();
- }
-
- public void DrawWireframe()
- {
- if (vertices == null || vertices.Length == 0)
- return;
-
- var offset = transform.TransformVector(Vector3.up * wireframeHeight);
- for (int i = 0; i < 4; i++)
- {
- int next = (i + 1) % 4;
-
- var a = transform.TransformPoint(vertices[i]);
- var b = a + offset;
- var c = transform.TransformPoint(vertices[next]);
- var d = c + offset;
- Gizmos.DrawLine(a, b);
- Gizmos.DrawLine(a, c);
- Gizmos.DrawLine(b, d);
- }
- }
-
- public void OnEnable()
- {
- if (Application.isPlaying)
- {
- GetComponent<MeshRenderer>().enabled = drawInGame;
-
- // No need to remain enabled at runtime.
- // Anyone that wants to change properties at runtime
- // should call BuildMesh themselves.
- enabled = false;
-
- // If we want the configured bounds of the user,
- // we need to wait for tracking.
- if (drawInGame && size == Size.Calibrated)
- StartCoroutine(UpdateBounds());
- }
- }
-
- IEnumerator UpdateBounds()
- {
- GetComponent<MeshFilter>().mesh = null; // clear existing
-
- var chaperone = OpenVR.Chaperone;
- if (chaperone == null)
- yield break;
-
- while (chaperone.GetCalibrationState() != ChaperoneCalibrationState.OK)
- yield return null;
-
- BuildMesh();
- }
- }
-
|