// ============================================================================= // METHODS STATIC -------------------------------------------------------------- public static void SetVanishingPoint( Camera cam, float offset, ClientCameraScreen screen ) { Transform t = cam.transform; NearPlane plane = new NearPlane(); Vector3 nearCenter = t.position + t.forward*cam.nearClipPlane; Plane nearPlane = new Plane ( -t.forward, nearCenter ); float distance = 0f; Vector3 direction; Ray ray; Vector3 screenTL = t.TransformPoint ( new Vector3 ( ( -screen.Width/2.0f ) + offset, screen.Height/2.0f, screen.Distance ) ); direction = ( screenTL - t.position ).normalized; ray = new Ray ( t.position, direction ); nearPlane.Raycast ( ray, out distance ); Vector3 nearTL = -( t.InverseTransformPoint ( nearCenter ) - t.InverseTransformPoint ( ( t.position + direction*distance ) ) ); Vector3 screenBR = t.TransformPoint ( new Vector3 ( ( screen.Width/2.0f ) + offset, -screen.Height/2.0f, screen.Distance ) ); direction = ( screenBR - t.position ).normalized; ray = new Ray ( t.position, direction ); nearPlane.Raycast ( ray, out distance ); Vector3 nearBR = -( t.InverseTransformPoint ( nearCenter ) - t.InverseTransformPoint ( ( t.position + direction*distance ) ) ); plane.left = nearTL.x; plane.top = nearTL.y; plane.right = nearBR.x; plane.bottom = nearBR.y; plane.near = cam.nearClipPlane; plane.far = cam.farClipPlane; cam.projectionMatrix = PerspectiveOffCenter ( plane ); }
private static Matrix4x4 PerspectiveOffCenter( NearPlane plane ) { float x = ( 2.0f*plane.near )/( plane.right - plane.left ); float y = ( 2.0f*plane.near )/( plane.top - plane.bottom ); float a = ( plane.right + plane.left )/( plane.right - plane.left ); float b = ( plane.top + plane.bottom )/( plane.top - plane.bottom ); float c = -( plane.far + plane.near )/( plane.far - plane.near ); float d = -( 2.0f*plane.far*plane.near )/( plane.far - plane.near ); float e = -1.0f; Matrix4x4 m = new Matrix4x4 (); m[0, 0] = x; m[0, 1] = 0.0f; m[0, 2] = a; m[0, 3] = 0.0f; m[1, 0] = 0.0f; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0.0f; m[2, 0] = 0.0f; m[2, 1] = 0.0f; m[2, 2] = c; m[2, 3] = d; m[3, 0] = 0.0f; m[3, 1] = 0.0f; m[3, 2] = e; m[3, 3] = 0.0f; return m; }
private static Matrix4x4 PerspectiveOffCenter(NearPlane plane) { float x = (2.0f * plane.near) / (plane.right - plane.left); float y = (2.0f * plane.near) / (plane.top - plane.bottom); float a = (plane.right + plane.left) / (plane.right - plane.left); float b = (plane.top + plane.bottom) / (plane.top - plane.bottom); float c = -(plane.far + plane.near) / (plane.far - plane.near); float d = -(2.0f * plane.far * plane.near) / (plane.far - plane.near); float e = -1.0f; Matrix4x4 m = new Matrix4x4(); m[0, 0] = x; m[0, 1] = 0.0f; m[0, 2] = a; m[0, 3] = 0.0f; m[1, 0] = 0.0f; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0.0f; m[2, 0] = 0.0f; m[2, 1] = 0.0f; m[2, 2] = c; m[2, 3] = d; m[3, 0] = 0.0f; m[3, 1] = 0.0f; m[3, 2] = e; m[3, 3] = 0.0f; return(m); }
/// <summary> /// Calculate a projection matrix from a given near plane. /// </summary> /// <param name="np"> /// A <see cref="NearPlane"/> /// The NearPlane that defines the projection. /// </param> /// <returns> /// A <see cref="Matrix4x4"/> /// The projection matrix. /// </returns> Matrix4x4 PerspectiveOffCenter(NearPlane np) { float x = (2.0f * np.near) / (np.right - np.left); float y = (2.0f * np.near) / (np.top - np.bottom); float a = (np.right + np.left) / (np.right - np.left); float b = (np.top + np.bottom) / (np.top - np.bottom); float c = -(np.far + np.near) / (np.far - np.near); float d = -(2.0f * np.far * np.near) / (np.far - np.near); float e = -1.0f; Matrix4x4 m = new Matrix4x4(); m[0, 0] = x; m[0, 1] = 0; m[0, 2] = a; m[0, 3] = 0; m[1, 0] = 0; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0; m[2, 0] = 0; m[2, 1] = 0; m[2, 2] = c; m[2, 3] = d; m[3, 0] = 0; m[3, 1] = 0; m[3, 2] = e; m[3, 3] = 0; return(m); }
// ============================================================================= // METHODS STATIC -------------------------------------------------------------- public static void SetVanishingPoint(Camera cam, float offset, ClientCameraScreen screen) { Transform t = cam.transform; NearPlane plane = new NearPlane(); Vector3 nearCenter = t.position + t.forward * cam.nearClipPlane; Plane nearPlane = new Plane(-t.forward, nearCenter); float distance = 0f; Vector3 direction; Ray ray; Vector3 screenTL = t.TransformPoint(new Vector3((-screen.Width / 2.0f) + offset, screen.Height / 2.0f, screen.Distance)); direction = (screenTL - t.position).normalized; ray = new Ray(t.position, direction); nearPlane.Raycast(ray, out distance); Vector3 nearTL = -(t.InverseTransformPoint(nearCenter) - t.InverseTransformPoint((t.position + direction * distance))); Vector3 screenBR = t.TransformPoint(new Vector3((screen.Width / 2.0f) + offset, -screen.Height / 2.0f, screen.Distance)); direction = (screenBR - t.position).normalized; ray = new Ray(t.position, direction); nearPlane.Raycast(ray, out distance); Vector3 nearBR = -(t.InverseTransformPoint(nearCenter) - t.InverseTransformPoint((t.position + direction * distance))); plane.left = nearTL.x; plane.top = nearTL.y; plane.right = nearBR.x; plane.bottom = nearBR.y; plane.near = cam.nearClipPlane; plane.far = cam.farClipPlane; cam.projectionMatrix = PerspectiveOffCenter(plane); }
void OnPreCull() { //cam = camera; // update screen (if defined) // this must be called manually to ensure the correct order of execution if (screen != null) { screen.SetSize(3.0f, 3.0f); screen.UpdateCorners(); } else { cam.ResetProjectionMatrix(); } // calculate off-center projection if (projectionMode == ProjectionMode.Async || ProjectionMode == ProjectionMode.ObliqueAsync) { NearPlane plane = CalculateNearPlane(screen, cam, transform); mp = PerspectiveOffCenter(plane); } // choose the correct projection matrix switch (projectionMode) { case ProjectionMode.Standard: cam.ResetProjectionMatrix(); // Debug.Log("Standard"); break; case ProjectionMode.Oblique: cam.projectionMatrix = bimberMatrix * origProjMatrix; // Debug.Log("Oblique"); break; case ProjectionMode.Async: cam.projectionMatrix = mp; // Debug.Log("Async"); break; case ProjectionMode.ObliqueAsync: cam.projectionMatrix = bimberMatrix * mp; // Debug.Log("ObliqueAsync"); break; } }
/// <summary> /// Calculate a near plane that defines a projection looking through a virtual window/screen. /// </summary> /// <param name="window"> /// A <see cref="VirtualScreen"/> /// The virtual window the frustum should be locked to. /// </param> /// <param name="cam"> /// A <see cref="Camera"/> /// The camera for which the projection is calculated. /// </param> /// <param name="t"> /// A <see cref="Transform"/> /// /// </param> /// <returns> /// A <see cref="NearPlane"/> /// </returns> NearPlane CalculateNearPlane(VirtualScreen window, Camera cam, Transform t) { Profiler.BeginSample("CalcNearPlane"); // align camera with window t.rotation = window.transform.rotation; // get top left and bottom right coordinates Vector3 wtl = window.tl; Vector3 wbr = window.br; NearPlane plane = new NearPlane(); // construct nearPlane Vector3 nearCenter = t.position + t.forward * cam.nearClipPlane; Plane nearPlane = new Plane(-t.forward, nearCenter); // calculate top left for near plane float dist = 0; Vector3 direction = (wtl - t.position).normalized; Ray ray = new Ray(t.position, direction); nearPlane.Raycast(ray, out dist); Vector3 ntl = -(t.InverseTransformPoint(nearCenter) - t.InverseTransformPoint((t.position + direction * dist))); plane.left = ntl.x; plane.top = ntl.y; // calculate bottom right for near plane direction = (wbr - t.position).normalized; ray = new Ray(t.position, direction); nearPlane.Raycast(ray, out dist); Vector3 nbr = -(t.InverseTransformPoint(nearCenter) - t.InverseTransformPoint((t.position + direction * dist))); plane.right = nbr.x; plane.bottom = nbr.y; plane.near = cam.nearClipPlane; plane.far = cam.farClipPlane; Profiler.EndSample(); return(plane); }
/// <summary> /// Creats a NearPlane based on the given VirtualScreen and transform. /// This function comes from the old CAVE Asset. /// </summary> /// <param name="window">VirtualScreen</param> /// <param name="targetTransform">Transform</param> /// <returns></returns> private NearPlane CalculateNearPlane(VirtualScreen window, Transform targetTransform) { NearPlane nearPlane = new NearPlane(); Vector3 nearCenter = targetTransform.position + targetTransform.forward * cam.nearClipPlane; Plane plane = new Plane(-targetTransform.forward, nearCenter); float distance = 0.0f; Vector3 direction; Ray ray; // calculate top left for nearPlane direction = (window.topLeft - targetTransform.position).normalized; ray = new Ray(targetTransform.position, direction); plane.Raycast(ray, out distance); Vector3 nearTopLeft = -(targetTransform.InverseTransformPoint(nearCenter) - targetTransform.InverseTransformPoint((targetTransform.position + direction * distance))); nearPlane.left = nearTopLeft.x; nearPlane.top = nearTopLeft.y; // calculate bottom right for nearPlane direction = (window.bottomRight - targetTransform.position).normalized; ray = new Ray(targetTransform.position, direction); plane.Raycast(ray, out distance); Vector3 nearBottomRight = -(targetTransform.InverseTransformPoint(nearCenter) - targetTransform.InverseTransformPoint((targetTransform.position + direction * distance))); nearPlane.right = nearBottomRight.x; nearPlane.bottom = nearBottomRight.y; // near and far clipPlane for nearPlane nearPlane.near = cam.nearClipPlane; nearPlane.far = cam.farClipPlane; return(nearPlane); }
/// <summary> /// Calculate a projection matrix from a given near plane. /// </summary> /// <param name="np"> /// A <see cref="NearPlane"/> /// The NearPlane that defines the projection. /// </param> /// <returns> /// A <see cref="Matrix4x4"/> /// The projection matrix. /// </returns> Matrix4x4 PerspectiveOffCenter(NearPlane np) { float x = (2.0f * np.near) / (np.right - np.left); float y = (2.0f * np.near) / (np.top - np.bottom); float a = (np.right + np.left) / (np.right - np.left); float b = (np.top + np.bottom) / (np.top - np.bottom); float c = -(np.far + np.near) / (np.far - np.near); float d = -(2.0f * np.far * np.near) / (np.far - np.near); float e = -1.0f; Matrix4x4 m = new Matrix4x4(); m[0, 0] = x; m[0, 1] = 0; m[0, 2] = a; m[0, 3] = 0; m[1, 0] = 0; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0; m[2, 0] = 0; m[2, 1] = 0; m[2, 2] = c; m[2, 3] = d; m[3, 0] = 0; m[3, 1] = 0; m[3, 2] = e; m[3, 3] = 0; return m; }
/// <summary> /// Calculate a near plane that defines a projection looking through a virtual window/screen. /// </summary> /// <param name="window"> /// A <see cref="VirtualScreen"/> /// The virtual window the frustum should be locked to. /// </param> /// <param name="cam"> /// A <see cref="Camera"/> /// The camera for which the projection is calculated. /// </param> /// <param name="t"> /// A <see cref="Transform"/> /// /// </param> /// <returns> /// A <see cref="NearPlane"/> /// </returns> NearPlane CalculateNearPlane(VirtualScreen window, Camera cam, Transform t) { Profiler.BeginSample("CalcNearPlane"); // align camera with window t.rotation = window.transform.rotation; // get top left and bottom right coordinates Vector3 wtl = window.tl; Vector3 wbr = window.br; NearPlane plane = new NearPlane(); // construct nearPlane Vector3 nearCenter = t.position + t.forward * cam.nearClipPlane; Plane nearPlane = new Plane(-t.forward, nearCenter); // calculate top left for near plane float dist = 0; Vector3 direction = (wtl - t.position).normalized; Ray ray = new Ray(t.position, direction); nearPlane.Raycast(ray, out dist); Vector3 ntl = -(t.InverseTransformPoint(nearCenter) - t.InverseTransformPoint((t.position + direction * dist))); plane.left = ntl.x; plane.top = ntl.y; // calculate bottom right for near plane direction = (wbr - t.position).normalized; ray = new Ray(t.position, direction); nearPlane.Raycast(ray, out dist); Vector3 nbr = -(t.InverseTransformPoint(nearCenter) - t.InverseTransformPoint((t.position + direction * dist))); plane.right = nbr.x; plane.bottom = nbr.y; plane.near = cam.nearClipPlane; plane.far = cam.farClipPlane; Profiler.EndSample(); return plane; }