NxrCameraUtils.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // Copyright 2016 Nibiru. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. using UnityEngine;
  15. //Utility class that includes functions for calculating camera properties.
  16. namespace Nxr.Internal
  17. {
  18. public class NxrCameraUtils
  19. {
  20. public static void FixProjection(Rect camRect, float nearClipPlane, float farClipPlane,
  21. ref Matrix4x4 proj)
  22. {
  23. // Adjust for non-fullscreen camera. NxrViewer assumes fullscreen,
  24. // so the aspect ratio might not match.
  25. proj[0, 0] *= camRect.height / camRect.width / 2;
  26. // NxrViewer had to pass "nominal" values of near/far to the native layer, which
  27. // we fix here to match our mono camera's specific values.
  28. proj[2, 2] = (nearClipPlane + farClipPlane) / (nearClipPlane - farClipPlane);
  29. proj[2, 3] = 2 * nearClipPlane * farClipPlane / (nearClipPlane - farClipPlane);
  30. }
  31. public static Rect FixViewport(Rect rect, Rect viewport, bool isRightEye)
  32. {
  33. // We are rendering straight to the screen. Use the reported rect that is visible
  34. // through the device's lenses.
  35. if (isRightEye)
  36. {
  37. rect.x -= 0.5f;
  38. }
  39. rect.width *= 2 * viewport.width;
  40. rect.x = viewport.x + 2 * rect.x * viewport.width;
  41. rect.height *= viewport.height;
  42. rect.y = viewport.y + rect.y * viewport.height;
  43. return rect;
  44. }
  45. public static Rect FixEditorViewport(Rect rect, float profileAspect, float windowAspect)
  46. {
  47. float aspectComparison = profileAspect / windowAspect;
  48. if (aspectComparison < 1)
  49. {
  50. rect.width *= aspectComparison;
  51. rect.x *= aspectComparison;
  52. rect.x += (1 - aspectComparison) / 2;
  53. }
  54. else
  55. {
  56. rect.height /= aspectComparison;
  57. rect.y /= aspectComparison;
  58. }
  59. return rect;
  60. }
  61. public static void ZoomStereoCameras(float matchByZoom, float matchMonoFOV, float monoProj11,
  62. ref Matrix4x4 proj)
  63. {
  64. float lerp = Mathf.Clamp01(matchByZoom) * Mathf.Clamp01(matchMonoFOV);
  65. // Lerping the reciprocal of proj(1,1), so zoom is linear in frustum height not the depth.
  66. float zoom = 1 / Mathf.Lerp(1 / proj[1, 1], 1 / monoProj11, lerp) / proj[1, 1];
  67. proj[0, 0] *= zoom;
  68. proj[1, 1] *= zoom;
  69. }
  70. //旋转矩阵转换成四元数
  71. //RotationMatrix to Quaternion
  72. public static void RotationMatrix_to_Quaternion(ref float[] quaternion, float[] r)
  73. {
  74. quaternion = new float[4] { 0, 0, 0, 0 };
  75. //探测四元数中最大的项
  76. float fourWSquaredMinusl = r[0] + r[4] + r[8];
  77. float fourXSquaredMinusl = r[0] - r[4] - r[8];
  78. float fourYSquaredMinusl = r[4] - r[0] - r[8];
  79. float fourZSquaredMinusl = r[8] - r[0] - r[4];
  80. int biggestIndex = 0;
  81. float fourBiggestSqureMinus1 = fourWSquaredMinusl;
  82. if (fourXSquaredMinusl > fourBiggestSqureMinus1)
  83. {
  84. fourBiggestSqureMinus1 = fourXSquaredMinusl;
  85. biggestIndex = 1;
  86. }
  87. if (fourYSquaredMinusl > fourBiggestSqureMinus1)
  88. {
  89. fourBiggestSqureMinus1 = fourYSquaredMinusl;
  90. biggestIndex = 2;
  91. }
  92. if (fourZSquaredMinusl > fourBiggestSqureMinus1)
  93. {
  94. fourBiggestSqureMinus1 = fourZSquaredMinusl;
  95. biggestIndex = 3;
  96. }
  97. //计算平方根和除法
  98. float biggestVal = Mathf.Sqrt(fourBiggestSqureMinus1 + 1.0f) * 0.5f;
  99. float mult = 0.25f / biggestVal;
  100. //计算四元数的值
  101. switch (biggestIndex)
  102. {
  103. case 0:
  104. quaternion[3] = biggestVal;
  105. quaternion[0] = (r[5] - r[7]) * mult;
  106. quaternion[1] = (r[6] - r[2]) * mult;
  107. quaternion[2] = (r[1] - r[3]) * mult;
  108. break;
  109. case 1:
  110. quaternion[0] = biggestVal;
  111. quaternion[3] = (r[5] - r[7]) * mult;
  112. quaternion[1] = (r[1] + r[3]) * mult;
  113. quaternion[2] = (r[6] + r[2]) * mult;
  114. break;
  115. case 2:
  116. quaternion[1] = biggestVal;
  117. quaternion[3] = (r[6] - r[2]) * mult;
  118. quaternion[0] = (r[1] + r[3]) * mult;
  119. quaternion[2] = (r[5] + r[7]) * mult;
  120. break;
  121. case 3:
  122. quaternion[2] = biggestVal;
  123. quaternion[3] = (r[1] - r[3]) * mult;
  124. quaternion[0] = (r[6] + r[2]) * mult;
  125. quaternion[1] = (r[5] + r[7]) * mult;
  126. break;
  127. }
  128. }
  129. //旋转矩阵转换成欧拉角
  130. /// <summary>
  131. ///
  132. /// </summary>
  133. /// <param name="eulerAngle"></param>
  134. /// <param name="rm">3X3</param>
  135. public static void RotationMatrixToEulerAngles(ref float[] eulerAngle, float[] rm)
  136. {
  137. float sy = Mathf.Sqrt(rm[0] * rm[0] + rm[3] * rm[3]);
  138. bool singular = sy < 1e-6; // If
  139. float x, y, z;
  140. if (!singular)
  141. {
  142. x = Mathf.Atan2(rm[7], rm[8]);
  143. y = Mathf.Atan2(-rm[6], sy);
  144. z = Mathf.Atan2(rm[3], rm[0]);
  145. }
  146. else
  147. {
  148. x = Mathf.Atan2(-rm[5], rm[4]);
  149. y = Mathf.Atan2(-rm[6], sy);
  150. z = 0;
  151. }
  152. x = x * 180.0f / Mathf.PI;
  153. y = y * 180.0f / Mathf.PI;
  154. z = z * 180.0f / Mathf.PI;
  155. eulerAngle = new float[3] { x, y, z };
  156. }
  157. }
  158. }