SteamVR_Frustum.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Generates a mesh based on field of view.
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using Valve.VR;
  8. [ExecuteInEditMode, RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
  9. public class SteamVR_Frustum : MonoBehaviour
  10. {
  11. public SteamVR_TrackedObject.EIndex index;
  12. public float fovLeft = 45, fovRight = 45, fovTop = 45, fovBottom = 45, nearZ = 0.5f, farZ = 2.5f;
  13. public void UpdateModel()
  14. {
  15. fovLeft = Mathf.Clamp(fovLeft, 1, 89);
  16. fovRight = Mathf.Clamp(fovRight, 1, 89);
  17. fovTop = Mathf.Clamp(fovTop, 1, 89);
  18. fovBottom = Mathf.Clamp(fovBottom, 1, 89);
  19. farZ = Mathf.Max(farZ, nearZ + 0.01f);
  20. nearZ = Mathf.Clamp(nearZ, 0.01f, farZ - 0.01f);
  21. var lsin = Mathf.Sin(-fovLeft * Mathf.Deg2Rad);
  22. var rsin = Mathf.Sin(fovRight * Mathf.Deg2Rad);
  23. var tsin = Mathf.Sin(fovTop * Mathf.Deg2Rad);
  24. var bsin = Mathf.Sin(-fovBottom * Mathf.Deg2Rad);
  25. var lcos = Mathf.Cos(-fovLeft * Mathf.Deg2Rad);
  26. var rcos = Mathf.Cos(fovRight * Mathf.Deg2Rad);
  27. var tcos = Mathf.Cos(fovTop * Mathf.Deg2Rad);
  28. var bcos = Mathf.Cos(-fovBottom * Mathf.Deg2Rad);
  29. var corners = new Vector3[] {
  30. new Vector3(lsin * nearZ / lcos, tsin * nearZ / tcos, nearZ), //tln
  31. new Vector3(rsin * nearZ / rcos, tsin * nearZ / tcos, nearZ), //trn
  32. new Vector3(rsin * nearZ / rcos, bsin * nearZ / bcos, nearZ), //brn
  33. new Vector3(lsin * nearZ / lcos, bsin * nearZ / bcos, nearZ), //bln
  34. new Vector3(lsin * farZ / lcos, tsin * farZ / tcos, farZ ), //tlf
  35. new Vector3(rsin * farZ / rcos, tsin * farZ / tcos, farZ ), //trf
  36. new Vector3(rsin * farZ / rcos, bsin * farZ / bcos, farZ ), //brf
  37. new Vector3(lsin * farZ / lcos, bsin * farZ / bcos, farZ ), //blf
  38. };
  39. var triangles = new int[] {
  40. // 0, 1, 2, 0, 2, 3, // near
  41. // 0, 2, 1, 0, 3, 2, // near
  42. // 4, 5, 6, 4, 6, 7, // far
  43. // 4, 6, 5, 4, 7, 6, // far
  44. 0, 4, 7, 0, 7, 3, // left
  45. 0, 7, 4, 0, 3, 7, // left
  46. 1, 5, 6, 1, 6, 2, // right
  47. 1, 6, 5, 1, 2, 6, // right
  48. 0, 4, 5, 0, 5, 1, // top
  49. 0, 5, 4, 0, 1, 5, // top
  50. 2, 3, 7, 2, 7, 6, // bottom
  51. 2, 7, 3, 2, 6, 7, // bottom
  52. };
  53. int j = 0;
  54. var vertices = new Vector3[triangles.Length];
  55. var normals = new Vector3[triangles.Length];
  56. for (int i = 0; i < triangles.Length / 3; i++)
  57. {
  58. var a = corners[triangles[i * 3 + 0]];
  59. var b = corners[triangles[i * 3 + 1]];
  60. var c = corners[triangles[i * 3 + 2]];
  61. var n = Vector3.Cross(b - a, c - a).normalized;
  62. normals[i * 3 + 0] = n;
  63. normals[i * 3 + 1] = n;
  64. normals[i * 3 + 2] = n;
  65. vertices[i * 3 + 0] = a;
  66. vertices[i * 3 + 1] = b;
  67. vertices[i * 3 + 2] = c;
  68. triangles[i * 3 + 0] = j++;
  69. triangles[i * 3 + 1] = j++;
  70. triangles[i * 3 + 2] = j++;
  71. }
  72. var mesh = new Mesh();
  73. mesh.vertices = vertices;
  74. mesh.normals = normals;
  75. mesh.triangles = triangles;
  76. GetComponent<MeshFilter>().mesh = mesh;
  77. }
  78. private void OnDeviceConnected(int i, bool connected)
  79. {
  80. if (i != (int)index)
  81. return;
  82. GetComponent<MeshFilter>().mesh = null;
  83. if (connected)
  84. {
  85. var system = OpenVR.System;
  86. if (system != null && system.GetTrackedDeviceClass((uint)i) == ETrackedDeviceClass.TrackingReference)
  87. {
  88. var error = ETrackedPropertyError.TrackedProp_Success;
  89. var result = system.GetFloatTrackedDeviceProperty((uint)i, ETrackedDeviceProperty.Prop_FieldOfViewLeftDegrees_Float, ref error);
  90. if (error == ETrackedPropertyError.TrackedProp_Success)
  91. fovLeft = result;
  92. result = system.GetFloatTrackedDeviceProperty((uint)i, ETrackedDeviceProperty.Prop_FieldOfViewRightDegrees_Float, ref error);
  93. if (error == ETrackedPropertyError.TrackedProp_Success)
  94. fovRight = result;
  95. result = system.GetFloatTrackedDeviceProperty((uint)i, ETrackedDeviceProperty.Prop_FieldOfViewTopDegrees_Float, ref error);
  96. if (error == ETrackedPropertyError.TrackedProp_Success)
  97. fovTop = result;
  98. result = system.GetFloatTrackedDeviceProperty((uint)i, ETrackedDeviceProperty.Prop_FieldOfViewBottomDegrees_Float, ref error);
  99. if (error == ETrackedPropertyError.TrackedProp_Success)
  100. fovBottom = result;
  101. result = system.GetFloatTrackedDeviceProperty((uint)i, ETrackedDeviceProperty.Prop_TrackingRangeMinimumMeters_Float, ref error);
  102. if (error == ETrackedPropertyError.TrackedProp_Success)
  103. nearZ = result;
  104. result = system.GetFloatTrackedDeviceProperty((uint)i, ETrackedDeviceProperty.Prop_TrackingRangeMaximumMeters_Float, ref error);
  105. if (error == ETrackedPropertyError.TrackedProp_Success)
  106. farZ = result;
  107. UpdateModel();
  108. }
  109. }
  110. }
  111. void OnEnable()
  112. {
  113. GetComponent<MeshFilter>().mesh = null;
  114. SteamVR_Events.DeviceConnected.Listen(OnDeviceConnected);
  115. }
  116. void OnDisable()
  117. {
  118. SteamVR_Events.DeviceConnected.Remove(OnDeviceConnected);
  119. GetComponent<MeshFilter>().mesh = null;
  120. }
  121. #if UNITY_EDITOR
  122. void Update()
  123. {
  124. if (!Application.isPlaying)
  125. UpdateModel();
  126. }
  127. #endif
  128. }