SteamVR_Frustum.cs 6.0 KB

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