#if UNITY_EDITOR using UnityEngine; using System.Collections.Generic; namespace O3DWB { public class CameraViewVolume { #region Private Variables /// /// Holds the camera view volume points in world space. This array can be accessed /// using members of the 'CameraViewVolumePoint' as indices. /// private Vector3[] _worldSpaceVolumePoints; private Box _worldSpaceAABB; /// /// This array holds the view volume's planes in world space. The elements in this array /// can be accessed using members of the 'CameraViewVolumePlane' enum as indices. The /// planes are stored in the following order: left, right, bottom, top, near, far. All /// planes are pointing inside the volume. /// private Plane[] _worldSpacePlanes; /// /// Holds a collection of rays which unite the view volume points. For example, one of these /// rays could be the ray which starts from the top left point on the camera near plane and /// aims towards the camera top left far clip plane point. /// private Ray3D[] _worldSpaceVolumeEdgeRays; private float _farClipPlaneDistance; private float _nearClipPlaneDistance; #endregion #region Public Properties public Vector3[] WorldSpaceVolumePoints { get { return _worldSpaceVolumePoints.Clone() as Vector3[]; } } public Ray3D[] WorldSpaceVolumeEdgeRays { get { return _worldSpaceVolumeEdgeRays.Clone() as Ray3D[]; } } public Vector3 TopLeftPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopLeftOnNearPlane]; } } public Vector3 TopRightPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopRightOnNearPlane]; } } public Vector3 BottomRightPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomRightOnNearPlane]; } } public Vector3 BottomLeftPointOnNearPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomLeftOnNearPlane]; } } public Vector3 TopLeftPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopLeftOnFarPlane]; } } public Vector3 TopRightPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.TopRightOnFarPlane]; } } public Vector3 BottomRightPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomRightOnFarPlane]; } } public Vector3 BottomLeftPointOnFarPlane { get { return _worldSpaceVolumePoints[(int)CameraViewVolumePoint.BottomLeftOnFarPlane]; } } public float FarClipPlaneDistance { get { return _farClipPlaneDistance; } } public float NearClipPlaneDistance { get { return _nearClipPlaneDistance; } } public Box WorldSpaceAABB { get { return _worldSpaceAABB; } } #endregion #region Constructors public CameraViewVolume() { } /// /// Constructor. /// /// /// The camera whose view volume data is necessary to construct the 'CameraViewVolume' instance. /// /// /// This can be used to in cases when it's useful to have a view volume that has a smaller or bigger /// far clip plane distance. This value will override the actual camera far clip plane distance and the /// view volume will be constructed using this value instead. Note that the far clip plane distance for /// 'camera' will not be modified. /// public CameraViewVolume(Camera camera, float desiredCameraFarClipPlane) { BuildForCamera(camera, desiredCameraFarClipPlane); } #endregion #region Public Methods /// /// Builds the camera view volume for the specified camera. Please see the comments for the /// class constructor in order to understand what the second parameter is about. /// public void BuildForCamera(Camera camera, float desiredCameraFarClipPlane) { // Store the old camera far clip plane distance. We need to do this because we will // temporarily modify the camera far clip plane to 'desiredCameraFarClipPlane' in order // to perform all the necessary calculations. float oldCameraFarClipPlane = camera.farClipPlane; AdjustCameraFarClipPlane(camera, desiredCameraFarClipPlane); // Calculate the view volume data CalculateWorldSpacePoints(camera); CalculateWorldSpacePlanes(camera); CalculateWorldSpaceVolumeEdgeRays(); // Restore the camera far clip plane to what it was before camera.farClipPlane = oldCameraFarClipPlane; // Store clip plane distances _farClipPlaneDistance = desiredCameraFarClipPlane; _nearClipPlaneDistance = camera.nearClipPlane; _worldSpaceAABB = Box.FromPoints(new List(_worldSpaceVolumePoints)); } public bool ContainsWorldSpaceAABB(Bounds worldSpaceAABB) { return GeometryUtility.TestPlanesAABB(_worldSpacePlanes, worldSpaceAABB); } #endregion #region Private Methods /// /// Calculates the view volume world space points using the specified camera. /// private void CalculateWorldSpacePoints(Camera camera) { CameraViewVolumePointsCalculator volumePointsCalculator = CameraViewVolumePointsCalculatorFactory.Create(camera); _worldSpaceVolumePoints = volumePointsCalculator.CalculateWorldSpaceVolumePoints(camera); } /// /// Calculates the view volume world space planes using the specified camera. /// private void CalculateWorldSpacePlanes(Camera camera) { _worldSpacePlanes = GeometryUtility.CalculateFrustumPlanes(camera); } /// /// Calculates the view volume world space edge rays. /// private void CalculateWorldSpaceVolumeEdgeRays() { _worldSpaceVolumeEdgeRays = CameraViewVolumeEdgeRaysCalculator.CalculateWorldSpaceVolumeEdgeRays(this); } /// /// Adjusts the far clip plane distance of 'camera' to 'desiredFarClipPlane'. /// /// /// The method will ensure that the far clip plane always sits in front of the /// near plane. /// private void AdjustCameraFarClipPlane(Camera camera, float desiredFarClipPlane) { // Set the far clip plane distance and make sure it sits in front of the near plane. camera.farClipPlane = desiredFarClipPlane; EnsureFarClipPlaneSitsInFrontOfNearPlane(camera); } /// /// Ensures the the far clip plane of 'camera' always sits in front of the /// camera's near plane. /// private void EnsureFarClipPlaneSitsInFrontOfNearPlane(Camera camera) { if (camera.farClipPlane <= camera.nearClipPlane) camera.farClipPlane = camera.nearClipPlane + 0.1f; } #endregion } } #endif