221 lines
7.4 KiB
C#
221 lines
7.4 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
|
|
namespace Beyond
|
|
{
|
|
|
|
[RequireComponent(typeof(Camera))]
|
|
[ExecuteAlways]
|
|
public class PortalCamera : MonoBehaviour
|
|
{
|
|
public GameObject target;
|
|
Camera mCam;
|
|
public Vector3 xVec = new Vector3(1, 0, 0);
|
|
public Vector3 yVec = new Vector3(0, 1, 0);
|
|
public Vector3 zVec = new Vector3(0, 0, -1);
|
|
MeshFilter mMesh;
|
|
Bounds bounds;
|
|
Vector4[] quadPoints = new Vector4[4];
|
|
Vector4[] camSpaceQuadPoints = new Vector4[4];
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
mCam = GetComponent<Camera>();
|
|
CalculateQuadPoints();
|
|
}
|
|
|
|
public float CalculateFOV()
|
|
{
|
|
float correction = 1f;
|
|
/*
|
|
if (targetQuad)
|
|
{
|
|
mCam.transform.LookAt(targetQuad.transform);
|
|
Vector3 forward = transform.InverseTransformDirection(targetQuad.transform.forward);
|
|
correction = -forward.x / forward.z;
|
|
}
|
|
*/
|
|
float zPlaneDist = 0f;
|
|
zPlaneDist = Vector3.Dot(-target.transform.forward, transform.position);
|
|
float fov = Mathf.Atan2(target.transform.localScale.x / correction, zPlaneDist) * Mathf.Rad2Deg * 2.0f;
|
|
float fov2 = Mathf.Atan2(target.transform.localScale.x, -transform.localPosition.z) * Mathf.Rad2Deg;
|
|
Debug.Log("FOV: " + fov);
|
|
return fov;
|
|
}
|
|
|
|
|
|
static public Matrix4x4 CalculateOffcenterProjectionMatrix(float near, float far, float left, float right, float top, float bottom)
|
|
{
|
|
Matrix4x4 m = Matrix4x4.identity;
|
|
float x = 2.0F * near / (right - left);
|
|
float y = 2.0F * near / (top - bottom);
|
|
float a = (right + left) / (right - left);
|
|
float b = (top + bottom) / (top - bottom);
|
|
float c = -(far + near) / (far - near);
|
|
float d = -(2.0F * far * near) / (far - near);
|
|
float e = -1.0F;
|
|
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;
|
|
|
|
}
|
|
|
|
static public Matrix4x4 CalculateProjectionMatrix(float near, float far, float aspect, float fov)
|
|
{
|
|
Matrix4x4 m = Matrix4x4.identity;
|
|
float left, right, top, bottom;
|
|
float scale = Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad) * near;
|
|
right = aspect * scale;
|
|
left = -right;
|
|
top = scale;
|
|
bottom = -top;
|
|
|
|
float x = 2.0F * near / (right - left);
|
|
float y = 2.0F * near / (top - bottom);
|
|
float a = (right + left) / (right - left);
|
|
float b = (top + bottom) / (top - bottom);
|
|
float c = -(far + near) / (far - near);
|
|
float d = -(2.0F * far * near) / (far - near);
|
|
float e = -1.0F;
|
|
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;
|
|
|
|
}
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
|
|
}
|
|
|
|
void CalculateQuadPoints()
|
|
{
|
|
Vector3 pos = target.transform.TransformPoint(bounds.center);
|
|
Vector3 right = target.transform.right * bounds.extents.x;
|
|
Vector3 up = target.transform.up * bounds.extents.y;
|
|
quadPoints[0] = pos + right + up;
|
|
quadPoints[1] = pos - right + up;
|
|
quadPoints[2] = pos - right - up;
|
|
quadPoints[3] = pos + right - up;
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
quadPoints[i].w = 1;
|
|
}
|
|
|
|
void CalculateCamSpacePoints()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
camSpaceQuadPoints[i] = mCam.worldToCameraMatrix * quadPoints[i];
|
|
camSpaceQuadPoints[i] /= camSpaceQuadPoints[i].w;
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
|
|
mCam = GetComponent<Camera>();
|
|
//Gizmos.DrawCube()
|
|
Vector4[] cubePoints = new Vector4[8];
|
|
Matrix4x4 mat = (mCam.projectionMatrix * mCam.worldToCameraMatrix).inverse;
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
cubePoints[i] = new Vector4(i % 2 == 0 ? -1f : 1f, (i / 2) % 2 == 0 ? -1f : 1f, (i / 4) % 2 == 0 ? -1f : 1f, 1f);
|
|
cubePoints[i] = mat * cubePoints[i];
|
|
cubePoints[i] /= cubePoints[i].w;
|
|
}
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawLine(cubePoints[0], cubePoints[1]);
|
|
Gizmos.DrawLine(cubePoints[2], cubePoints[3]);
|
|
Gizmos.DrawLine(cubePoints[0], cubePoints[2]);
|
|
Gizmos.DrawLine(cubePoints[1], cubePoints[3]);
|
|
|
|
Gizmos.DrawLine(cubePoints[4], cubePoints[5]);
|
|
Gizmos.DrawLine(cubePoints[6], cubePoints[7]);
|
|
Gizmos.DrawLine(cubePoints[4], cubePoints[6]);
|
|
Gizmos.DrawLine(cubePoints[5], cubePoints[7]);
|
|
|
|
Gizmos.DrawLine(cubePoints[0], cubePoints[4]);
|
|
Gizmos.DrawLine(cubePoints[1], cubePoints[5]);
|
|
Gizmos.DrawLine(cubePoints[2], cubePoints[6]);
|
|
Gizmos.DrawLine(cubePoints[3], cubePoints[7]);
|
|
|
|
CalculateQuadPoints();
|
|
|
|
CalculateCamSpacePoints();
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
Gizmos.DrawLine(camSpaceQuadPoints[i], camSpaceQuadPoints[(i + 1) % 4]);
|
|
|
|
|
|
// for (int i = 0; i < 4; i++)
|
|
// Gizmos.DrawLine(camSpaceQuadPoints[i], camSpaceQuadPoints[(i + 1) % 4]);
|
|
|
|
//Gizmos.DrawLine(cubePoints[3], cubePoints[0]);
|
|
}
|
|
// Update is called once per frame
|
|
void LateUpdate()
|
|
{
|
|
if (!target)
|
|
return;
|
|
|
|
|
|
if (!mMesh)
|
|
{
|
|
mMesh = target.GetComponent<MeshFilter>();
|
|
bounds = mMesh.mesh.bounds;
|
|
}
|
|
transform.up = Vector3.Cross(transform.right, transform.forward);
|
|
transform.forward = target.transform.forward;
|
|
transform.right = target.transform.right;
|
|
|
|
|
|
Vector3 forward = transform.InverseTransformDirection(target.transform.forward);
|
|
xVec.z = -forward.x / forward.z;
|
|
yVec.z = -forward.y / forward.z;
|
|
|
|
Matrix4x4 skewMat = Matrix4x4.identity;
|
|
skewMat.SetColumn(0, xVec);
|
|
skewMat.SetColumn(1, yVec);
|
|
skewMat.SetColumn(2, zVec);
|
|
|
|
mCam.worldToCameraMatrix = skewMat * transform.worldToLocalMatrix;
|
|
CalculateQuadPoints();
|
|
|
|
CalculateCamSpacePoints();
|
|
|
|
mCam.projectionMatrix = CalculateOffcenterProjectionMatrix(-camSpaceQuadPoints[0].z, 1000f, camSpaceQuadPoints[1].x, camSpaceQuadPoints[0].x, camSpaceQuadPoints[0].y, camSpaceQuadPoints[2].y);
|
|
|
|
}
|
|
}
|
|
} |