You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			278 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			278 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C#
		
	
//======= 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;
 | 
						|
 | 
						|
namespace 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)
 | 
						|
            {
 | 
						|
                bool temporarySession = false;
 | 
						|
                if (Application.isEditor && Application.isPlaying == false)
 | 
						|
                    temporarySession = SteamVR.InitializeTemporarySession();
 | 
						|
 | 
						|
                var chaperone = OpenVR.Chaperone;
 | 
						|
                bool success = (chaperone != null) && chaperone.GetPlayAreaRect(ref pRect);
 | 
						|
                if (!success)
 | 
						|
                    Debug.LogWarning("<b>[SteamVR]</b> Failed to get Calibrated Play Area bounds!  Make sure you have tracking first, and that your space is calibrated.");
 | 
						|
 | 
						|
                if (temporarySession)
 | 
						|
                    SteamVR.ExitTemporarySession();
 | 
						|
 | 
						|
                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();
 | 
						|
        }
 | 
						|
    }
 | 
						|
} |