/Assets/Tools/Octave3D World Builder/Scripts/Camera/View Volume/CameraViewVolume.cs

https://bitbucket.org/Jackie0100/abovequantum · C# · 161 lines · 84 code · 19 blank · 58 comment · 1 complexity · 56354fe18b6bbfc3294b5990ba5d49ea MD5 · raw file

  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. namespace O3DWB
  5. {
  6. public class CameraViewVolume
  7. {
  8. #region Private Variables
  9. /// <summary>
  10. /// Holds the camera view volume points in world space. This array can be accessed
  11. /// using members of the 'CameraViewVolumePoint' as indices.
  12. /// </summary>
  13. private Vector3[] _worldSpaceVolumePoints;
  14. private Box _worldSpaceAABB;
  15. /// <summary>
  16. /// This array holds the view volume's planes in world space. The elements in this array
  17. /// can be accessed using members of the 'CameraViewVolumePlane' enum as indices. The
  18. /// planes are stored in the following order: left, right, bottom, top, near, far. All
  19. /// planes are pointing inside the volume.
  20. /// </summary>
  21. private Plane[] _worldSpacePlanes;
  22. /// <summary>
  23. /// Holds a collection of rays which unite the view volume points. For example, one of these
  24. /// rays could be the ray which starts from the top left point on the camera near plane and
  25. /// aims towards the camera top left far clip plane point.
  26. /// </summary>
  27. private Ray3D[] _worldSpaceVolumeEdgeRays;
  28. private float _farClipPlaneDistance;
  29. private float _nearClipPlaneDistance;
  30. #endregion
  31. #region Public Properties
  32. public Vector3[] WorldSpaceVolumePoints { get { return _worldSpaceVolumePoints.Clone() as Vector3[]; } }
  33. public Ray3D[] WorldSpaceVolumeEdgeRays { get { return _worldSpaceVolumeEdgeRays.Clone() as Ray3D[]; } }
  34. public Vector3 TopLeftPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopLeftOnNearPlane]; } }
  35. public Vector3 TopRightPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopRightOnNearPlane]; } }
  36. public Vector3 BottomRightPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomRightOnNearPlane]; } }
  37. public Vector3 BottomLeftPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomLeftOnNearPlane]; } }
  38. public Vector3 TopLeftPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopLeftOnFarPlane]; } }
  39. public Vector3 TopRightPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopRightOnFarPlane]; } }
  40. public Vector3 BottomRightPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomRightOnFarPlane]; } }
  41. public Vector3 BottomLeftPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomLeftOnFarPlane]; } }
  42. public float FarClipPlaneDistance { get { return _farClipPlaneDistance; } }
  43. public float NearClipPlaneDistance { get { return _nearClipPlaneDistance; } }
  44. public Box WorldSpaceAABB { get { return _worldSpaceAABB; } }
  45. #endregion
  46. #region Constructors
  47. public CameraViewVolume()
  48. {
  49. }
  50. /// <summary>
  51. /// Constructor.
  52. /// </summary>
  53. /// <param name="camera">
  54. /// The camera whose view volume data is necessary to construct the 'CameraViewVolume' instance.
  55. /// </param>
  56. /// <param name="desiredCameraFarClipPlane">
  57. /// This can be used to in cases when it's useful to have a view volume that has a smaller or bigger
  58. /// far clip plane distance. This value will override the actual camera far clip plane distance and the
  59. /// view volume will be constructed using this value instead. Note that the far clip plane distance for
  60. /// 'camera' will not be modified.
  61. /// </param>
  62. public CameraViewVolume(Camera camera, float desiredCameraFarClipPlane)
  63. {
  64. BuildForCamera(camera, desiredCameraFarClipPlane);
  65. }
  66. #endregion
  67. #region Public Methods
  68. /// <summary>
  69. /// Builds the camera view volume for the specified camera. Please see the comments for the
  70. /// class constructor in order to understand what the second parameter is about.
  71. /// </summary>
  72. public void BuildForCamera(Camera camera, float desiredCameraFarClipPlane)
  73. {
  74. // Store the old camera far clip plane distance. We need to do this because we will
  75. // temporarily modify the camera far clip plane to 'desiredCameraFarClipPlane' in order
  76. // to perform all the necessary calculations.
  77. float oldCameraFarClipPlane = camera.farClipPlane;
  78. AdjustCameraFarClipPlane(camera, desiredCameraFarClipPlane);
  79. // Calculate the view volume data
  80. CalculateWorldSpacePoints(camera);
  81. CalculateWorldSpacePlanes(camera);
  82. CalculateWorldSpaceVolumeEdgeRays();
  83. // Restore the camera far clip plane to what it was before
  84. camera.farClipPlane = oldCameraFarClipPlane;
  85. // Store clip plane distances
  86. _farClipPlaneDistance = desiredCameraFarClipPlane;
  87. _nearClipPlaneDistance = camera.nearClipPlane;
  88. _worldSpaceAABB = Box.FromPoints(new List<Vector3>(_worldSpaceVolumePoints));
  89. }
  90. public bool ContainsWorldSpaceAABB(Bounds worldSpaceAABB)
  91. {
  92. return GeometryUtility.TestPlanesAABB(_worldSpacePlanes, worldSpaceAABB);
  93. }
  94. #endregion
  95. #region Private Methods
  96. /// <summary>
  97. /// Calculates the view volume world space points using the specified camera.
  98. /// </summary>
  99. private void CalculateWorldSpacePoints(Camera camera)
  100. {
  101. CameraViewVolumePointsCalculator volumePointsCalculator = CameraViewVolumePointsCalculatorFactory.Create(camera);
  102. _worldSpaceVolumePoints = volumePointsCalculator.CalculateWorldSpaceVolumePoints(camera);
  103. }
  104. /// <summary>
  105. /// Calculates the view volume world space planes using the specified camera.
  106. /// </summary>
  107. private void CalculateWorldSpacePlanes(Camera camera)
  108. {
  109. _worldSpacePlanes = GeometryUtility.CalculateFrustumPlanes(camera);
  110. }
  111. /// <summary>
  112. /// Calculates the view volume world space edge rays.
  113. /// </summary>
  114. private void CalculateWorldSpaceVolumeEdgeRays()
  115. {
  116. _worldSpaceVolumeEdgeRays = CameraViewVolumeEdgeRaysCalculator.CalculateWorldSpaceVolumeEdgeRays(this);
  117. }
  118. /// <summary>
  119. /// Adjusts the far clip plane distance of 'camera' to 'desiredFarClipPlane'.
  120. /// </summary>
  121. /// <remarks>
  122. /// The method will ensure that the far clip plane always sits in front of the
  123. /// near plane.
  124. /// </remarks>
  125. private void AdjustCameraFarClipPlane(Camera camera, float desiredFarClipPlane)
  126. {
  127. // Set the far clip plane distance and make sure it sits in front of the near plane.
  128. camera.farClipPlane = desiredFarClipPlane;
  129. EnsureFarClipPlaneSitsInFrontOfNearPlane(camera);
  130. }
  131. /// <summary>
  132. /// Ensures the the far clip plane of 'camera' always sits in front of the
  133. /// camera's near plane.
  134. /// </summary>
  135. private void EnsureFarClipPlaneSitsInFrontOfNearPlane(Camera camera)
  136. {
  137. if (camera.farClipPlane <= camera.nearClipPlane) camera.farClipPlane = camera.nearClipPlane + 0.1f;
  138. }
  139. #endregion
  140. }
  141. }
  142. #endif